├── 对象的新增方法
│ ├── Object.is()
│ │ └─ ES5 比较两个值是否相等,只有两个运算符:相等运算符(`==`)和严格相等运算符(`===`)。它们都有缺点,前者会自动转换数据类型,后者的`NaN`不等于自身,以及`+0`等于`-0`。JavaScript 缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。
│ │ └─ ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。`Object.is`就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
│ ├── Object.assign()
│ │ └─ 基本用法
│ │ └─ `Object.assign()`方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
│ │ └─ 如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果`undefined`和`null`不在首参数,就不会报错。
│ │ └─ 注意点
│ │ └─ `Object.assign()`方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
│ │ └─ 对于这种嵌套的对象,一旦遇到同名属性,`Object.assign()`的处理方法是替换,而不是添加。
│ │ └─ `Object.assign()`可以用来处理数组,但是会把数组视为对象。
│ │ └─ `Object.assign()`只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。
│ │ └─ 常见用途
│ │ └─ (1)为对象添加属性
│ │ └─ (2)为对象添加方法
│ │ └─ (3)克隆对象
│ │ └─ (4)合并多个对象
│ │ └─ (5)为属性指定默认值
│ ├── Object.getOwnPropertyDescriptors()
│ │ └─ ES5 的`Object.getOwnPropertyDescriptor()`方法会返回某个对象属性的描述对象(descriptor)。ES2017 引入了`Object.getOwnPropertyDescriptors()`方法,返回指定对象所有自身属性(非继承属性)的描述对象。
│ │ └─ `source`对象的`foo`属性的值是一个赋值函数,`Object.assign`方法将这个属性拷贝给`target1`对象,结果该属性的值变成了`undefined`。这是因为`Object.assign`方法总是拷贝一个属性的值,而不会拷贝它背后的赋值方法或取值方法。这时,`Object.getOwnPropertyDescriptors()`方法配合`Object.defineProperties()`方法,就可以实现正确拷贝。
│ ├── `__proto__`属性,Object.setPrototypeOf(),Object.getPrototypeOf()
│ │ └─ `__proto__`属性
│ │ └─ `__proto__`属性(前后各两个下划线),用来读取或设置当前对象的原型对象(prototype)。目前,所有浏览器(包括 IE11)都部署了这个属性。
│ │ └─ Object.setPrototypeOf()
│ │ └─ `Object.setPrototypeOf`方法的作用与`__proto__`相同,用来设置一个对象的原型对象(prototype),返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。
│ │ └─ Object.setPrototypeOf()
│ │ └─ 该方法与`Object.setPrototypeOf`方法配套,用于读取一个对象的原型对象。
│ ├── Object.keys(),Object.values(),Object.entries()
│ │ └─ Object.keys()
│ │ └─ `Object.keys`方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
│ │ └─ Object.values()
│ │ └─ `Object.values`方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
│ │ └─ Object.entries()
│ │ └─ `Object.entries()`方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
│ ├── Object.fromEntries()
│ │ └─ `Object.fromEntries()`方法是`Object.entries()`的逆操作,用于将一个键值对数组转为对象。
├── 运算符的扩展
│ ├── 指数运算符
│ │ └─ ES2016 新增了一个指数运算符(`**`) 2 ** 2
│ ├── 链判断运算符 `?.`
│ │ └─ const firstName = message?.body?.user?.firstName || 'default';
│ │ └─ myForm.checkValidity?.() === false 老式浏览器的表单对象可能没有`checkValidity()`这个方法,这时`?.`运算符就会返回`undefined`,判断语句就变成了`undefined === false`,所以就会跳过下面的代码。
│ │ └─ `?.`运算符,直接在链式调用的时候判断,左侧的对象是否为`null`或`undefined`。如果是的,就不再往下运算,而是返回`undefined`。
│ │ └─ (1)短路机制
│ │ └─ 本质上,`?.`运算符相当于一种短路机制,只要不满足条件,就不再往下执行。
│ │ └─ (2)括号的影响
│ │ └─ 如果属性链有圆括号,链判断运算符对圆括号外部没有影响,只对圆括号内部有影响。
│ │ └─ (3)报错场合
│ │ └─ 构造函数 ; 链判断运算符的右侧有模板字符串 ; 链判断运算符的左侧是 super ; 链运算符用于赋值运算符左侧
│ │ └─ (4)右侧不得为十进制数值
│ │ └─ 为了保证兼容以前的代码,允许`foo?.3:0`被解析成`foo ? .3 : 0`,因此规定如果`?.`后面紧跟一个十进制数字,那么`?.`不再被看成是一个完整的运算符,而会按照三元运算符进行处理,也就是说,那个小数点会归属于后面的十进制数字,形成一个小数。
│ ├── Null 判断运算符 `??`
│ │ └─ const headerText = response.settings.headerText ?? 'Hello, world!';
│ │ └─ 读取对象属性的时候,如果某个属性的值是`null`或`undefined`,有时候需要为它们指定默认值。常见做法是通过`||`运算符指定默认值。
│ │ └─ `??`本质上是逻辑运算,它与其他两个逻辑运算符`&&`和`||`有一个优先级问题 必须加入表明优先级的括号。
│ ├── 逻辑赋值运算符 `||=`、`&&=`、`??=`
│ │ └─ 这三个运算符`||=`、`&&=`、`??=`相当于先进行逻辑运算,然后根据运算结果,再视情况进行赋值运算。