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与对象原型。