web-dev-qa-db-fra.com

Quel est le mot clé "nouveau" en JavaScript?

Le mot clé new en JavaScript peut être assez déroutant lorsqu'il est rencontré 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 problèmes cela résout-il?
  • Quand est-ce approprié et quand non?
1608
Alon Gubkin

Il fait 5 choses:

  1. Cela crée un nouvel objet. Le type de cet objet est simplement objet.
  2. Il définit la propriété interne, inaccessible, [[prototype]] (c'est-à-dire _ PROTO _) comme étant la propriété externe de la fonction constructeur , accessible, prototype objet (chaque objet fonction a automatiquement une propriété prototype).
  3. Cela fait que la variable this pointe sur le nouvel objet créé.
  4. Il exécute la fonction constructeur en utilisant le nouvel objet créé chaque fois que this est mentionné.
  5. Il renvoie le nouvel objet créé, à moins que la fonction constructeur ne retourne une référence d'objet non -null. Dans ce cas, cette référence d'objet est renvoyée à la place.

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

new ConstructorFunction(arg1, arg2)

Une fois cette opération effectuée, si une propriété non définie du nouvel objet est demandée, le script vérifie à la place l'objet [[prototype]] de l'objet. Voici comment obtenir quelque chose de similaire à l'héritage de classe traditionnel en JavaScript.

La partie la plus difficile à ce sujet est le point 2. Chaque objet (y compris les fonctions) possède cette propriété interne appelée [[prototype]]. Il peut seulement ​​être défini au moment de la création de l'objet, soit avec new, avec Object.create, soit en fonction du littéral (les fonctions par défaut sont Function .prototype, nombre en nombre.prototype, etc.). Il ne peut être lu qu'avec Object.getPrototypeOf (someObject). Il y a no une autre façon de définir ou de lire cette valeur.

Les fonctions, en plus de la propriété [[prototype]] masquée, ont également une propriété appelée prototype, et c’est à cela que vous pouvez accéder et modifier pour fournir des propriétés héritées. propriétés et méthodes pour les objets que vous créez.


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 car maintenant, tous les objets que vous créez avec new ObjMaker() semblent également avoir hérité de la propriété 'b'.

Si vous voulez quelque chose comme une sous-classe, alors 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 d'ordures à ce sujet avant de finalement trouver cette page , où cela s'explique très bien avec de jolis diagrammes.

2060
Daniel Howard

Supposons que vous ayez cette fonction:

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

Si vous appelez cela comme une fonction autonome, procédez comme suit:

Foo();

L'exécution de cette fonction ajoutera deux propriétés à l'objet window (A et B). Il l'ajoute à la window car window est l'objet qui a appelé la fonction lorsque vous l'exécutez ainsi, et this dans une fonction est l'objet qui a appelé la fonction. Au moins en Javascript. 

Maintenant, appelez-le comme ceci avec new:

var bar = new Foo();

Lorsque vous ajoutez new à un appel de fonction, il se produit qu'un nouvel objet est créé (uniquement var bar = new Object()) et que la variable this de la fonction pointe vers la nouvelle Object que vous venez de créer, au lieu de l'objet qui a appelé la fonction. Donc, bar est maintenant un objet avec les propriétés A et B. Toute fonction peut être un constructeur, cela n’a pas toujours de sens. 

369
JulianR

En plus de la réponse de Daniel Howard, voici ce que 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;
}

Tandis que

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

est équivalent à

var obj = new A(1, 2);
153
basilikum

Pour que les débutants comprennent mieux

essayez le code suivant dans la console du navigateur.

function Foo() { 
    return this; 
}

var a = Foo();       //returns window object
var b = new Foo();   //returns empty object of foo

a instanceof Window;  // true
a instanceof Foo;     // false

b instanceof Window;  // false
b instanceof Foo;     // true

Vous pouvez maintenant lire la réponse du wiki community :)

94
Anulal S

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

C'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 d’ECMAScript est que vous pouvez étendre la propriété avec la propriété .prototype afin que nous puissions faire quelque chose comme ...

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

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

33
meder omuraliev

JavaScript est un langage de programmation orienté objet, utilisé précisément pour la création d'instances. Il est basé sur un prototype plutôt que sur une classe, mais cela ne signifie pas qu'il n'est pas orienté objet.

26
Michael

Javascript est un langage de programmation dynamique qui prend en charge le paradigme de la programmation orientée objet et qui est utilisé pour créer de nouvelles instances d'objet.

Les classes ne sont pas nécessaires pour les objets - Javascript est un langage basé sur un prototype .

13
Greg

Il existe déjà de très bonnes réponses, mais j'en publie une nouvelle pour souligner mon observation sur le casIIIci-dessous à propos de ce qui se passe lorsque vous avez une instruction de retour explicite dans une fonction dont vous êtes new. Regardez ci-dessous les cas suivants:

Cas I :

var Foo = function(){
  this.A = 1; 
  this.B = 2;
};
console.log(Foo()); //prints undefined
console.log(window.A); //prints 1

Ci-dessus est un cas simple d’appel de la fonction anonyme indiquée par Foo. Lorsque vous appelez cette fonction, il retourne undefined. Comme il n'y a pas d'instruction de retour explicite, l'interpréteur JavaScript insère de force une instruction return undefined; à la fin de la fonction. Ici, la fenêtre est l’objet d’appel (contextuel this) qui obtient les nouvelles propriétés A et B.

Affaire II :

var Foo = function(){
  this.A = 1;
  this.B = 2;
};
var bar = new Foo();
console.log(bar()); //illegal isn't pointing to a function but an object
console.log(bar.A); //prints 1

Ici, l'interprète JavaScript qui voit le mot clé new crée un nouvel objet qui agit en tant qu'objet d'invocation (contextuel this) de la fonction anonyme indiquée par Foo. Dans ce cas, A et B deviennent des propriétés sur l'objet nouvellement créé (à la place de l'objet window). Comme vous n'avez aucune instruction de retour explicite, l'interpréteur JavaScript insère de force une instruction de retour pour renvoyer le nouvel objet créé en raison de l'utilisation du mot clé new.

Affaire III :

var Foo = function(){
  this.A = 1;
  this.B = 2;
  return {C:20,D:30}; 
};
var bar = new Foo();
console.log(bar.C);//prints 20
console.log(bar.A); //prints undefined. bar is not pointing to the object which got created due to new keyword.

Ici encore, l'interprète JavaScript qui voit le mot clé new crée un nouvel objet qui sert d'objet d'invocation (contextuel this) de la fonction anonyme indiquée par Foo. Encore une fois, A et B deviennent des propriétés sur l'objet nouvellement créé. Mais cette fois, vous avez une déclaration de retour explicite afin que l’interprète JavaScript ne fasse pas quelque chose en soi.

La chose à noter au cas oùIIIest que l’objet créé en raison du mot clé new a été perdu de votre radar. bar pointe en fait sur un objet complètement différent de celui créé par l'interpréteur JavaScript en raison du mot clé new.

3
RBT

parfois le code est plus facile que les mots:

var func1 = function (x) { this.x = x; }                    // used with 'new' only
var func2 = function (x) { var z={}; z.x = x; return z; }   // used both ways
func1.prototype.y = 11;
func2.prototype.y = 12;

A1 = new func1(1);      // has A1.x  AND  A1.y
A2 =     func1(1);      // undefined ('this' refers to 'window')
B1 = new func2(2);      // has B1.x  ONLY
B2 =     func2(2);      // has B2.x  ONLY

pour moi, tant que je ne prototype pas, j'utilise le style func2 car cela me donne un peu plus de flexibilité à l'intérieur et à l'extérieur de la fonction.

3
rsbkk

Le mot clé new sert à créer de nouvelles instances d'objet. Et oui, javascript est un langage de programmation dynamique, qui prend en charge le paradigme de la programmation orientée objet. La convention concernant la dénomination des objets est de toujours utiliser des majuscules pour les objets supposés être instanciés par le nouveau mot clé.

obj = new Element();
2
erenon

Le mot clé new modifie le contexte dans lequel la fonction est en cours d'exécution et renvoie un pointeur sur ce contexte. 

Lorsque vous n'utilisez pas le mot clé new, le contexte dans lequel la fonction Vehicle() est exécutée est identique à celui dans lequel vous appelez la fonction Vehicle. Le mot clé this fera référence au même contexte. Lorsque vous utilisez new Vehicle(), un nouveau contexte est créé pour que le mot clé this à l'intérieur de la fonction fasse référence au nouveau contexte. Ce que vous obtenez en retour, c'est le contexte nouvellement créé.

1
Juzer Ali

Bien, JavaScript peut différer considérablement d’une plate-forme à l’autre, car il s’agit toujours d’une implémentation de la spécification originale EcmaScript.

Dans tous les cas, indépendamment de l’implémentation, toutes les implémentations JavaScript qui suivent la spécification EcmaScript vous donneront un langage orienté objet. Selon le standard ES:

ECMAScript est un langage de programmation orienté objet pour effectuer des calculs et manipuler des objets de calcul dans un environnement hôte.

Donc, maintenant que nous sommes d’accord sur le fait que JavaScript est une implémentation d’EcmaScript, il s’agit donc d’un langage orienté objet. La définition de l'opération new dans tout langage orienté objet indique que ce mot clé est utilisé pour créer une instance d'objet à partir d'une classe d'un certain type (y compris les types anonymes, dans des cas tels que C #).

En EcmaScript, nous n'utilisons pas de classes, comme vous pouvez le lire dans les spécifications:

ECMAScript n'utilise pas de classes telles que celles en C++, Smalltalk ou Java. Au lieu de cela, les objets peuvent être créés de différentes manières, notamment via une notation littérale ou via des constructeurs qui créent des objets, puis exécutent du code qui initialise tout ou partie d’entre eux en affectant la valeur initiale les valeurs à leurs propriétés. Chaque constructeur est une fonction qui a un propriété nommée prototype ‖ utilisé pour mettre en œuvre un héritage basé sur un prototype et des propriétés partagées. Les objets sont créés par
utiliser des constructeurs dans de nouvelles expressions; par exemple, new Date (2009,11) crée un nouvel objet Date. Invoquer un constructeur sans utiliser new a des conséquences qui dépendent du constructeur. Par exemple, Date () produit une représentation sous forme de chaîne du date et heure actuelles plutôt qu’un objet.

1
João Pinho

Le mot clé new crée des occurrences d'objets à l'aide de fonctions en tant que constructeur. Par exemple:

var Foo = function() {};
Foo.prototype.bar = 'bar';

var foo = new Foo();
foo instanceof Foo; // true

Les instances héritent de la prototype de la fonction constructeur. Donc, étant donné l'exemple ci-dessus ...

foo.bar; // 'bar'
0
eyelidlessness

Résumé:

Le mot clé new est utilisé en javascript pour créer un objet à partir d'une fonction constructeur. Le mot clé new doit être placé avant l'appel de la fonction constructeur et effectuera les opérations suivantes:

  1. Crée un nouvel objet
  2. Définit le prototype de cet objet sur la propriété prototype de la fonction constructeur
  3. Lie le mot clé this au nouvel objet créé et exécute la fonction constructeur
  4. Retourne le nouvel objet créé

Exemple:

function Dog (age) {
  this.age = age;
}

const doggie = new Dog(12);

console.log(doggie);
console.log(doggie.__proto__ === Dog.prototype) // true

Qu'est-ce qui se passe exactement:

  1. const doggie dit: Nous avons besoin de mémoire pour déclarer une variable.
  2. L'opérateur d'assignation = dit: Nous allons initialiser cette variable avec l'expression après le =
  3. L'expression est new Dog(12). Le moteur JS voit le nouveau mot-clé, crée un nouvel objet et définit le prototype sur Dog.prototype
  4. La fonction constructeur est exécutée avec la valeur this définie sur le nouvel objet. À cette étape, l’âge est attribué au nouvel objet créé.
  5. L'objet nouvellement créé est renvoyé et affecté à la variable doggie.
0
Willem van der Veen