Qual è la “nuova” parola chiave in JavaScript?

La new parola chiave in JavaScript può essere abbastanza confusa quando viene rilevata per la prima volta, poiché le persone tendono a pensare che JavaScript non sia un linguaggio di programmazione orientato agli oggetti.

  • Che cos’è?
  • Quali problemi risolve?
  • Quando è appropriato e quando no?

Fa 5 cose:

  1. Crea un nuovo object. Il tipo di questo object è semplicemente object .
  2. Imposta la proprietà interna, inaccessibile, [[prototype]] (cioè __proto__ ) di questo object interno come object prototipo esterno, accessibile, della funzione di costruzione (ogni object funzione ha automaticamente una proprietà prototipo ).
  3. Rende this variabile punto all’object appena creato.
  4. Esegue la funzione di costruzione, utilizzando l’object appena creato ogni volta che viene menzionato.
  5. Restituisce l’object appena creato, a meno che la funzione di costruzione non restituisca un riferimento object non null . In questo caso, tale riferimento all’object viene invece restituito.

Nota: la funzione di costruzione fa riferimento alla funzione dopo la new parola chiave, come in

 new ConstructorFunction(arg1, arg2) 

Fatto ciò, se viene richiesta una proprietà non definita del nuovo object, lo script controllerà invece l’object [[prototype]] dell’object per la proprietà. È così che puoi ottenere qualcosa di simile all’ereditarietà di class tradizionale in JavaScript.

La parte più difficile a questo proposito è il punto numero 2. Ogni object (comprese le funzioni) ha questa proprietà interna chiamata [[prototype]] . Può essere impostato solo al momento della creazione dell’object, sia con nuovo , con Object.create , o basato sul letterale (funzioni predefinite su Function.prototype, numeri su Number.prototype, ecc.). Può essere letto solo con Object.getPrototypeOf (someObject) . Non c’è altro modo per impostare o leggere questo valore.

Le funzioni, oltre alla proprietà nascosta [[prototype]] , hanno anche una proprietà chiamata prototype , ed è questo che puoi accedere e modificare per fornire proprietà e metodi ereditati per gli oggetti che fai.


Ecco un esempio:

 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' 

È come l’ereditarietà delle classi perché ora, anche gli oggetti che usi usando il new ObjMaker() avranno ereditato la proprietà ‘b’.

Se vuoi qualcosa come una sottoclass, allora fai questo:

 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 

Ho letto una tonnellata di spazzatura su questo argomento prima di trovare finalmente questa pagina , dove questo è spiegato molto bene con dei buoni diagrammi.

Supponiamo di avere questa funzione:

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

Se lo chiami come una funzione autonoma in questo modo:

 Foo(); 

L’esecuzione di questa funzione aggiungerà due proprietà all’object della window ( A e B ). Lo aggiunge alla window perché la window è l’object che ha chiamato la funzione quando la si esegue in quel modo, e this in una funzione è l’object che ha chiamato la funzione. In Javascript almeno.

Ora chiamalo così con un new :

 var bar = new Foo(); 

Quello che succede quando aggiungi una new chiamata a una funzione è che viene creato un nuovo object (solo var bar = new Object() ) e che this all’interno della funzione punta al nuovo Object appena creato, anziché all’object che ha chiamato la funzione. Quindi bar ora è un object con le proprietà A e B Qualsiasi funzione può essere un costruttore, semplicemente non ha sempre senso.

Oltre alla risposta di Daniel Howard, ecco cosa fa (o almeno sembra) nuovo:

 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; } 

Mentre

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

è equivalente a

 var obj = new A(1, 2); 

Per i principianti per capirlo meglio

prova il seguente codice nella console del browser.

 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 

Ora puoi leggere la risposta wiki della community 🙂

quindi probabilmente non è per creare istanze di oggetti

È usato esattamente per quello. Si definisce un costruttore di funzioni in questo modo:

 function Person(name) { this.name = name; } var john = new Person('John'); 

Tuttavia, il vantaggio extra di ECMAScript è che puoi estendere con la proprietà .prototype , in modo che possiamo fare qualcosa come …

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

Tutti gli oggetti creati da questo costruttore ora avranno un getName causa della catena di prototipi a cui hanno accesso.

JavaScript è un linguaggio di programmazione orientato agli oggetti ed è usato esattamente per creare istanze. È basato su prototipi, piuttosto che su classi, ma ciò non significa che non sia orientato agli oggetti.

Javascript è un linguaggio di programmazione dinamico che supporta il paradigma di programmazione orientato agli oggetti e viene utilizzato per creare nuove istanze di oggetti.

Le classi non sono necessarie per gli oggetti – Javascript è un linguaggio basato su prototipi .

a volte il codice è più facile delle parole:

 var func1 = function (x) { this.x = x; } // used with 'new' only var func2 = function (x) { var z={}; zx = 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 

per me, finché non eseguo il prototipo, uso lo stile di func2 in quanto mi dà un po ‘più di flessibilità dentro e fuori la funzione.

La new parola chiave è per la creazione di nuove istanze di oggetti. E sì, javascript è un linguaggio di programmazione dinamico, che supporta il paradigma di programmazione orientato agli oggetti. La convenzione sulla denominazione degli oggetti è, usa sempre la maiuscola per gli oggetti che dovrebbero essere istanziati dalla nuova parola chiave.

 obj = new Element(); 

Ci sono già delle ottime risposte, ma ne sto postando una nuova per enfatizzare la mia osservazione sul caso III qui sotto su cosa succede quando hai un’istruzione esplicita sul rendimento in una funzione che stai facendo. Dai uno sguardo ai seguenti casi:

Caso I :

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

Sopra è un semplice caso di chiamare la funzione anonima indicata da Foo . Quando chiami questa funzione restituisce undefined . Poiché non esiste un’istruzione di ritorno esplicita, l’interprete JavaScript inserisce forzatamente un risultato return undefined; dichiarazione alla fine della funzione. Qui la finestra è l’object di invocazione (contestuale) che ottiene le nuove proprietà A e B

Caso 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 

Qui l’interprete JavaScript che vede la new parola chiave crea un nuovo object che funge da object di invocazione (contestuale) di funzione anonima puntata da Foo . In questo caso A e B diventano proprietà sull’object appena creato (al posto dell’object finestra). Dal momento che non hai alcuna dichiarazione di ritorno esplicita, l’interprete JavaScript inserisce forzatamente un’istruzione return per restituire il nuovo object creato a causa dell’uso di una new parola chiave.

Caso 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. 

Ancora una volta l’interprete JavaScript che vede la new parola chiave crea un nuovo object che funge da object di invocazione (contestuale) di funzione anonima puntata da Foo . Ancora, A e B diventano proprietà sull’object appena creato. Ma questa volta hai una dichiarazione di ritorno esplicita, quindi l’interprete JavaScript non farà nulla di proprio.

La cosa da notare nel caso III è che l’object che si sta creando a causa della new parola chiave è stato perso dal radar. bar indica effettivamente un object completamente diverso che non è quello che l’interprete JavaScript ha creato a causa della new parola chiave.

Beh, JavaScript per si può differire notevolmente da piattaforma a piattaforma in quanto è sempre un’implementazione della specifica originale EcmaScript.

In ogni caso, indipendentemente dall’implementazione di tutte le implementazioni di JavaScript che seguono le specifiche di EcmaScript, si otterrà un linguaggio orientato agli oggetti. Secondo lo standard ES:

ECMAScript è un linguaggio di programmazione orientato agli oggetti per eseguire calcoli e manipolare oggetti computazionali all’interno di un ambiente host.

Quindi ora che abbiamo concordato che JavaScript è un’implementazione di EcmaScript e quindi è un linguaggio orientato agli oggetti. La definizione della new operazione in qualsiasi linguaggio orientato agli oggetti, dice che tale parola chiave viene utilizzata per creare un’istanza di object da una class di un certo tipo (compresi i tipi anonimi, in casi come C #).

In EcmaScript non usiamo le classi, come puoi leggere dalle specifiche:

ECMAScript non usa classi come quelle in C ++, Smalltalk o Java. Invece gli oggetti possono essere creati in vari modi, anche tramite una notazione letterale o tramite costruttori che creano oggetti e quindi eseguono il codice che li inizializza tutti o parte di essi assegnando valori iniziali alle loro proprietà. Ogni costruttore è una funzione che ha una proprietà denominata – prototipo ‖ che viene utilizzata per implementare l’ereditarietà basata su prototipo e le proprietà condivise. Gli oggetti sono creati da
usare i costruttori in nuove espressioni; ad esempio, new Date (2009,11) crea un nuovo object Date. Il richiamo di un costruttore senza l’utilizzo di nuove ha conseguenze che dipendono dal costruttore. Ad esempio, Date () produce una rappresentazione di stringa della data e dell’ora corrente anziché di un object.

La new parola chiave modifica il contesto in cui viene eseguita la funzione e restituisce un puntatore a quel contesto.

Quando non si utilizza la new parola chiave, il contesto in cui viene eseguita la funzione Vehicle() è lo stesso contesto dal quale si chiama la funzione Vehicle . La parola chiave farà riferimento allo stesso contesto. Quando si utilizza il new Vehicle() , viene creato un nuovo contesto, quindi la parola chiave all’interno della funzione fa riferimento al nuovo contesto. Quello che ottieni in cambio è il contesto appena creato.

La new parola chiave crea istanze di oggetti usando le funzioni come costruttore. Per esempio:

 var Foo = function() {}; Foo.prototype.bar = 'bar'; var foo = new Foo(); foo instanceof Foo; // true 

Le istanze ereditano dal prototype della funzione di costruzione. Quindi dato l’esempio sopra …

 foo.bar; // 'bar' 

Sommario:

La new parola chiave viene utilizzata in javascript per creare un object da una funzione di costruzione. La new parola chiave deve essere posizionata prima della chiamata della funzione di costruzione e farà quanto segue:

  1. Crea un nuovo object
  2. Imposta il prototipo di questo object sulla proprietà prototype della funzione di costruzione
  3. Associa la parola chiave all’object appena creato ed esegue la funzione di costruzione
  4. Restituisce l’object appena creato

Esempio:

 function Dog (age) { this.age = age; } const doggie = new Dog(12); console.log(doggie); console.log(doggie.__proto__ === Dog.prototype) // true