Skip to content

JS-ES2015-Object #141

Open
Open
@yaofly2012

Description

@yaofly2012

Object.assign

通过React源码里Object.assign的polyfill来了解:

  1. Object.assign实现细节;
  2. 何时使用Object.assign的polyfill。

1. Object.assign实现细节

能做的:

Object.assign(target, ...sources)
  1. 通过浅复制的方式将多个sources对象合并到target对象里;
  2. 只copysources对象的可枚举的对象本身的属性;
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"}
  1. 字符串属性和Symbol属性都支持。
  2. 会自动将sources参数转成对象,如果sources参数为null/undefined,则忽略。
  3. 如果target参数为null/undefined, 则抛异常。

不能做的

  1. 不copy属性的特性;
    可以借助库merge-descriptors
  2. 不支持深copy;
  3. 不会过滤取值为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 ?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions