Sous FF, ça renvoie 't'
La chaîne est découpée par caractère.Code:
1
2 var s=new String('toto'); alert(s[0]); for(i in s) alert(i);
Version imprimable
comme en php une chaine est considérée comme un array de caractères !
mais pas sous IE :(
Attention également , un Objet , même s'il a une propriété length , n'est pas typé Array Spaffy ;-)
Comme dans beaucoup de langage en fait.
Voici une fonction de clonage qui lève quelques lièvres. Inspirée d'une source d'un blog où il manquait la prise en compte de certains objets ;)
La méthode n'étant pas anonyme, on peut la soliciter par obj.clone() ou clone(obj).Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 if(!Object.clone) Object.prototype.clone = function clone (obj) { if (obj === null) return null; if (!obj) obj = this; if (obj.cloneNode) return obj.cloneNode(true); if (typeof(obj) != 'object') return obj; var temp = (obj instanceof Array) ? new Array(obj.length) : new obj.constructor(obj); for (var key in obj) { if (!obj.hasOwnProperty(key)) continue; temp[key] = (obj[key] === undefined) ? undefined : clone(obj[key]); } return temp; };
Fonctionne sous FF et Safari. :ccool:
suffit de tester ensuite dans les boucles for in si c'est un prototype ou pas avec hasOwnProperty non ?
Heu... non justement, c'est d'ailleurs bien une raison importante pour répéter que les tableaux associatifs n'existent pas en JavaScript : le type Object ne possède pas de propriété length :
Amusant ça... j'aimerais bien voir un Array avoir pour typeof 'array' :)Code:
1
2
3
4
5
6 var test={ 'toto': 'tata', 'valeur': 1, 3: 'autrechose' } alert(test.length)
Là encore, c'est une source de confusion courante, le typeof d'un objet Array est object !
Là dessus, je rejoins allègrement kernelfailure et E.Bzz.Code:
1
2 var tab = [1,2,3]; alert(typeof tab)
Ensuite, c'est comme pour tout, utiliser prototype implique de savoir assez précisément ce que l'on fait, ce qui n'est malheureusement pas souvent le cas avec JavaScript... :(
En effet. Je ne sais pas ce qu'il m'a pris... Bien vu :ccool:
Correction(s) apportée(s)
EDIT:
La version 'finale'(?) de toSource() puisque j'avais commencé par là pour lequel un clonage = eval( original.toSource() ) fonctionne aussi :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 if(!Object.toSource) Object.prototype.toSource = function toSource (obj) { if (obj === null) return 'null'; if (!obj) obj = this; switch (obj.constructor) { case Boolean: return (typeof(obj) != 'object') ? obj : "(new Boolean(" + obj + "))"; case Number: return (typeof(obj) != 'object') ? obj : "(new Number(" + obj + "))"; case String: var s = '\"' + obj.replace(/[\\\"\']/g,"\\$&") + '\"'; return (typeof(obj) != 'object') ? s : "(new String(" + s + "))"; case Date: return "(new Date(" + obj.valueOf() + "))"; case RegExp: return obj; case Function: return '(' + obj.toString().replace(/[\s]+/g,' ').replace(/{ /g,'{').replace(/ }/g,'}') + ')'; case Array: var a = new Array(obj.length); if (!new RegExp(/^[,]+$/).test(obj.toString())) { for (var i=0, n=obj.length; i<n; i++) { a[i] = (obj[i] === undefined) ? '(void 0)' : toSource(obj[i]); } } return '[' + a.toString() + ']'; default: var o = []; for (var p in obj) { if (!obj.hasOwnProperty(p)) continue; o.push(p.valueOf() + ':' + (obj[p] === undefined ? '(void 0)' : toSource(obj[p]))); } return "({" + o.join(", ") + "})"; } };
malheureusement pas de façon crossbrowser :(Citation:
pour lequel un clonage = eval( original.toSource() ) fonctionne aussi :
Les prototypes de Array, Number, Date si vous voulez, mais certainement pas Object.
le simple fait de créer un objet basique du genre
quand tu vas itérer dessus pour récupérer ses propriétés et dans un cas par exemple le sérialiser et que tu ne fais pas de test sur les attributs (car tu sais que ton objet est simple)Code:
1
2 var o = {y:12, x:14}
Donc comme tu peux le voir nous avons un magnifique résidu moisi qui n'a rien à faire ICI. C'est pour cela qu'il ne faut jamais modifier le prototype de Object en JS, tu peux modifier le prototype de Array, Number ou Date ou n'importe quel autre Classe si tu veux, mais pas ObjectCode:
1
2
3
4
5
6
7 for (var i in o) { console.log(o[i],':',typeof o[i]); } y : 12 => number x : 14 => number clone : function() => function
exemple encore plus flagrant quand tu as une map de fonctions :
Et la je voudrais par exemple lister tous les éléments de cette map pour une raison ou une autre dans un array :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 var tablesTypeMap = { tableData1 : { //pleins de trucs dedans }, tableData2 : { }, EnergyValues : { } }
C'est là ou je veux en venir, en général en JS, un objet est vide, ne contient aucune méthode, et on a souvent l'habitude de s'en servir comme hashmap par exemple, donc si on se retrouve avec des methodes sur nos object on peut foirer un application.Code:
1
2
3
4
5
6
7 var mapItemsList = []; for (var i in tablesTypeMap) { mapItemsList.push(i); } alert(mapItemsList.join(';')) --> tableData1;tableData2;EnergyValues;toSource() // ya un intrus ici
Il m'arrive parfois d'avoir des hashmap de fonctions, et j'aime pas avoir un intrus en plus :)
Aucune des librairies tels que Mootools ou Jquery ne tapent sur Object.prototype, pour PrototypeJS je ne sais pas
Exact. Tu as raison de le préciser.
IE7 ne le digère pas, à cause de Element, qu'il n'implémente pas.
Il existe quelques solutions qui passent par des wrappers, mettant en oeuvre ou pas HTC. On sombre dans l'exotisme, comme toujours.
IE6, j'imagine que non et je ne m'en soucis pas, pas plus que de communicator.
Logiquement, ça devrait passer IE8 puisqu'il est prétendument "respectueux DOM W3C".
Pour ma part, ça fonctionne sous FF, Opera et Safari.
Ca ne fonctionnera pas sous Lynx, et donc peut-être pas sous IE.
(confusion avec une autre source : Pas d'utilisation de Element ici) :oops:
Sous quel autre nav as-tu testé ?
je teste principalement sous FFX Opera IE et google chrome parfois lunascape
je trouve que vos propositions sont lourdes et compliqué, si il s'agit juste de copié un tableau en profondeur.
on peux pas faire plus simple ;)Code:
1
2
3
4
5
6
7
8
9
10
11
12 Array.prototype.deepClone = function(){ var obj = this.slice(); for(var i = 0, l = obj.length; i < l; i++) if(obj[i].constructor == Array) obj[i] = obj[i].deepClone(); return obj; }; var ar = new Array(1,['oui',['no','niet']],3,{hello:"bonjour",goodbye:"aurevoir"}), ar2 = ar.deepClone(); alert(ar2[1] == ar[1])
sauf que ta copie en profondeur ne s'applique pas dasn ce cas au dernier element de l'array il copie par reference :
retourne bingo au lieu de bonjourCode:
1
2
3
4
5
6
7
8
9
10
11
12 Array.prototype.deepClone = function(){ var obj = this.slice(); for(var i = 0, l = obj.length; i < l; i++) if(obj[i].constructor == Array) obj[i] = obj[i].deepClone(); return obj; }; var ar = new Array(1,['oui',['no','niet']],3,{hello:"bonjour",goodbye:"aurevoir"}), ar2 = ar.deepClone(); ar[3]['hello']='bingo' alert(ar2[3]['hello'])
ba c'est normale en faite :)
La question était
il s'agit donc juste de copié en profondeur un tableau de tableau, et non pas de copié tout les membres descendant.Citation:
Je souhaite faire une deep copy, c'est à dire que je souhaite que les deux tableaux soient indépendants, l'un devant être une "sauvegarde" de l'autre.
De la même manière qu'on ne liste pas un répertoire courant en incluant sa racine :
C'est l'intérêt de prototype. avec hasOwnProperty, on sait s'il s'agit d'une propriété hérité ou pas.Code:
1
2
3
4
5
6
7 for (var i in o) { if(!o.hasOwnProperty()) continue; console.log(o[i],':',typeof o[i]); } y : 12 => number x : 14 => number
une fonction pour tout cloner ....
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 Object.isCollection = function(obj){ return obj && typeof obj.item == 'function' && obj.namedItem == 'function'; }; Object.isArrayLike = function(obj){ return obj && (obj.constructor == Array || obj.callee || Object.isCollection(obj)); }; Object.isObjectLike = function(obj){ return typeof obj == 'object' && obj.constructor != Array && obj.constructor != Date && obj.constructor != RegExp && !Object.isCollection(obj); }; Object.isFunction = function(obj){ return typeof obj == "function"; }; var deepClone = function(obj){ var isArrayLike = Object.isArrayLike(obj), isObjectLike = Object.isObjectLike(obj), isFunction = Object.isFunction(obj), res; if(isArrayLike){ res = [];//on peux pas appélle le constructeur de argument et d'une colection donc on renvoie tjrs un tableau for(var i = 0, l = obj.length; i < l; i++) res[i] = deepClone(obj[i]); }else if(isObjectLike){ res = {}; for(var i in obj) res[i] = deepClone(obj[i]); }else if(isFunction){ var res = eval('[' + obj.toString() + ']')[0]; for(var i in obj) if(this.hasOwnProperty(i)) res[i] = deepClone(obj[i]); for(var i in obj.prototype) res.prototype[i] = deepClone(obj.prototype[i]); }else res = obj; return res; } var ar = new Array(1,['oui',['no','niet']],3,{hello:"bonjour",goodbye:"aurevoir"}), ar2 = deepClone(ar); ar[3]['hello']='bingo' alert(ar2[3]['hello']);