容易被忽视的JavaScript超实用新特性

382 阅读3分钟

js图片.jpeg

容易被忽视的JavaScript超实用新特性

这是我参与新手入门的第1篇文章

一.可选链操作符( ?. )

你可能碰到过这样的情形:当需要访问嵌套在对象内部好几层的属性时,可能会得到这种错误Cannot read property 'xx' of undefined,然后你就要修改你的代码来处理属性链中每一个可能的undefined对象,比如:

let nestedProp = obj.first && obj.first.second;

为了避免报错,在访问obj.first.second之前,要保证 obj.first 的值既不是 null,也不是 undefined。如果只是直接访问 obj.first.second,而不对 obj.first 进行校验,则有可能抛出错误。

有了可选链操作符(?.),在访问 obj.first.second 之前,不再需要明确地校验 obj.first 的状态,再并用短路计算获取最终结果:

let nestedProp = obj.first?.second;

通过使用 ?. 操作符取代 . 操作符,JavaScript 会在尝试访问 obj.first.second 之前,先隐式地检查并确定 obj.first 既不是 null 也不是 undefined。如果obj.first 是 null 或者 undefined,表达式将会短路计算直接返回 undefined

二.空值合并操作符(??)

我们在开发过程中,经常会遇到这样场景:变量如果是空值,则就使用默认值,我们是这样实现的:

let c = a ? a : b // 方式1 
let c = a || b // 方式2 

这两种方式有个明显的弊端,由于 || 是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值(0, '', NaN, null, undefined)都不会被返回。这导致如果你使用0,''或NaN作为有效值,就会出现不可预料的后果。比如:

let count = 0;
let text = "";

let qty = count || 42;
let message = text || "hi!";
console.log(qty);     // 42,而不是 0
console.log(message); // "hi!",而不是 ""

空值合并操作符可以避免这种陷阱,其只在第一个操作数为null 或 undefined 时(而不是其它假值)返回第二个操作数:

let c = a ?? b; 
// 等价于let c = a !== undefined && a !== null ? a : b; 

const x = null; 
const y = x ?? 500; 
console.log(y); // 500 
const n = 0 
const m = n ?? 9000; 
console.log(m) // 0 

三.类的私有属性(#)

最新提案之一是在类中添加私有属性的方法。我们将使用 # 符号表示类的私有属性。这样就不需要使用闭包来隐藏不想暴露给外界的私有属性。

class Counter { 
#x = 0; #increment() { 
  this.#x++; 
} 
​ 
onClick() { 
  this.#increment(); 
} 
} 
​ 
const c = new Counter(); 
c.onClick(); // 正常 
c.#increment(); // 报错

为什么引用属性时需要符号#?

1.我们需要允许公有属性和私有属性同名,因此不能采用过去的传统方式去访问一个私有属性。

2.在 JavaScript 中可以采用 this.field 或者 this['field'] 的方式引用公有属性。而由于私有属性是静态的(不能动态添加),它不能支持第二种引用方式。这可能会导致语法上的混乱。

3.会承担额外的检查“代价”。

总之,我们需要使用符号#来标识私有属性,而使用其它方式会造成不可预期的行为和结果,并带来巨大的性能问题。

私有属性对语言来说是一个非常好的补充。