// 属性简写 var foo = 'bar'; var baz = {foo}; baz // {foo: "bar"} // 等同于 var baz = {foo: foo}; // 方法简写 function f(x, y) { return {x, y}; } // 等同于 function f(x, y) { return {x: x, y: y}; } f(1, 2) // Object {x: 1, y: 2}
合并对象:
Object.assign(target, [...source]);
将 source 中所有和枚举的属性复制到 target。
多个 source 对象有同名属性,后面的覆盖前面的。
var target = { a: 1 }; var source1 = { b: 2 }; var source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
注意一点,该命令执行的是浅克隆,如果 source 中有属性是对象,target 中会复制该对象的引用。
常用于给对象添加属性和方法(如给构造函数的原型添加方法),克隆、合并对象等。
获取对象自身的值或键值对(做为Object.keys(obj)的补充不包括不可枚举的):
Object.keys(obj)返回 obj 自身所有可枚举属性的值组成的数组。
Object.entries(obj)返回 obj 自身所有可枚举键值对数组组成的数组,例如:
var obj = { foo: 'bar', baz: 42 }; Object.entries(obj) // [ ["foo", "bar"], ["baz", 42] ] // 可用于将对象转为 Map 结构 var obj = { foo: 'bar', baz: 42 }; var map = new Map(Object.entries(obj)); map // Map { foo: "bar", baz: 42 }
拓展运算符:
取出对象所有可历遍属性,举例:
let z = { a: 3, b: 4 }; let n = { ...z }; n // { a: 3, b: 4 } // 可代替 Object.assign() let ab = { ...a, ...b }; // 等同于 let ab = Object.assign({}, a, b);
可用于解构赋值中最后一个参数:
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; x // 1 y // 2 z // { a: 3, b: 4 } // 可以这样理解,把 z 拆开以后就等于后面对象未被分配出去的键值对。
Null 传导运算符:
const firstName = message?.body?.user?.firstName || 'default'; // 代替 const firstName = (message && message.body && message.body.user && message.body.user.firstName) || 'default';
class:
ES6 引入了 class 关键字,但并没有改变对象基于原型继承的原理,只是一个语法糖,让他长得像传统面向对象语言而已。
以下两个写法完全等价:
function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; //定义类 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } // 类中定义的方法就是在原型上
有两点区别, class 中定义的方法是不可枚举的,class 必须通过 new 调用不能直接运行。
class 不存在变量提升,使用要在定义之后。
class 中的方法前加 static 关键字定义静态方法,只能通过 class 直接调用不能被实例继承。
如果静态方法包含 this 关键字,这个 this 指的是 class,而不是实例。注意下面代码:
class Foo { static bar () { this.baz(); } static baz () { console.log('hello'); } baz () { console.log('world'); } } Foo.bar() // hello
父类的静态方法,可以被子类继承,目前 class 内部无法定义静态属性。
设置静态属性与实例属性新提案:
class 的实例属性可以用等式,写入类的定义之中。
静态属性直接前面加 static 即可。
class MyClass { myProp = 42; static myStaticProp = 42; }
class 的继承:
class 通过 extends 实现继承,注意 super 关键字
class ColorPoint extends Point { constructor(x, y, color) { super(x, y); // 调用父类的constructor(x, y) this.color = color; } toString() { return this.color + ' ' + super.toString(); // 调用父类的toString() } }
extends 可以继承其他类或任何有 prototype 属性的函数。
super 会从父类获取各路信息绑定到子类的 this。
子类自己没有 this 对象,要先继承父类的实例对象然后再进行加工,所以要在 constructor 里调用 super 继承 this 对象后才能使用 this。