对象的扩展
对象(object)是 JavaScript 最重要的数据结构。ES6 对它进行了重大升级
属性的简洁表示法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
let name = "iwen"
const user = {
name,
age:20
}
除了属性简写,方法也可以简写
const o = {
method() {
return "Hello!";
}
};
// 等同于
const o = {
method: function() {
return "Hello!";
}
};
这种写法用于函数的返回值,将会非常方便
function getPoint() {
const x = 1;
const y = 10;
return {x, y};
}
getPoint() // {x:1, y:10}
属性名表达式
ES6 允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内
let propKey = 'itxiaotong';
let obj = {
[propKey]: true,
['a' + 'bc']: 123
};
对象的扩展运算符
ES2018 将这个运算符引入了对象
let z = { a: 3, b: 4 };
let n = { ...z };
console.log(n);
{...{}, a: 1}
// { a: 1 }
实时效果反馈
1. 下列代码输出结果是什么:
let propKey = 'itbaizhan'; let obj = { [propKey]: true, ['a' + 'bc']: 123 }; console.log(obj.propKey);
A true
B 报错
C undefined
D propKey
对象的新增方法
Object.is()
ES5 比较两个值是否相等,只有两个运算符:相等运算符( == )和 严格相等运算符( === )。它们都有缺点,前者会自动转换数据类 型,后者的 NaN 不等于自身,以及 +0 等于 -0 。JavaScript 缺乏一种 运算,在所有环境中,只要两个值是一样的,它们就应该相等ES6 提出“Same-value equality”(同值相等)算法,用来解决这个 问题。 Object.is 就是部署这个算法的新方法。它用来比较两个值是否 严格相等,与严格比较运算符(===)的行为基本一致
Object.is('foo', 'foo')
// true
Object.is({}, {})
// false
不同之处只有两个:一是 +0 不等于 -0 ,二是 NaN 等于自身
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.assign()
Object.assign() 方法用于对象的合并
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
同名属性的替换
对于这种嵌套的对象,一旦遇到同名属性, Object.assign() 的处理方法是替换,而不是添加
const target = { a: "hello" }
const source = { a: "world" }
console.log(Object.assign(target, source));
数组的处理
Object.assign() 可以用来处理数组,但是会把数组视为对
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
Object.assign() 把数组视为属性名为 0、1、2 的对象,因此源数组的 0 号属性 4 覆盖了目标数组的 0 号属性 1
Object.keys(),Object.values(),Object.entries()
ES5 引入了 Object.keys 方法,返回一个数组,成员是参数对象自身的所有可遍历(enumerable)属性的键名
var obj = { name:"iwen",age:20 };
console.log(Object.keys(obj)); // ['name', 'age']
ES2017 引入了跟 Object.keys 配套的 Object.values 和 Object.entries ,作为遍历 一个对象的补充手段,供 for...of 循环使用
let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };
for (let key of keys(obj)) {
console.log(key); // 'a', 'b', 'c'
}
for (let value of values(obj)) {
console.log(value); // 1, 2, 3
}
for (let [key, value] of entries(obj)) {
console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}
实时效果反馈
1. 合并对象,可以使用下列那个方法:
A Object.is()
B Object.assign()
C Object.keys()
D Object.values()
运算符的扩展
指数运算符
ES2016 新增了一个指数运算符( ** )
2 ** 2 // 4
2 ** 3 // 8
这个运算符的一个特点是右结合,而不是常见的左结合。多个指数 运算符连用时,是从最右边开始计算的
// 相当于 2 ** (3 ** 2)
2 ** 3 ** 2
// 512
指数运算符可以与等号结合,形成一个新的赋值运算符( **= )
let a = 1.5;
a **= 2;
// 等同于 a = a * a;
let b = 4;
b **= 3;
// 等同于 b = b * b * b;
链判断运算符
编程实务中,如果读取对象内部的某个属性,往往需要判断一下, 属性的上层对象是否存在。比如,读取 message.body.user.firstName 这个属性,安全的写法是写成下面这样
// 错误的写法
const firstName = message.body.user.firstName || 'default';
// 正确的写法
const firstName = (message
&& message.body
&& message.body.user
&& message.body.user.firstName) || 'default';
这样的层层判断非常麻烦,因此 ES2020引入了“链判断运算符” (optional chaining operator) ?. ,简化上面的写法
const firstName = message?.body?.user?.firstName || 'default';
Null 判断运算符
读取参数的时候,如果某个参数的值是 null 或 undefined ,有时候需要 为它们指定默认值。常见做法是通过 || 运算符指定默认值。
function add(x,y){
x = x || 100;
y = y || 100;
console.log(x+y);
}
add(0,0); // 200
上面的三行代码都通过 || 运算符指定默认值,但是这样写是错的。 开发者的原意是,只要属性的值为 null 或 undefined ,默认值就会生效,但是属性的值如果为空字符串或 false 或 0 ,默认值也会生效
为了避免这种情况,ES2020 引入了一个新的 Null 判断运算符 ?? 。 它的行为类似 || ,但是只有运算符左侧的值为 null 或 undefined 时,才 会返回右侧的值。
function add(x,y){
x = x ?? 100;
y = y ?? 100;
console.log(x+y);
}
add(0,0);
逻辑赋值运算符
ES2021 引入了三个新的逻辑赋值运算符(logical assignment operators),将逻辑运算符与赋值运算符进行结合
// 或赋值运算符
x ||= y
// 等同于
x || (x = y)
// 与赋值运算符
x &&= y
// 等同于
x && (x = y)
// Null 赋值运算符
x ??= y
// 等同于
x ?? (x = y)
它们的一个用途是,为变量或属性设置默认值
// 老的写法
user.id = user.id || 1;
// 新的写法
user.id ||= 1;
user.id 属性如果不存在,则设为 1 ,新的写法比老的写法更紧凑一些
实时效果反馈
1. 下列代码运算结果是多少:
function add(x,y){ x = x ?? 100; y = y || 100; console.log(x+y); } add(0,0);
A 0
B 100
C 200
D 报错