# 1. 空值合并操作符 ??

  • 空值合并操作符(??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。
  • 与逻辑或操作符(||)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。
  • 如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如,'' 或 0)时。
const val1 = null ?? 'default string'; // 'default string'
const val2 = undefined ?? 'default string'; // 'default string'
const val3 = 123 ?? 'default string'; // 123
const val4 = 0 ?? 666; // 0
const val5 = '' ?? 666; // ''
const val6 = '' || 666; // 666

# 2. 可选链运算符 ?.

  • ?.运算符在运算过程中,首先从左到右执行,左侧的对象是否为null或undefined。
    如果是的,就不再往右边执行运算,而是返回undefined。
  • 一般用法
    (1) obj?.prop 对象属性
    (2) obj?.[expr] 对象属性
    (3) func?.(...args) 执行函数
const user = {
    name: '张三',
    children: { name: '李四', children: { name: '小明' } },
};
const name1 = user?.name;
const name2 = user?.children?.name;
const name3 = user?.children?.children?.name;
const name4 = user?.children?.children?.xxx;
console.log(name1); // '张三'
console.log(name2); // '李四'
console.log(name3); // '小明'
console.log(name4); // undefined

# 3. 函数默认参数处理

const getUser = (name='张三', age=23) => `名字是: ${name}, 年龄是: ${age}`
console.log(getUser()) // 名字是: 张三, 年龄是: 23
console.log(getUser('李四', 29)) // 名字是: 李四, 年龄是: 29

# 4. Object.hasOwn

  • Object.hasOwn返回一个布尔值(true/false),表示对象自身属性中是否具有对应的值(原型链上的属性不会读取)。
  • obj.hasOwnProperty可以过滤掉原型链上的属性,但在某些情况下,它还是不安全。。
  • in 不会过滤掉原型链上的属性。
Object.create(null).hasOwnProperty('name') // Uncaught TypeError: Object.create(...).hasOwnProperty is not a function

const object = { age: 24 }
Object.hasOwn(object, 'age') // true

const object2 = Object.create({ age: 24 })
Object.hasOwn(object2, 'age') // false  

const object3 = Object.create(null)
Object.hasOwn(object3, 'age') // false

# 5. 数字分隔符 _

const sixBillion = 6000000000 // ❌ 难以阅读
const sixBillion2 = 6000_000_000 // ✅ 更加易于阅读
console.log(sixBillion2) // 6000000000

const sum = 1000 + 6000_000_000
console.log(sum) // 6000001000

# 6. 大数计算 BigInt

JS中超过 Number.MAX_SAFE_INTEGER(9007199254740991) 的数字计算将是不安全的。

Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
Math.pow(2, 53) // 9007199254740992
Math.pow(2, 53) + 1 // 9007199254740992

BigInt(Math.pow(2, 53)) === BigInt(Math.pow(2, 53)) + BigInt(1) // false