Object
几个额外的静态帮助方法已经被加入Object
。从传统意义上讲,这种种类的函数是关注于对象值的行为/能力的。
但是,从ES6开始,Object
静态函数还用于任意种类的通用全局API —— 那些还没有更自然地存在于其他的某些位置的API(例如,Array.from(..)
)。
Object.is(..)
静态函数
Object.is(..)
静态函数进行值的比较,它的风格甚至要比===
比较还要严格。
Object(..)
调用底层的SameValue
算法(ES6语言规范,第7.2.9节)。SameValue
算法基本上与===
严格等价比较算法相同(ES6语言规范,第7.2.13节),但是带有两个重要的例外。
考虑如下代码:
var x = NaN, y = 0, z = -0;
x === x; // false
y === z; // true
Object.is( x, x ); // true
Object.is( y, z ); // false
你应当为严格等价性比较继续使用===
;Object.is(..)
不应当被认为是这个操作符的替代品。但是,在你想要严格地识别NaN
或-0
值的情况下,Object.is(..)
是现在的首选方式。
注意: ES6还增加了一个Number.isNaN(..)
工具(在本章稍后讨论),它可能是一个稍稍方便一些的测试;比起Object.is(x, NaN)
你可能更偏好Number.isNaN(x)
。你 可以 使用笨拙的x == 0 && 1 / x === -Infinity
来准确地测试-0
,但在这种情况下Object.is(x,-0)
要好得多。
Object.getOwnPropertySymbols(..)
静态函数
第二章中的“Symbol”一节讨论了ES6中的新Symbol基本值类型。
Symbol可能将是在对象上最经常被使用的特殊(元)属性。所以引入了Object.getOwnPropertySymbols(..)
,它仅取回直接存在于对象上的symbol属性:
var o = {
foo: 42,
[ Symbol( "bar" ) ]: "hello world",
baz: true
};
Object.getOwnPropertySymbols( o ); // [ Symbol(bar) ]
Object.setPrototypeOf(..)
静态函数
还是在第二章中,我们提到了Object.setPrototypeOf(..)
工具,它为了 行为委托 的目的(意料之中地)设置一个对象的[[Prototype]]
(参见本系列的 this与对象原型)。考虑如下代码:
var o1 = {
foo() { console.log( "foo" ); }
};
var o2 = {
// .. o2 的定义 ..
};
Object.setPrototypeOf( o2, o1 );
// 委托至 `o1.foo()`
o2.foo(); // foo
另一种方式:
var o1 = {
foo() { console.log( "foo" ); }
};
var o2 = Object.setPrototypeOf( {
// .. o2 的定义 ..
}, o1 );
// 委托至 `o1.foo()`
o2.foo(); // foo
在前面两个代码段中,o2
和o1
之间的关系都出现在o2
定义的末尾。更常见的是,o2
和o1
之间的关系在o2
定义的上面被指定,就像在类中,而且在对象字面量的__proto__
中也是这样(参见第二章的“设置[[Prototype]]
”)。
警告: 正如展示的那样,在对象创建之后立即设置[[Prototype]]
是合理的。但是在很久之后才改变它一般不是一个好主意,而且经常会导致困惑而非清晰。
Object.assign(..)
静态函数
许多JavaScript库/框架都提供将一个对象的属性拷贝/混合到另一个对象中的工具(例如,jQuery的extend(..)
)。在这些不同的工具中存在着各种微妙的区别,比如一个拥有undefined
值的属性是否被忽略。
ES6增加了Object.assign(..)
,它是这些算法的一个简化版本。第一个参数是 目标对象 而所有其他的参数是 源对象,它们会按照罗列的顺序被处理。对每一个源对象,它自己的(也就是,不是“继承的”)可枚举键,包括symbol,将会好像通过普通=
赋值那样拷贝。Object.assign(..)
返回目标对象。
考虑这种对象构成:
var target = {},
o1 = { a: 1 }, o2 = { b: 2 },
o3 = { c: 3 }, o4 = { d: 4 };
// 设置只读属性
Object.defineProperty( o3, "e", {
value: 5,
enumerable: true,
writable: false,
configurable: false
} );
// 设置不可枚举属性
Object.defineProperty( o3, "f", {
value: 6,
enumerable: false
} );
o3[ Symbol( "g" ) ] = 7;
// 设置不可枚举 symbol
Object.defineProperty( o3, Symbol( "h" ), {
value: 8,
enumerable: false
} );
Object.setPrototypeOf( o3, o4 );
仅有属性a
,b
,c
,e
,和Symbol("g")
将被拷贝到target
:
Object.assign( target, o1, o2, o3 );
target.a; // 1
target.b; // 2
target.c; // 3
Object.getOwnPropertyDescriptor( target, "e" );
// { value: 5, writable: true, enumerable: true,
// configurable: true }
Object.getOwnPropertySymbols( target );
// [Symbol("g")]
属性d
,f
,和Symbol("h")
在拷贝中被忽略了;非枚举属性和非自身属性将会被排除在赋值之外。另外,e
作为一个普通属性赋值被拷贝,而不是作为一个只读属性被复制。
在早先一节中,我们展示了使用setPrototypeOf(..)
来在对象o2
和o1
之间建立一个[[Prototype]]
关系。这是利用Object.assign(..)
的另外一种形式:
var o1 = {
foo() { console.log( "foo" ); }
};
var o2 = Object.assign(
Object.create( o1 ),
{
// .. o2 的定义 ..
}
);
// 委托至 `o1.foo()`
o2.foo(); // foo
注意: Object.create(..)
是一个ES5标准工具,它创建一个[[Prototype]]
链接好的空对象。更多信息参见本系列的 this与对象原型。