摘要:现在让我们用来复制我们可能看到,当用的时候,对象属性是递归复制的。到目前为止,一切看起来还不错。如果深入研究的源码,我们会发现,无论是还是都调用了这个内部函数。结果如下总结将框架升级到新版本是一种冒险行为。
在时间属性上慎用Angular.js1.4的“angular.merge”函数
原文:Pay Attention to "angular.merge" in 1.4 on Date Properties
今天我将应用从Angular.js1.3.9升级到1.4的时候,发现了一些Bug。在经过一翻研究后,发现它们与时间属性及1.4中的“angular.merge”函数有关。
在官方文档中,“angular.merge”的表述如下:
复制src对象中的可枚举属性到dst对象中,以深度扩展目标对象“dst”。
同时也提到了与先前版本中的”angular.extend“的区别。
与"extend()"不同,在进行深度复制时,"merge()"支持递归复制。
让我们来看一个简单的例子,在下面的代码中,作用域内有一个源对象和一个自定义对象,接着我用”angular.extend“将自定义对象复制到源对象中。
$scope.source = { name: "Shaun", age: 35, birthDate: new Date(1997, 5, 27), skills: { dotNet: { level: "expert", years: 10 }, javaScript: { level: "newbie", years: 2 } }, mvp: [ 2011, 2012, 2013, 2014, 2015 ] }; $scope.custom = { name: "Ziyan", age: 35, skills: { dotNet: { level: "hero", years: 100, active: true }, }, mvp: [ 2016 ] }; $scope.extend = angular.extend({}, $scope.source, $scope.custom);
从结果中我们可以看到,“angular.extend”执行的是浅拷贝,像“name”,”age”和“birthDate”这些原始属性值已经合并了,但因为“skills”和”mvp”是对象和数组,”angular.extend“会复制全部值,而不是数组或对象中的成员。
现在让我们用“angular.merge”来复制:
$scope.merge = angular.merge({}, $scope.source, $scope.custom);
我们可能看到,当用“angular.merge”的时候,对象属性是递归复制的。
到目前为止,一切看起来还不错。但是有些人可能会发现,在使用“angular.merge”的时候,其中一个属性“birthDate”被设成了空对象。
如果深入研究angular.js的源码,我们会发现,无论是“angular.extend”还是“angular.merge”都调用了“baseExtend”这个内部函数。它将多个对象合并到目标对象,用一个标志参数来表明是否为深度合并。
在这个函数内部,会遍历每个可枚举属性,将值复制到目标对象。如果源属性是一个对象并且需要深度复制,Angular.js会在目标对象中创建一个空对象,并且对这个属性递归执行这个函数。
function baseExtend(dst, objs, deep) { var h = dst.$$hashKey; for (var i = 0, ii = objs.length; i < ii; ++i) { var obj = objs[i]; if (!isObject(obj) && !isFunction(obj)) continue; var keys = Object.keys(obj); for (var j = 0, jj = keys.length; j < jj; j++) { var key = keys[j]; var src = obj[key]; if (deep && isObject(src)) { if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; baseExtend(dst[key], [src], true); } else { dst[key] = src; } } } setHashKey(dst, h); return dst; }
除了日期之外,它几乎可以处理所有情况。如果我们定义了一个日期属性,例如“birthDate”,它就会用“angular.isObject”检查这个属性是否是为对象,返回的是“true”。所以它会在目标对象中创建一个属性名为“birthDate”的空对象,并且对“birthDate”调用“baseExtend”。但是因为“birthDate”的属性为Date,并不是可枚举属性,所以这个对象不会分配到任何数据。这就是为什么结果中"birthDate"属性为空的原因。
如果我将Angular.js 中的“baseExtend”函数复制到作用域内,并将代码改成如下形式,当属性为Date时,也会执行简单的复制了。
$scope.$baseExtend = function (dst, objs, deep) { for (var i = 0, ii = objs.length; i < ii; ++i) { var obj = objs[i]; if (!angular.isObject(obj) && !angular.isFunction(obj)) { console.log("[" + obj + "] = (skip)"); continue; } var keys = Object.keys(obj); for (var j = 0, jj = keys.length; j < jj; j++) { var key = keys[j]; var src = obj[key]; // perform deep copy if // 1. spcified by user // 2. source property is an object // 3. source property is NOT a date if (deep && angular.isObject(src) && !angular.isDate(src)) { if (!angular.isObject(dst[key])) { console.log("[" + key + "] = (Try copy an object to an non-object, create an empty for deep copy.)"); dst[key] = angular.isArray(src) ? [] : {}; } $scope.$baseExtend(dst[key], [src], true); } else { dst[key] = src; console.log("[" + key + "] = " + src); } } } return dst; }; $scope.sample = $scope.$baseExtend({}, [$scope.source, $scope.custom], true);
结果如下:
总结:将框架升级到新版本是一种冒险行为。我们需要进行大量的回归测试,以确保不会出现任何问题。我在执行E2E测试时发现了这个问题。我想这是Angular.js的Bug,我已经将这个问题贴了出来。在他们确认和修改之前,在你的应用中,慎用“angular.merge”这个函数。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/78526.html
摘要:总结一下的核心对象上的方法,也帮助自己学习一下平时工作中没怎么用到的方法,看能不能提高开发效率。我当前使用的版本是也是目前最新的稳定版本,不过在全局上,版本不同也没什么区别。在引入了的情况下,使用方法和几乎一样,相当于一个语法糖。 总结一下AngularJS的核心对象angular上的方法,也帮助自己学习一下平时工作中没怎么用到的方法,看能不能提高开发效率。我当前使用的Angularj...
摘要:总结一下的核心对象上的方法,也帮助自己学习一下平时工作中没怎么用到的方法,看能不能提高开发效率。我当前使用的版本是也是目前最新的稳定版本,不过在全局上,版本不同也没什么区别。在引入了的情况下,使用方法和几乎一样,相当于一个语法糖。 总结一下AngularJS的核心对象angular上的方法,也帮助自己学习一下平时工作中没怎么用到的方法,看能不能提高开发效率。我当前使用的Angularj...
摘要:原型链理解第一件事你不用管其他语言,一句话,你只要记住里面的对象包含一个原型,原型是啥,就是另外一个对象。原型就相当于你家的车棚子,而你的那个自行车就是对象。万事万物皆对象有啥用一句话,扩展原型方法,给大家一到面试题,数组去重自己体会下。 概述 通过上节课的学习,大家已经会用一种json的方式定义对象了,其实这个就是传说中的单体模式,当然这个大家不用记,关于设计模式暂时不用了解。但是总...
阅读 2014·2021-11-08 13:22
阅读 2482·2021-09-04 16:40
阅读 1129·2021-09-03 10:29
阅读 1652·2019-08-30 15:44
阅读 2095·2019-08-30 11:13
阅读 2765·2019-08-29 17:07
阅读 1935·2019-08-29 14:22
阅读 1224·2019-08-26 14:00