1
主要知识点有对象类别、属性速记法、方法简写、需计算属性名、Object.is()方法、Object.assign()方法、可允许重复的属性、自有属性的枚举顺序、Object.setPrototypeOf()方法、super引用、方法定义
图片描述

《深入理解ES6》笔记 目录

对象类别

  • 普通对象:拥有 JS 对象所有默认的内部行为。
  • 奇异对象:其内部行为在某些方面有别于默认行为。
  • 标准对象:在 ES6 中被定义的对象,例如 Array 、 Date ,等等。标准对象可以是普通的,也可以是奇异的。
  • 内置对象:在脚本开始运行时由 JS 运行环境提供的对象。所有的标准对象都是内置对象。

对象字面量语法的扩展

属性初始化器的速记法

属性初始化器的速记法可以用来消除属性名和本地变量的重复情况,可以使用作用域内的变量值赋值给同名属性:

ES5 及更早版本中:

function createPerson(name, age) {
    return {
        name: name,
        age: age
    };
}

ES6简写:

function createPerson(name, age) {
    return {
        name,
        age
    };
}

方法简写

在对象字面量的写法中,为一个对象添加一个方法,需要指定对象的属性以及具体的函数声明。ES6提供了一种方法简写语法,通过省略function关键字,能够让为对象添加方法的语法更加简洁。
ES5中的写法:

var person = {
    name: "Nicholas",
    sayName: function() {
        console.log(this.name);
    }
};

ES6简写语法:

var person = {
    name: "Nicholas",
    sayName() {
        console.log(this.name);
    }
};

需计算属性名

需计算属性名规则允许对象字面量中属性名是变量、字符串字面量或者由变量计算而得的,具体写法是通过方括号[]包含属性名。

var lastName = "last name";
var person = {
    "first name": "Nicholas",
    [lastName]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person[lastName]); // "Zakas"

var suffix = " name";
var person = {
    ["first" + suffix]: "Nicholas",
    ["last" + suffix]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person["last name"]); // "Zakas"

const id = 5
const obj = {
  [`my-${id}`]: id
}
console.log(obj['my-5']) // 5

新的方法:Object.is()和Object.assign()

Object.is() 方法

JS中比较两个值是否相同的时候会使用严格等于运算符===,但是,使用严格运算符式,+0和-0会认为这两者是相等的,而NaN===NaN是不相等的,使用Object.is()方法来判断这两者情况与使用严格相等符会有所不同,其他情况和使用严格相等运算符基本一致;

console.log(+0 == -0); // true
console.log(+0 === -0); // true
console.log(Object.is(+0, -0)); // false
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
console.log(5 == 5); // true
console.log(5 == "5"); // true
console.log(5 === 5); // true
console.log(5 === "5"); // false
console.log(Object.is(5, 5)); // true
console.log(Object.is(5, "5")); // false

Object.assign() 方法

混入( Mixin )是在 JS 中组合对象时最流行的模式。在一次混入中,一个对象会从另一个对象中接收属性与方法。
下面是一个mixin方法的实现,这个方法实现的是浅拷贝。将b对象的属性拷贝到了a对象,合并成一个新的对象。

//mixin不只有这一种实现方法。
function mixin(receiver, supplier) {
  Object.keys(supplier).forEach((key) => {
    receiver[key] = supplier[key]
  })
  return receiver
}

let a = {name: 'sb'};
let b = {
  c: {
    d: 5
    }
  }
console.log(mixin(a, b)) // {"name":"sb","c":{"d":5}}

写这样一个mixin方法是不是很烦,而且每个项目都得引入这个方法,现在,ES6给我们提供了一个现成的方法Object.assign()来做mixin的事情。

假设要实现上面的mixin方法,你只需要给Object.assign()传入参数即可。

console.log(Object.assign(a, b))// {"name":"sb","c":{"d":5}}

重复的对象字面量属性

ES5 严格模式为重复的对象字面量属性引入了一个检查,若找到重复的属性名,就会抛出错误。

"use strict";
var person = {
    name: "Nicholas",
    name: "Greg" // 在 ES5 严格模式中是语法错误
};

ES6 移除了重复属性的检查,严格模式与非严格模式都不再检查重复的属性。当存在重复属性时,排在后面的属性的值会成为该属性的实际值:

"use strict";
var person = {
    name: "Nicholas",
    name: "Greg" // 在 ES6 严格模式中不会出错
};
console.log(person.name); // "Greg"

自有属性的枚举顺序

ES5 并没有定义对象属性的枚举顺序,而是把该问题留给了 JS 引擎厂商。而 ES6 则严格定义了对象自有属性在被枚举时返回的顺序。这对 Object.getOwnPropertyNames() 与Reflect.ownKeys)如何返回属性造成了影响,还同样影响了Object.assign() 处理属性的顺序。
自有属性枚举时基本顺序如下:

  1. 所有的数字类型键,按升序排列。
  2. 所有的字符串类型键,按被添加到对象的顺序排列。
  3. 所有的符号类型(详见第六章)键,也按添加顺序排列。
const state = {
  id: 1,
  5: 5,
  name: "eryue",
  3: 3
}

Object.getOwnPropertyNames(state) 
//["3","5","id","name"] 枚举key

Object.assign(state, null)
//{"3":3,"5":5,"id":1,"name":"eryue"} 
for-in 循环的枚举顺序仍未被明确规定,因为并非所有的 JS 引擎都采用相同的方式。而 Object.keys() 和 JSON.stringify() 也使用了与 for-in 一样的枚举顺序。

更强大的原型

一般来说,对象的原型会在通过构造器或 Object.create() 方法创建该对象时被指定。
ES5 添加了 Object.getPrototypeOf() 方法来从任意指定对象中获取其原型;
缺少在初始化之后更改对象原型的标准方法。

修改对象的原型

ES6 通过添加 Object.setPrototypeOf() 方法而改变了这种假定,此方法允许你修改任意指定对象的原型。它接受两个参数:需要被修改原型的对象,以及将会成为前者原型的对象

let person = {
    getGreeting() {
        return "Hello";
    }
};
let dog = {
    getGreeting() {
        return "Woof";
    }
};
// 原型为 person
let friend = Object.create(person);
console.log(friend.getGreeting()); // "Hello"
console.log(Object.getPrototypeOf(friend) === person); // true
// 将原型设置为 dog
Object.setPrototypeOf(friend, dog);
console.log(friend.getGreeting()); // "Woof"
console.log(Object.getPrototypeOf(friend) === dog); // true

使用 super 引用的简单原型访问

能够使用super引用,来访问原型中的方法:

const proto = {
  foo: 'hello'
};

const obj = {
  foo: 'world',
  find() {
    return super.foo;
  }
};

Object.setPrototypeOf(obj, proto);
obj.find() // "hello"

注意,super关键字表示原型对象时,只能用在对象的简写方法之中,用在其他地方都会报错。

// 报错
const obj = {
  foo: super.foo
}

// 报错
const obj = {
  foo: () => super.foo
}

// 报错
const obj = {
  foo: function () {
    return super.foo
  }
}

javaScript 引擎内部,super.foo等同于Object.getPrototypeOf(this).foo(属性)或Object.getPrototypeOf(this).foo.call(this)(方法)。

const proto = {
  x: 'hello',
  foo() {
    console.log(this.x);
  },
};

const obj = {
  x: 'world',
  foo() {
    super.foo();
  }
}

Object.setPrototypeOf(obj, proto);

obj.foo() // "world"

上面代码中,super.foo指向原型对象proto的foo方法,但是绑定的this却还是当前对象obj,因此输出的就是world。

正式的“方法”定义

ES6 则正式做出了定义:方法是一个拥有 [[HomeObject]] 内部属性的函数,此内部属性指向该方法所属的对象。

let person = {
// 方法
    getGreeting() {
        return "Hello";
    }
};
// 并非方法
function shareGreeting() {
    return "Hi!";
}

大多数情况下,这种差异并不重要,然而使用 super 引用时就完全不同了。

let person = {
    getGreeting() {
        return "Hello";
    }
};
// 原型为 person
let friend = {
    getGreeting() {
        return super.getGreeting() + ", hi!";
    }
};
Object.setPrototypeOf(friend, person);
console.log(friend.getGreeting()); // "Hello, hi!"

sevencui
355 声望32 粉丝