主要知识点有对象种别、属性速记法、要领简写、需盘算属性名、Object.is()要领、Object.assign()要领、可许可反复的属性、自有属性的罗列递次、Object.setPrototypeOf()要领、super援用、要领定义
对象种别
- 一般对象:具有 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() 处置惩罚属性的递次。
自有属性罗列时基础递次以下:
- 一切的数字范例键,按升序分列。
- 一切的字符串范例键,按被增加到对象的递次分列。
- 一切的标记范例(详见第六章)键,也按增加递次分列。
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!"