Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 54fa16e

Browse files
committed
perf: speed up shallowCopy and special case Attributes cloning
`for in` is much faster than `Object.keys()` but `for in` includes properties from the prototype. http://jsperf.com/for-in-vs-object-keys2 All the uses of shallowCopy don't deal with objects with heavy prototypes, except for Attributes instances in $compile. For this reason it's better to special-case Attributes constructor and make it do it's own shallow copy. This cleans up the Attribute/$compile code as well.
1 parent fb00210 commit 54fa16e

File tree

3 files changed

+23
-27
lines changed

3 files changed

+23
-27
lines changed

src/Angular.js

+5-7
Original file line numberDiff line numberDiff line change
@@ -821,11 +821,13 @@ function copy(source, destination, stackSource, stackDest) {
821821
}
822822

823823
/**
824-
* Creates a shallow copy of an object, an array or a primitive
824+
* Creates a shallow copy of an object, an array or a primitive.
825+
*
826+
* Assumes that there no proto properties for objects
825827
*/
826828
function shallowCopy(src, dst) {
827829
var i = 0;
828-
var l;
830+
var l, key;
829831

830832
if (isArray(src)) {
831833
dst = dst || [];
@@ -836,11 +838,7 @@ function shallowCopy(src, dst) {
836838
} else if (isObject(src)) {
837839
dst = dst || {};
838840

839-
var keys = Object.keys(src);
840-
841-
for (l = keys.length; i < l; i++) {
842-
var key = keys[i];
843-
841+
for (key in src) {
844842
if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
845843
dst[key] = src[key];
846844
}

src/ng/compile.js

+18-7
Original file line numberDiff line numberDiff line change
@@ -663,9 +663,20 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
663663
function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
664664
$controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
665665

666-
var Attributes = function(element, attr) {
666+
var Attributes = function(element, attributesToCopy) {
667+
if (attributesToCopy) {
668+
var keys = Object.keys(attributesToCopy);
669+
var i, l, key;
670+
671+
for (i = 0, l = keys.length; i < l; i++) {
672+
key = keys[i];
673+
this[key] = attributesToCopy[key];
674+
}
675+
} else {
676+
this.$attr = {};
677+
}
678+
667679
this.$$element = element;
668-
this.$attr = attr || {};
669680
};
670681

671682
Attributes.prototype = {
@@ -1459,12 +1470,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
14591470

14601471

14611472
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
1462-
var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;
1473+
var i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;
14631474

1464-
attrs = (compileNode === linkNode)
1465-
? templateAttrs
1466-
: shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));
1467-
$element = attrs.$$element;
1475+
var $element = jqLite(linkNode);
1476+
var attrs = (compileNode === linkNode)
1477+
? templateAttrs
1478+
: new Attributes($element, templateAttrs);
14681479

14691480
if (newIsolateScopeDirective) {
14701481
var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;

test/AngularSpec.js

-13
Original file line numberDiff line numberDiff line change
@@ -244,19 +244,6 @@ describe('angular', function() {
244244
expect(clone.$some).toBe(original.$some);
245245
});
246246

247-
it('should omit properties from prototype chain', function() {
248-
var original, clone = {};
249-
function Func() {}
250-
Func.prototype.hello = "world";
251-
252-
original = new Func();
253-
original.goodbye = "world";
254-
255-
expect(shallowCopy(original, clone)).toBe(clone);
256-
expect(clone.hello).toBeUndefined();
257-
expect(clone.goodbye).toBe("world");
258-
});
259-
260247
it('should handle arrays', function() {
261248
var original = [{}, 1],
262249
clone = [];

0 commit comments

Comments
 (0)