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

在前面两个代码段中,o2o1之间的关系都出现在o2定义的末尾。更常见的是,o2o1之间的关系在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 );

仅有属性abce,和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")]

属性df,和Symbol("h")在拷贝中被忽略了;非枚举属性和非自身属性将会被排除在赋值之外。另外,e作为一个普通属性赋值被拷贝,而不是作为一个只读属性被复制。

在早先一节中,我们展示了使用setPrototypeOf(..)来在对象o2o1之间建立一个[[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与对象原型

results matching ""

    No results matching ""