/ ECMAScript6

ECMAScript 6 之对象

简介的表达方式

const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}

// 等同于
const baz = {foo: foo};

直接将对象的值作为对象对应属性下的值。当然方法也是如此:

const o = {
  method() {
    return "Hello!";
  }
};

// 等同于

const o = {
  method: function() {
    return "Hello!";
  }
};

一个完整的例子

let birth = '2000/01/01';

const Person = {

  name: '张三',

  //等同于birth: birth
  birth,

  // 等同于hello: function ()...
  hello() { console.log('我的名字是', this.name); }

};

用处:

  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
//  }

对象与遍历的关系

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

属性的遍历

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

注: 上面的例子大多数来自 《ECMAScript 6入门》这本书。