2021.04.27(链判断运算符、Null 判断运算符 11.对象的新增方法 Object.is()、Object.assign())

链判断运算符

ES2020 引入了“链判断运算符”(optional chaining
operator) ?.

 

1.  const firstName = message?.body?.user?.firstName || 'default';
2.  const fooValue = myForm.querySelector('input[name=foo]')?.value

 

链判断运算符有三种用法。
obj?.prop  // 对象属性
obj?.[expr]  // 同上
func?.(...args)  // 函数或对象方法的调用

下面是判断对象方法是否存在,如果存在就立即执行的例子。

1.  iterator.return?.()

上面代码中, iterator.return  如果有定义,就会调用该方法,否则直接返回 undefined  。

Null 判断运算符

ES2020 引入了一个新的 Null 判断运算符 ??  。它的行为类似 ||  ,但是只
有运算符左侧的值为 null  或 undefined  时,才会返回右侧的值。

1.  const headerText = response.settings.headerText ?? 'Hello, world!';
2.  const animationDuration = response.settings.animationDuration ?? 300;
3.  const showSplashScreen = response.settings.showSplashScreen ?? true;

上面代码中,默认值只有在属性值为 null  或 undefined  时,才会生效。
这个运算符的一个目的,就是跟链判断运算符 ?.  配合使用,为 null  或 undefined  的值设置默
认值。

1.  const animationDuration = response.settings?.animationDuration ?? 300;

上面代码中, response.settings  如果是 null  或 undefined  ,就会返回默认值300。

??  有一个运算优先级问题,它与 &&  和 ||  的优先级孰高孰低。现在的规则是,如果多个逻辑运
算符一起使用,必须用括号表明优先级,否则会报错。

1.  // 报错
2.  lhs && middle ?? rhs
3.  lhs ?? middle && rhs
4.  lhs || middle ?? rhs
5.  lhs ?? middle || rhs

上面四个表达式都会报错,必须加入表明优先级的括号。

1.  (lhs && middle) ?? rhs;
2.  lhs && (middle ?? rhs);
3.
4.  (lhs ?? middle) && rhs;
5.  lhs ?? (middle && rhs);
6.
7.  (lhs || middle) ?? rhs;
8.  lhs || (middle ?? rhs);
9.
10.  (lhs ?? middle) || rhs;
11.  lhs ?? (middle || rhs);

Object.is()

ES5 比较两个值是否相等,只有两个运算符:相等运算符( ==  )和严格相等运算符( ===  )。
它们都有缺点,前者会自动转换数据类型,后者的 NaN  不等于自身,以及 +0  等于 -0  。
JavaScript 缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。

ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。 Object.is  就是部
署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

1.  Object.is('foo', 'foo')
2.  // true
3.  Object.is({}, {})
4.  // false

不同之处只有两个:一是 +0  不等于 -0  ,二是 NaN  等于自身。

1.  +0 === -0 //true
2.  NaN === NaN // false
3.
4.  Object.is(+0, -0) // false
5.  Object.is(NaN, NaN) // true

ES5 可以通过下面的代码,部署 Object.is  。

1.  Object.defineProperty(Object, 'is', {
2.  value: function(x, y) {
3.  if (x === y) {
4.  // 针对+0 不等于 -0的情况
5.  return x !== 0 || 1 / x === 1 / y;
6.  }
7.  // 针对NaN的情况
8.  return x !== x && y !== y;
9.  },
10.  configurable: true,
11.  enumerable: false,
12.  writable: true
13.  });

Object.assign()

Object.assign  方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象
(target)。

1.  const target = { a: 1 };
2.
3.  const source1 = { b: 2 };
4.  const source2 = { c: 3 };
5.
6.  Object.assign(target, source1, source2);
7.  target // {a:1, b:2, c:3}

Object.assign  方法的第一个参数是目标对象,后面的参数都是源对象。
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属
性。

1.  const target = { a: 1, b: 1 };
2.
3.  const source1 = { b: 2, c: 2 };
4.  const source2 = { c: 3 };
5.
6.  Object.assign(target, source1, source2);
7.  target // {a:1, b:2, c:3}

如果只有一个参数, Object.assign  会直接返回该参数。

1.  const obj = {a: 1};
2.  Object.assign(obj) === obj // true

如果该参数不是对象,则会先转成对象,然后返回。

1.  typeof Object.assign(2) // "object"

由于 undefined  和 null  无法转成对象,所以如果它们作为参数,就会报错。

1.  Object.assign(undefined) // 报错
2.  Object.assign(null) // 报错

如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转
成对象,如果无法转成对象,就会跳过。这意味着,如果 undefined  和 null  不在首参数,就不会
报错。

1.  let obj = {a: 1};
2.  Object.assign(obj, undefined) === obj // true
3.  Object.assign(obj, null) === obj // true

其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形
式,拷贝入目标对象,其他值都不会产生效果。

数组的处理

Object.assign  可以用来处理数组,但是会把数组视为对象。

1.  Object.assign([1, 2, 3], [4, 5])
2.  // [4, 5, 3]

上面代码中, Object.assign  把数组视为属性名为 0、1、2 的对象,因此源数组的 0 号属
性 4  覆盖了目标数组的 0 号属性 1  。

 

2021-04-28  10:07:24

 

上一篇:【二分查找】详细图解


下一篇:选第k小元素:特定分治策略