Open
Description
Object.assign
通过React源码里Object.assign
的polyfill来了解:
Object.assign
实现细节;- 何时使用
Object.assign
的polyfill。
1. Object.assign
实现细节
能做的:
Object.assign(target, ...sources)
- 通过浅复制的方式将多个
sources
对象合并到target
对象里; - 只copy
sources
对象的可枚举的对象本身的属性;
var p = {
say: () => {
console.log('hi~')
}
}
var a = Object.create(p)
a.name = 'a';
Object.defineProperty(a, 'age', {
enumerable: false,
value: 12
})
var b = Object.assign({}, a)
console.log(b) // {name: "a"}
- 字符串属性和
Symbol
属性都支持。 - 会自动将
sources
参数转成对象,如果sources
参数为null/undefined,则忽略。 - 如果
target
参数为null/undefined, 则抛异常。
不能做的
- 不copy属性的特性;
可以借助库merge-descriptors - 不支持深copy;
- 不会过滤取值为
null
或则undefined
的属性
2. 何时该使用polyfill
不能简单的判断Object.assign
是否存在,奉上React的实现:
function shouldUseNative() {
try {
if (!Object.assign) {
return false;
}
// Detect buggy property enumeration order in older V8 versions.
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
test1[5] = 'de';
if (Object.getOwnPropertyNames(test1)[0] === '5') {
return false;
}
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test2 = {};
for (var i = 0; i < 10; i++) {
test2['_' + String.fromCharCode(i)] = i;
}
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
return test2[n];
});
if (order2.join('') !== '0123456789') {
return false;
}
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test3 = {};
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
test3[letter] = letter;
});
if (Object.keys(Object.assign({}, test3)).join('') !==
'abcdefghijklmnopqrst') {
return false;
}
return true;
} catch (err) {
// We don't expect any of the above to throw, but better to be safe.
return false;
}
}
- 不明白bug4118 跟
Object.assign
有什么关系 ? - 如果不考虑顺序问题,可以忽略bug4118和3056 ?