Object.assign 模块

起因:

今年周末闲的蛋疼,于是想看看源码消磨时间。于是不知从哪翻出 Object-assign的模块,看完觉得挺有意思的,于是写篇文章记录一下。

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象

这个模块是Object.assign的Polyfill

开始:

首先拿Object三个方法

getOwnPropertySymbols 对象的所有符号属性作为 Symbol 数组获取

hasOwnProperty 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性

propertyIsEnumerable 判断属性是否可以枚举

var getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
复制代码

toObject这个函数 第一个参数判断是否null或者undefined 是的话报错,否则把值转换为Object类型返回

function toObject(val) {
	if (val === null || val === undefined) {
		throw new TypeError('Object.assign cannot be called with null or undefined');
	}

	return Object(val);
}
复制代码

shouldUseNative这个函数比较有意思,不止判断了Object对象有没有assign,还判断了一些旧版V8对象枚举的一些BUG。 在这里我也用了旧版V8测试了一番。

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;
	}
}
复制代码

这个地方 5这个属性是后面才加上的 枚举顺序应该是 0,1,2,5

在旧版V8里却是 5,0,1,2。

这里把0到9转成字符编码存到数组再用map遍历后转成字符串

按道理应该是0123456789 我们却发现旧版里的输出已经乱了。

额 第三个判断 我想应该个第二个判断一样遍历完后变乱

不过这个判断用到Object.assgin,我这个旧V8不支持报错了,如果报错 会被try catch捕获 在函数里返回false。

最后判断如果 shouldUseNatva 返回true 就说明环境支持Object.assgin和不是旧版的V8,直接调用原生Objetc.assgin。

否则返回自己实现assgin函数。

module.exports = shouldUseNative() ? Object.assign : function (target, source) {
	var from;
	//把第一个参数转成Object
	var to = toObject(target);
	var symbols;
   
        //从第二个对象开始遍历
	for (var s = 1; s < arguments.length; s++) {
		//转换为对象
		from = Object(arguments[s]);
		for (var key in from) {
		    //判断对象自身有没有这个属性
			if (hasOwnProperty.call(from, key)) {
			    //存在的话 目标对象添加这个属性
				to[key] = from[key];
			}
		}
        //  判断环境支不支持 getOwnPropertySymbols
		if (getOwnPropertySymbols) {
		    //获得对象的所有符号属性作为 Symbol 数组
			symbols = getOwnPropertySymbols(from);
			for (var i = 0; i < symbols.length; i++) {
			    //判断这个值是否可以遍历
				if (propIsEnumerable.call(from, symbols[i])) {
					//可以遍历的话 目标对象添加这个属性
					to[symbols[i]] = from[symbols[i]];
				}
			}
		}
	}
     //最后返回这个目标对象
	return to;
};
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值