逻辑运算符 #

一、运算符概述 #

逻辑运算符用于布尔逻辑运算,常用于条件判断和流程控制。Deno支持逻辑与、逻辑或、逻辑非以及空值合并运算符。

二、逻辑非(!) #

2.1 基本用法 #

typescript
console.log(!true); // false
console.log(!false); // true
console.log(!0); // true
console.log(!1); // false
console.log(!""); // true
console.log(!"hello"); // false
console.log(!null); // true
console.log(!undefined); // true

2.2 双重否定 #

将任意值转换为布尔值:

typescript
console.log(!!1); // true
console.log(!!0); // false
console.log(!!"hello"); // true
console.log(!!""); // false
console.log(!!null); // false
console.log(!!undefined); // false
console.log(!!{}); // true
console.log(!![]); // true

2.3 实际应用 #

typescript
const items: string[] = [];

// 检查数组是否为空
if (!items.length) {
  console.log("数组为空");
}

// 检查变量是否有值
let value: string | null = null;
if (!value) {
  console.log("值为空");
}

三、逻辑与(&&) #

3.1 基本用法 #

typescript
console.log(true && true); // true
console.log(true && false); // false
console.log(false && true); // false
console.log(false && false); // false

3.2 短路求值 #

如果第一个操作数为假值,则不会计算第二个操作数:

typescript
let count = 0;

false && count++;
console.log(count); // 0 (count++未执行)

true && count++;
console.log(count); // 1 (count++执行)

3.3 返回值 #

返回第一个假值或最后一个值:

typescript
console.log(1 && 2); // 2
console.log(0 && 2); // 0
console.log("hello" && "world"); // "world"
console.log("" && "world"); // ""
console.log(null && "world"); // null
console.log(undefined && "world"); // undefined

3.4 实际应用 #

typescript
// 条件执行
const user = { name: "Alice", admin: true };

user.admin && console.log("管理员权限");

// 可选属性访问
interface Config {
  server?: {
    port?: number;
  };
}

const config: Config = {};

const port = config.server && config.server.port;
console.log(port); // undefined

// 使用可选链更简洁
const port2 = config.server?.port;
console.log(port2); // undefined

四、逻辑或(||) #

4.1 基本用法 #

typescript
console.log(true || true); // true
console.log(true || false); // true
console.log(false || true); // true
console.log(false || false); // false

4.2 短路求值 #

如果第一个操作数为真值,则不会计算第二个操作数:

typescript
let count = 0;

true || count++;
console.log(count); // 0 (count++未执行)

false || count++;
console.log(count); // 1 (count++执行)

4.3 返回值 #

返回第一个真值或最后一个值:

typescript
console.log(1 || 2); // 1
console.log(0 || 2); // 2
console.log("hello" || "world"); // "hello"
console.log("" || "world"); // "world"
console.log(null || "default"); // "default"
console.log(undefined || "default"); // "default"

4.4 实际应用 #

typescript
// 默认值
function greet(name: string) {
  const displayName = name || "Guest";
  console.log(`Hello, ${displayName}!`);
}

greet("Alice"); // Hello, Alice!
greet(""); // Hello, Guest!

// 配置默认值
interface Options {
  timeout?: number;
  retries?: number;
}

function fetchData(options: Options = {}) {
  const timeout = options.timeout || 5000;
  const retries = options.retries || 3;
  
  console.log(`Timeout: ${timeout}ms, Retries: ${retries}`);
}

fetchData(); // Timeout: 5000ms, Retries: 3
fetchData({ timeout: 10000 }); // Timeout: 10000ms, Retries: 3

五、空值合并(??) #

5.1 基本用法 #

只有当左侧为 nullundefined 时才返回右侧:

typescript
console.log(null ?? "default"); // "default"
console.log(undefined ?? "default"); // "default"
console.log(0 ?? "default"); // 0
console.log("" ?? "default"); // ""
console.log(false ?? "default"); // false
console.log(NaN ?? "default"); // NaN

5.2 与||的区别 #

typescript
// || 会将假值视为需要默认值
console.log(0 || "default"); // "default"
console.log("" || "default"); // "default"
console.log(false || "default"); // "default"

// ?? 只检查null和undefined
console.log(0 ?? "default"); // 0
console.log("" ?? "default"); // ""
console.log(false ?? "default"); // false

5.3 实际应用 #

typescript
interface Config {
  port?: number;
  host?: string;
  debug?: boolean;
}

function startServer(config: Config) {
  const port = config.port ?? 3000;
  const host = config.host ?? "localhost";
  const debug = config.debug ?? false;
  
  console.log(`Starting server at ${host}:${port}, debug: ${debug}`);
}

startServer({}); // Starting server at localhost:3000, debug: false
startServer({ port: 8080, debug: true }); // Starting server at localhost:8080, debug: true
startServer({ port: 0 }); // Starting server at localhost:0, debug: false

六、可选链(?.) #

6.1 基本用法 #

安全地访问深层嵌套属性:

typescript
interface User {
  name: string;
  address?: {
    city?: string;
    country?: string;
  };
}

const user: User = { name: "Alice" };

// 传统方式
const city = user.address && user.address.city;

// 可选链
const city2 = user.address?.city;
console.log(city2); // undefined

// 多层可选链
const country = user.address?.country?.toUpperCase();
console.log(country); // undefined

6.2 函数调用 #

typescript
interface Options {
  callback?: () => void;
}

function execute(options: Options) {
  options.callback?.();
}

execute({ callback: () => console.log("Called!") }); // Called!
execute({}); // 无输出,不报错

6.3 数组访问 #

typescript
const arr: (number | undefined)[] = [1, undefined, 3];

console.log(arr[0]?.toFixed(2)); // "1.00"
console.log(arr[1]?.toFixed(2)); // undefined
console.log(arr[10]?.toFixed(2)); // undefined

七、逻辑赋值运算符 #

7.1 逻辑与赋值(&&=) #

只有当左侧为真值时才赋值:

typescript
let a = 10;
a &&= 20;
console.log(a); // 20

let b = 0;
b &&= 20;
console.log(b); // 0 (未赋值)

// 等价于
// a = a && 20;

7.2 逻辑或赋值(||=) #

只有当左侧为假值时才赋值:

typescript
let a = 0;
a ||= 10;
console.log(a); // 10

let b = 5;
b ||= 10;
console.log(b); // 5 (未赋值)

// 等价于
// a = a || 10;

7.3 空值合并赋值(??=) #

只有当左侧为 nullundefined 时才赋值:

typescript
let a: number | null = null;
a ??= 10;
console.log(a); // 10

let b = 0;
b ??= 10;
console.log(b); // 0 (未赋值,因为0不是null/undefined)

let c: string | undefined = undefined;
c ??= "default";
console.log(c); // "default"

7.4 实际应用 #

typescript
interface Cache {
  [key: string]: string;
}

const cache: Cache = {};

function getData(key: string): string {
  cache[key] ??= expensiveOperation(key);
  return cache[key];
}

function expensiveOperation(key: string): string {
  console.log(`Computing for ${key}...`);
  return `value-${key}`;
}

console.log(getData("a")); // Computing for a... value-a
console.log(getData("a")); // value-a (使用缓存)

八、优先级 #

8.1 优先级顺序 #

从高到低:

  1. ! (逻辑非)
  2. ?? (空值合并)
  3. && (逻辑与)
  4. || (逻辑或)

8.2 示例 #

typescript
// 逻辑非优先级最高
console.log(!false && true); // true

// 逻辑与优先于逻辑或
console.log(true || false && false); // true
console.log((true || false) && false); // false

// 空值合并与逻辑运算符不能混用(需要括号)
// console.log(null ?? undefined || "default"); // 语法错误
console.log((null ?? undefined) || "default"); // "default"
console.log(null ?? (undefined || "default")); // "default"

九、真值和假值 #

9.1 假值(Falsy) #

typescript
const falsyValues = [
  false,
  0,
  -0,
  0n,
  "",
  null,
  undefined,
  NaN
];

falsyValues.forEach(value => {
  console.log(Boolean(value)); // 全部为false
});

9.2 真值(Truthy) #

除了假值以外的所有值:

typescript
const truthyValues = [
  true,
  1,
  -1,
  "hello",
  [],
  {},
  function() {},
  Infinity,
  -Infinity
];

truthyValues.forEach(value => {
  console.log(Boolean(value)); // 全部为true
});

十、实际应用场景 #

10.1 条件渲染 #

typescript
interface User {
  name: string;
  avatar?: string;
}

function renderUser(user: User | null) {
  return user && `
    <div>
      <img src="${user.avatar ?? "/default-avatar.png"}" />
      <span>${user.name}</span>
    </div>
  `;
}

console.log(renderUser(null)); // null
console.log(renderUser({ name: "Alice" })); // <div>...</div>

10.2 配置合并 #

typescript
interface Config {
  host?: string;
  port?: number;
  timeout?: number;
  debug?: boolean;
}

const defaultConfig: Required<Config> = {
  host: "localhost",
  port: 3000,
  timeout: 5000,
  debug: false
};

function createConfig(userConfig: Config = {}): Required<Config> {
  return {
    host: userConfig.host ?? defaultConfig.host,
    port: userConfig.port ?? defaultConfig.port,
    timeout: userConfig.timeout ?? defaultConfig.timeout,
    debug: userConfig.debug ?? defaultConfig.debug
  };
}

console.log(createConfig({ port: 8080 }));
// { host: "localhost", port: 8080, timeout: 5000, debug: false }

10.3 防御性编程 #

typescript
interface APIResponse {
  data?: {
    users?: Array<{
      name: string;
      email?: string;
    }>;
  };
  error?: string;
}

function getUsers(response: APIResponse): string[] {
  if (response.error) {
    throw new Error(response.error);
  }
  
  return response.data?.users?.map(u => u.name) ?? [];
}

const response: APIResponse = {
  data: {
    users: [
      { name: "Alice", email: "alice@example.com" },
      { name: "Bob" }
    ]
  }
};

console.log(getUsers(response)); // ["Alice", "Bob"]

十一、总结 #

本章学习了:

  • 逻辑非(!)和双重否定(!!)
  • 逻辑与(&&)和短路求值
  • 逻辑或(||)和默认值
  • 空值合并(??)
  • 可选链(?.)
  • 逻辑赋值运算符(&&=、||=、??=)
  • 运算符优先级
  • 真值和假值

下一章,我们将学习位运算符。

最后更新:2026-03-28