5

Consider following example:

var ar = [4, 2, 3];
ar.$x = 'something';
var br = angular.copy(ar);
console.dir(br);

br does not have $x property any more, because when copying array, angular iterates with for (;;;) which does not see custom properties (if it iterated with for in then it would work).

Which of following shall I do?

  1. Create array like class and then assign property;
  2. If it's bug, report to angular;
  3. Change my code, because assigning property to array is not good practice;
karaxuna
  • 26,752
  • 13
  • 82
  • 117

3 Answers3

5

Try angular.merge() This is a deep copy that includes enumerable properties.

var ar = [4, 2, 3];
ar.$x = 'something';
var br = angular.merge([], ar);
console.dir(br);

Output

Array[3]
  0: 4
  1: 2
  2: 3
  $x: "something"
  length: 3
  __proto__: Array[0]
Anthony Patton
  • 595
  • 3
  • 10
  • 2
    Hate to spoil the good mood, but `merge()` does **not** make a deep copy, it simply extends `br` with `ar`. If you afterwards change `ar`, say `ar.y = 'x'` then `br` will hold `y: 'x'` too. Proof of concept -> **http://plnkr.co/edit/idH8tKqRb2zGXT817UvV?p=preview** – davidkonrad Dec 17 '15 at 11:24
  • 1
    **Good Catch**. My eagerness to match the OPs example resulted in omitting the new array to merge into. I have updated the answer with the correct code. `var br = angular.merge(ar)` should be `var br = angular.merge([], ar)`. Updated POC -> http://plnkr.co/edit/UOGX1CpoOfr0QA4YqNda?p=preview. – Anthony Patton Dec 17 '15 at 13:54
  • I ended up changing my code, but marked this answer because it solves problem that is in question. – karaxuna Dec 18 '15 at 12:38
2

I think that it's not an Angular problem. If you call such a statement:

ar.$x = 'something';
console.log(Object.prototype.toString.call(ar));

You will see that [object Array] will be logged. That is how Array.isArray() method works, and, in its turn, that is how angular copy() method decides how to iterate through the entity passed as the argument. This detection is crucial beacuse for ... in loop on an array can make some confusions in other cases. Here is described why: Why is using "for...in" with array iteration a bad idea?

I would advise you to change your code, for this particular case.

Community
  • 1
  • 1
Alexandr Lazarev
  • 12,554
  • 4
  • 38
  • 47
1

Try using jQuery:

jQuery.extend([], ar);

var ar = [4, 2, 3];
ar.$x = 'something';
var br = jQuery.extend([], ar);
console.dir(br);
birwin
  • 2,524
  • 2
  • 21
  • 41