4、对象原型的操作
(1)Object.setPrototypeOf() ES6 IE11
设置对象的原型(即内部 [[Prototype]] 属性)
Object.setPrototypeOf() 方法设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null
。
当调用该方法 的时候,如果对象的[[Prototype]]是不可扩展(通过 Object.isExtensible()
查看),就会抛出 TypeError
异常。如果prototype
参数不是一个对象或者null
(例如,数字,字符串,boolean,或者 undefined
),则什么都不做。否则,该方法将obj
的[[Prototype]]
修改为新的值。
Object.setPrototypeOf()是
ECMAScript 6最新草案中的方法,相对于 Object.prototype.__proto__
,它被认为是修改对象原型更合适的方法。
注意传参,源对象 原型对象。返回修改了原型后的源对象。
var obj1 = {
name: "obj1"
}
var obj = {
age: 24
}
var dict = Object.setPrototypeOf(obj, obj1);
console.log(dict.name); obj1
警告: 由于现代 JavaScript 引擎优化属性访问所带来的特性的关系,更改对象的 [[Prototype]]
在各个浏览器和 JavaScript 引擎上都是一个很慢的操作。其在更改继承的性能上的影响是微妙而又广泛的,这不仅仅限于 obj.__proto__ = ...
语句上的时间花费,而且可能会延伸到任何代码,那些可以访问任何[[Prototype]]
已被更改的对象的代码。如果你关心性能,你应该避免设置一个对象的 [[Prototype]]
。相反,你应该使用 Object.create()
来创建带有你想要的[[Prototype]]
的新对象。
(2)Object.getPrototypeOf() ES5 IE9
Object.getPrototypeOf()
方法返回指定对象的原型(内部[[Prototype]]
属性的值)。如果没有继承属性,则返回 null
。
var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
var reg = /a/;
Object.getPrototypeOf(reg) === RegExp.prototype; // true
(3)Object.create()
方法创建一个新对象并指定对象原型 兼容性:ES5 IE9
var obj = {
name: "zhu",
age: 24
}
var dict = Object.create(obj);
console.log(dict);
5、Object上的两个工具方法
(1)Object.assign()浅复制对象 兼容性:Edge12 ES6
Object.assign()
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。
Object.assign
方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]
和目标对象的[[Set]]
,所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。
如果属性不可写,会引发TypeError
,如果在引发错误之前添加了任何属性,则可以更改target
对象。
Symbol
类型的属性都会被拷贝,字符串也会作为一个对象进行拷贝。
var sym = Symbol('foo'); //Symbol(foo)
var str = "abc";
var obj = {
name: "zhu",
age: 24,
s: sym
}
var dict = Object.assign({},str,obj);
console.log(dict); {0: "a", 1: "b", 2: "c", name: "zhu", age: 24, s: Symbol(foo)}
console.log(sym); Symbol(foo)
Object.assign()
拷贝的是(可枚举)属性值。假如源值是一个对象的引用,它仅仅会复制其引用值。
异常会打断后续的copy,但前面的copy是成功的,比如一个对象,一部分属性已经copy了,发生异常后,后续停止copy,而前面的属性copy成功。
原始类型会被包装,null 和 undefined 会被忽略。注意,只有字符串的包装对象才可能有自身可枚举属性。
(2)Object.is()判断两个值是否相等 Edge12 ES6
判断两个值是否相同。如果下列任何一项成立,则两个值相同:
这种相等性判断逻辑和传统的 ==
运算不同,==
运算符会对它两边的操作数做隐式类型转换(如果它们类型不同),然后才进行相等性比较,(所以才会有类似 "" == false
等于 true
的现象),但 Object.is
不会做这种类型转换。
这与 ===
运算符的判定方式也不一样。===
运算符(和==
运算符)将数字值 -0
和 +0
视为相等,并认为 Number.NaN
不等于 NaN
。
兼容性:Edge12
兼容性写法:
if (!Object.is) {
Object.is = function(x, y) {
// SameValue algorithm
if (x === y) { // Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / x === 1 / y;
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y;
}
};
}