ES6 对象

简洁的表达方式

  • 直接在对象下写属性
const foo = 'bar';
const baz = { foo };
baz                         // {foo: "bar"}

// 等同于
const baz = { foo: foo };
  • 可以在对象下直接写方法
const o = {
    method() {
        return "Hello!";
    }
}

// 等同于
const o = {
    method: function () {
        return "Hello!";
    }
}

简单使用:

  1. 函数的返回值
  2. CommonJS 模块输出一组变量
// 直接输出变量
function getPoint() {
    const x = 1;
    const y = 10;
    return { x, y };
}

getPoint();             // {x:1, y:10}

// CommonJS 的导出
let ms = {};

function getItem (key) {
    return key in ms ? ms[key] : null;
}

module.exports = { getItem };

属性名表达式

ES5 中定义对象的属性,有以下两种形式:

// 方法一:直接命名
obj.foo = true;

// 方法二:使用变量
obj['a' + 'bc'] = 123;

如果直接实例化的对象,在 ES5 中只能用方法一定义属性。

var obj = {
    foo: true,
    abc: 123
};

而在 ES6 中直接实例化的对象,也能使用方法二了。

let propKey = 'foo';

let obj = {
    [propKey]: true,
    ['a' + 'bc']: 123
};

Object.is

效果基本与 === 一致,仅仅有两点区别:

+0 === -0                   // true
NaN === NaN                 // false

Object.is(+0, -0)           // false
Object.is(NaN, NaN)         // true

Object.assign()

对象的合并,仅仅执行浅拷贝。将之后的对象下的属性链接到第一个对象下。注意是链接,所以是引用赋值。

Object.assign 拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性( enumerable: false )。

const target = { a: 1, b: 1 };

const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target              // {a: 1, b: 2, c: 3}

注:

  1. 浅拷贝。
  2. 同名属性替换。
  3. 把数组当做普通对象,也就是数组的索引会被认为是对象下的 key
  4. 对于函数的处理:会直接取函数的返回值。
  5. 永远都是值拷贝,所以不能正确处理用 definePropertie(s) 添加的数据。

可枚举性

通过 getOwnPropertyDescriptor 方法获取对象下,对应属性的描述信息。

let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo');
//  {
//    value: 123,
//    writable: true,
//    enumerable: true,
//    configurable: true
//  }

四个会忽略 enumerablefalse 的属性的操作

  • for...in: 遍历对象自身和继承的可枚举属性
  • Object.keys(): 返回对象自身的所有可枚举属性的键名
  • JSON.stringify(): 串行化对象自身的可枚举属性
  • Object.assign(): 仅拷贝对象自身的可枚举属性

属性的遍历

  • for...in: 遍历对象自身和继承的可枚举属性(不含 Symbol 属性)。
  • Object.keys(obj): 返回数组,仅包含对象自身属性(不含 Symbol 属性)的键名。
  • Reflect.ownKeys(obj): 返回数组,包含对象自身的所有键名(包含 Symbol 和不可枚举属性)。
  • Object.getOwnPropertyNames(obj): 返回数组,包含对象自身所有属性(不含 Symbol 属性,但包含不可枚举属性))的键名。
  • Object.getOwnPropertySymbol(obj): 返回数组,包含对象所有 Symbol 属性的键名。

遍历顺序

  • 数字升序
  • 字符串按加入时间升序
  • Symbol 按加入时间升序

原型链

// es5 的写法
const obj = {
  method: function() { ... }
};
obj.__proto__ = someOtherObj;

// es6 的写法
var obj = Object.create(someOtherObj);
obj.method = function() { ... };

ES6 规范了原型链的使用以及创建,ES5 中直接使用 __proto__ 来实现原型链,在 ES6 中,使用 create/getPrototypeOf/setPrototypeOf 来实现原型,并且 __proto__ 应该仅仅存在于浏览器上,所以之后应该用 ES6 的方式实现原型。

3个对象遍历器

Object.keysObject.valuesObject.entries,分别获取到对象的键名、键值和键值对,供 for...of 使用。

成员是参数对象自身的(不含继承的)所有可枚举(enumerable)属性的键名。

对象的扩展运算符

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x                   // 1
y                   // 2
z                   // { a: 3, b: 4 }

和数组类似, ... 运算符也只能出现在最后。

let z = { a: 3, b: 4 };
let n = { ...z };
n                   // { a: 3, b: 4 }