摘要:現(xiàn)在讓我們用來復(fù)制我們可能看到,當(dāng)用的時(shí)候,對(duì)象屬性是遞歸復(fù)制的。到目前為止,一切看起來還不錯(cuò)。如果深入研究的源碼,我們會(huì)發(fā)現(xiàn),無論是還是都調(diào)用了這個(gè)內(nèi)部函數(shù)。結(jié)果如下總結(jié)將框架升級(jí)到新版本是一種冒險(xiǎn)行為。
在時(shí)間屬性上慎用Angular.js1.4的“angular.merge”函數(shù)
原文:Pay Attention to "angular.merge" in 1.4 on Date Properties
今天我將應(yīng)用從Angular.js1.3.9升級(jí)到1.4的時(shí)候,發(fā)現(xiàn)了一些Bug。在經(jīng)過一翻研究后,發(fā)現(xiàn)它們與時(shí)間屬性及1.4中的“angular.merge”函數(shù)有關(guān)。
在官方文檔中,“angular.merge”的表述如下:
復(fù)制src對(duì)象中的可枚舉屬性到dst對(duì)象中,以深度擴(kuò)展目標(biāo)對(duì)象“dst”。
同時(shí)也提到了與先前版本中的”angular.extend“的區(qū)別。
與"extend()"不同,在進(jìn)行深度復(fù)制時(shí),"merge()"支持遞歸復(fù)制。
讓我們來看一個(gè)簡(jiǎn)單的例子,在下面的代碼中,作用域內(nèi)有一個(gè)源對(duì)象和一個(gè)自定義對(duì)象,接著我用”angular.extend“將自定義對(duì)象復(fù)制到源對(duì)象中。
$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);
從結(jié)果中我們可以看到,“angular.extend”執(zhí)行的是淺拷貝,像“name”,”age”和“birthDate”這些原始屬性值已經(jīng)合并了,但因?yàn)椤皊kills”和”mvp”是對(duì)象和數(shù)組,”angular.extend“會(huì)復(fù)制全部值,而不是數(shù)組或?qū)ο笾械某蓡T。
現(xiàn)在讓我們用“angular.merge”來復(fù)制:
$scope.merge = angular.merge({}, $scope.source, $scope.custom);
我們可能看到,當(dāng)用“angular.merge”的時(shí)候,對(duì)象屬性是遞歸復(fù)制的。
到目前為止,一切看起來還不錯(cuò)。但是有些人可能會(huì)發(fā)現(xiàn),在使用“angular.merge”的時(shí)候,其中一個(gè)屬性“birthDate”被設(shè)成了空對(duì)象。
如果深入研究angular.js的源碼,我們會(huì)發(fā)現(xiàn),無論是“angular.extend”還是“angular.merge”都調(diào)用了“baseExtend”這個(gè)內(nèi)部函數(shù)。它將多個(gè)對(duì)象合并到目標(biāo)對(duì)象,用一個(gè)標(biāo)志參數(shù)來表明是否為深度合并。
在這個(gè)函數(shù)內(nèi)部,會(huì)遍歷每個(gè)可枚舉屬性,將值復(fù)制到目標(biāo)對(duì)象。如果源屬性是一個(gè)對(duì)象并且需要深度復(fù)制,Angular.js會(huì)在目標(biāo)對(duì)象中創(chuàng)建一個(gè)空對(duì)象,并且對(duì)這個(gè)屬性遞歸執(zhí)行這個(gè)函數(shù)。
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; }
除了日期之外,它幾乎可以處理所有情況。如果我們定義了一個(gè)日期屬性,例如“birthDate”,它就會(huì)用“angular.isObject”檢查這個(gè)屬性是否是為對(duì)象,返回的是“true”。所以它會(huì)在目標(biāo)對(duì)象中創(chuàng)建一個(gè)屬性名為“birthDate”的空對(duì)象,并且對(duì)“birthDate”調(diào)用“baseExtend”。但是因?yàn)椤癰irthDate”的屬性為Date,并不是可枚舉屬性,所以這個(gè)對(duì)象不會(huì)分配到任何數(shù)據(jù)。這就是為什么結(jié)果中"birthDate"屬性為空的原因。
如果我將Angular.js 中的“baseExtend”函數(shù)復(fù)制到作用域內(nèi),并將代碼改成如下形式,當(dāng)屬性為Date時(shí),也會(huì)執(zhí)行簡(jiǎn)單的復(fù)制了。
$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);
結(jié)果如下:
總結(jié):將框架升級(jí)到新版本是一種冒險(xiǎn)行為。我們需要進(jìn)行大量的回歸測(cè)試,以確保不會(huì)出現(xiàn)任何問題。我在執(zhí)行E2E測(cè)試時(shí)發(fā)現(xiàn)了這個(gè)問題。我想這是Angular.js的Bug,我已經(jīng)將這個(gè)問題貼了出來。在他們確認(rèn)和修改之前,在你的應(yīng)用中,慎用“angular.merge”這個(gè)函數(shù)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78526.html
摘要:總結(jié)一下的核心對(duì)象上的方法,也幫助自己學(xué)習(xí)一下平時(shí)工作中沒怎么用到的方法,看能不能提高開發(fā)效率。我當(dāng)前使用的版本是也是目前最新的穩(wěn)定版本,不過在全局上,版本不同也沒什么區(qū)別。在引入了的情況下,使用方法和幾乎一樣,相當(dāng)于一個(gè)語法糖。 總結(jié)一下AngularJS的核心對(duì)象angular上的方法,也幫助自己學(xué)習(xí)一下平時(shí)工作中沒怎么用到的方法,看能不能提高開發(fā)效率。我當(dāng)前使用的Angularj...
摘要:總結(jié)一下的核心對(duì)象上的方法,也幫助自己學(xué)習(xí)一下平時(shí)工作中沒怎么用到的方法,看能不能提高開發(fā)效率。我當(dāng)前使用的版本是也是目前最新的穩(wěn)定版本,不過在全局上,版本不同也沒什么區(qū)別。在引入了的情況下,使用方法和幾乎一樣,相當(dāng)于一個(gè)語法糖。 總結(jié)一下AngularJS的核心對(duì)象angular上的方法,也幫助自己學(xué)習(xí)一下平時(shí)工作中沒怎么用到的方法,看能不能提高開發(fā)效率。我當(dāng)前使用的Angularj...
摘要:原型鏈理解第一件事你不用管其他語言,一句話,你只要記住里面的對(duì)象包含一個(gè)原型,原型是啥,就是另外一個(gè)對(duì)象。原型就相當(dāng)于你家的車棚子,而你的那個(gè)自行車就是對(duì)象。萬事萬物皆對(duì)象有啥用一句話,擴(kuò)展原型方法,給大家一到面試題,數(shù)組去重自己體會(huì)下。 概述 通過上節(jié)課的學(xué)習(xí),大家已經(jīng)會(huì)用一種json的方式定義對(duì)象了,其實(shí)這個(gè)就是傳說中的單體模式,當(dāng)然這個(gè)大家不用記,關(guān)于設(shè)計(jì)模式暫時(shí)不用了解。但是總...
閱讀 2050·2021-11-08 13:22
閱讀 2510·2021-09-04 16:40
閱讀 1155·2021-09-03 10:29
閱讀 1723·2019-08-30 15:44
閱讀 2127·2019-08-30 11:13
閱讀 2795·2019-08-29 17:07
閱讀 1972·2019-08-29 14:22
閱讀 1252·2019-08-26 14:00