JS学习笔记--ES6新增API Object部分

173 阅读3分钟

这篇文章是我学习了《你不知道的JavaScript》下卷 ES6 新增API Object部分,然后摘抄与整理所学到的四种 Object 函数。

1. 静态函数 Object.is(..)

静态函数Object.is(..)执行比===比较更严格的值比较。

Object.is(..)调用底层 SameValue 算法。SameValue 算法基本上和===严格相等比较算法一样,但有两个重要的区别。

考虑:

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(..)

2. 静态函数 Object.getOwnPropertySymbols(..)

ES6中新增了基本值类型 Symbol,而 Symbol 很可能会成为对象最常用的特殊(元)属性。所以引入了工具Object.getOwnPropertySymbols(..),他直接从对象上取得所有的符号属性:

var o = {
    foo: "42",
    [ Symbol( "bar" ) ]: "hello world",
    baz: true
};

Object.getOwnPropertySymbols( o );          // [ Symbol(bar) ]

3. 静态函数 Object.setPrototypeOf(..)

工具Object.setPrototypeOf(..)设置对象的[[Prototype]]用于行为委托。考虑:

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__一样。

4. 静态函数 Object.assign(..)

很多 JavaScript 库/框架提供了用于把一个对象的属性复制/混合到另一个对象中的工具。这些工具之间有各种细微的区别,比如是否忽略值为 undefined 的属性。

ES6 新增了 Object.assign(..),这是这些算法的简化版本。第一个参数是 target,其他传入的参数都是源,他们将按照列出的顺序依次被处理。对于每一个源来说,它的可枚举和自己拥有的(即不是“继承来的”)键值,包括 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;

// 设定不可枚举符号
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

原文链接