1848 votes

Qu'est-ce que le mot clé "new" en JavaScript ?

El new Le mot-clé en JavaScript peut être assez déroutant lorsqu'on le rencontre pour la première fois, car les gens ont tendance à penser que JavaScript n'est pas un langage de programmation orienté objet.

  • Qu'est-ce que c'est ?
  • Quels sont les problèmes qu'elle résout ?
  • Quand cela est-il approprié et quand cela ne l'est-il pas ?

12 votes

1 votes

Lisez d'abord ces exemples, les amis, developer.mozilla.org/fr/US/docs/Web/JavaScript/Référence/

2224voto

Daniel Howard Points 7596

Il fait 5 choses :

  1. Il crée un nouvel objet. Le type de cet objet est simplement objet .
  2. Il définit l'interne de ce nouvel objet, inaccessible, [[prototype]] (c'est-à-dire __proto__ ) pour être la propriété externe et accessible de la fonction constructeur, prototype (chaque objet fonction possède automatiquement un objet prototype propriété).
  3. Il rend le this pointe vers l'objet nouvellement créé.
  4. Il exécute la fonction du constructeur, en utilisant l'objet nouvellement créé à chaque fois que l'on a besoin d'une aide. this est mentionné.
  5. Elle renvoie l'objet nouvellement créé, à moins que la fonction du constructeur ne renvoie un non-objet. null référence à l'objet. Dans ce cas, cette référence d'objet est retournée à la place.

Nota: fonction constructeur fait référence à la fonction située après le new mot-clé, comme dans

new ConstructorFunction(arg1, arg2)

Une fois que cela est fait, si une propriété non définie du nouvel objet est demandée, le script vérifiera l'objet [[prototype]] pour la propriété à la place. C'est ainsi que vous pouvez obtenir quelque chose de similaire à l'héritage traditionnel des classes en JavaScript.

La partie la plus difficile est le point numéro 2. Chaque objet (y compris les fonctions) possède une propriété interne appelée [[prototype]] . Il peut uniquement être défini au moment de la création de l'objet, soit avec nouveau avec Objet.create ou en fonction du littéral (les fonctions renvoient par défaut à Function.prototype, les nombres à Number.prototype, etc.) Il ne peut être lu qu'avec Object.getPrototypeOf(someObject) . Il y a pas de autre moyen de définir ou de lire cette valeur.

Fonctions, en plus des fonctions cachées [[prototype]] ont également une propriété appelée prototype C'est à elle que vous pouvez accéder, et modifier, pour fournir des propriétés et des méthodes héritées aux objets que vous fabriquez.


Voici un exemple :

ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes 
// it a constructor.

ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that 
// we can alter. I just added a property called 'b' to it. Like 
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with

obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1.  At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'.

obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks 
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'

C'est comme l'héritage de classe parce que maintenant, tous les objets que vous faites en utilisant new ObjMaker() semblent également avoir hérité de la propriété "b".

Si vous voulez quelque chose comme une sous-classe, alors vous faites ceci :

SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);

SubObjMaker.prototype.c = 'third';  
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype

obj2.c;
// returns 'third', from SubObjMaker.prototype

obj2.b;
// returns 'second', from ObjMaker.prototype

obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype 
// was created with the ObjMaker function, which assigned a for us

J'ai lu une tonne de bêtises sur ce sujet avant de finalement trouver cette page où tout cela est très bien expliqué avec de beaux diagrammes.

1 votes

@daniel, +1 pour le bien. Comment avez-vous découvert ce que fait New ?

51 votes

Je voulais juste ajouter : Il existe en fait un moyen d'accéder au [[prototype]] interne, par __proto__. C'est cependant non standard, et seulement supporté par des navigateurs relativement récents (et pas tous). Il existe un moyen normalisé, à savoir Object.getPrototypeOf(obj), mais il s'agit d'Ecmascript3.1, et n'est lui-même pris en charge que par les nouveaux navigateurs - encore une fois. Il est généralement recommandé de ne pas utiliser cette propriété, car les choses se compliquent très vite à l'intérieur.

2 votes

Je pense que cela est également expliqué dans le classique Docs MDC .

428voto

JulianR Points 7257

Supposons que vous ayez cette fonction :

var Foo = function(){
  this.A = 1;
  this.B = 2;
};

Si vous l'appelez comme une fonction autonome, comme ceci :

Foo();

L'exécution de cette fonction ajoutera deux propriétés au fichier window objet ( A y B ). Il l'ajoute à la window parce que window est l'objet qui a appelé la fonction lorsque vous l'exécutez de cette manière, et this dans une fonction est l'objet qui a appelé la fonction. En Javascript au moins.

Maintenant, appelez-le comme ceci avec new :

var bar = new Foo();

Que se passe-t-il lorsque vous ajoutez new à l'appel d'une fonction est qu'un nouvel objet est créé (tout simplement var bar = new Object() ) et que le this dans la fonction pointe vers le nouveau Object que vous venez de créer, plutôt qu'à l'objet qui a appelé la fonction. Ainsi, bar est maintenant un objet avec les propriétés A y B . Toute fonction peut être un constructeur, mais cela n'a pas toujours de sens.

7 votes

Cela dépend du contexte d'exécution. Dans mon cas (Qt scripting) c'est juste un objet global.

2 votes

Cela entraînera-t-il une plus grande utilisation de la mémoire ?

2 votes

parce que window est l'objet qui a appelé la fonction - doit être : parce que la fenêtre est l'objet qui contient la fonction.

171voto

basilikum Points 4196

En plus de la réponse de Daniel Howard, voici ce qui suit new fait (ou du moins semble faire) :

function New(func) {
    var res = {};
    if (func.prototype !== null) {
        res.__proto__ = func.prototype;
    }
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }
    return res;
}

Alors que

var obj = New(A, 1, 2);

est équivalent à

var obj = new A(1, 2);

76 votes

Je trouve que le javascript est plus facile à comprendre que l'anglais :v

1 votes

Excellente réponse. J'ai une petite question : Comment est-il possible pour func.prototype à être null ? Pourriez-vous nous en dire un peu plus à ce sujet ?

6 votes

@tomp vous pouvez remplacer la propriété prototype, en écrivant simplement A.prototype = null; Dans ce cas new A() donnera naissance à un objet, dont le prototype interne pointe vers l'objet Object objet : jsfiddle.net/Mk42Z

39voto

meder Points 81864

donc ce n'est probablement pas pour créer instances d'objets

Il est utilisé exactement pour ça. Vous définissez un constructeur de fonction comme ceci :

function Person(name) {
    this.name = name;
}

var john = new Person('John');

Cependant, l'avantage supplémentaire de l'ECMAScript est que vous pouvez l'étendre avec la fonction .prototype donc on peut faire quelque chose comme...

Person.prototype.getName = function() { return this.name; }

Tous les objets créés à partir de ce constructeur auront désormais un nom d'utilisateur de type getName en raison de la chaîne de prototypes à laquelle ils ont accès.

7 votes

Les constructeurs de fonctions sont utilisés comme des classes, il n'y a pas de class mot-clé mais vous pouvez faire à peu près la même chose.

1 votes

Il y a en quelque sorte un mot-clé classe - classe est réservé pour une utilisation future.

11 votes

C'est d'ailleurs la raison pour laquelle on utilise .className et non .class pour définir une classe CSS.

29voto

Michael Points 4361

JavaScript es un langage de programmation orienté objet et il est utilisé exactement pour créer des instances. Il est basé sur des prototypes, plutôt que sur des classes, mais cela ne signifie pas qu'il n'est pas orienté objet.

9 votes

J'aime à dire que JavaScript semble être encore plus orienté objet que tous ces langages basés sur des classes. En JavaScript, tout ce que vous écrivez devient immédiatement un objet, alors que dans les langages à base de classes, vous écrivez d'abord des déclarations et ce n'est que plus tard que vous créez des instances spécifiques (objets) de classes. Et le prototype JavaScript semble rappeler vaguement tous ces trucs VTABLE pour les langages basés sur des classes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X