2013-04-19 8 views
22

Ho visto alcuni modi diversi per creare un'istanza di oggetti in javascript, volevo sapere i vantaggi/gli svantaggi dei vari approcci e perché dovresti usarne uno sull'altro.Javascript che crea oggetti: approcci multipli, differenze?

Approccio 1

var obj = { 
    prop: value, 
    . 
    . 
    . 
} 

Approccio uno è l'approccio standard, niente di nuovo :)

Approccio 2

var obj = new function() { 
    var prop1 = value1; 
    var fn1 = function() { 
    }; 
    . 
    . 
    . 

    this.prop2 = value2; 
    . 
    . 
    . 
}(); 

L'approccio funzioni, ho voluto confrontare questo approccio con approccio 3. L'approccio funzione è principalmente utilizzato per l'incapsulamento (correggere?)

Approach 3

var obj = (function() { 
    var prop1 = value1; 
    var fn1 = function() { 
    }; 
    . 
    . 
    . 

    return { 
     prop2: value2, 
     . 
     . 
     . 
    } 
})(); 

Con questo approccio, non ho ben vedere il ragionamento dietro il suo utilizzo. In che cosa differisce dall'approccio 2? Entrambi possono essere utilizzati per incapsulare la logica.

È così che possiamo passare i parametri, in modo che possiamo affrontare eventuali conflitti potenziali ?? E.g jquery's $ sintassi - ma è anche possibile farlo con approccio 2 ...

Grazie.


Edit:


sono consapevole l'approccio 1 e 3 sono simili (nel senso che entrambi gli oggetti di ritorno), tuttavia avvicinarsi 3 crea anche una chiusura. Quale approccio 2 fa anche.

Questa è la base della mia domanda in realtà, sia il 2 che il 3 creano chiusure, ma qual è la differenza tra loro.

+0

In Approccio 2 la parola chiave 'new' non dovrebbe essere lì. – Halcyon

+2

@FritsvanCampen - Sì, dovrebbe. Questo crea un nuovo oggetto dalla funzione di costruzione (anonima). –

+1

se la parola chiave 'new' non è lì, sarebbe una classe. – macool

risposta

10

Negli approcci n. 2 e n. 3 la proprietà constructor degli oggetti risultanti sarà diversa.

In pratica significa che il secondo approccio consente di effettuare istanze più di un oggetto utilizzando la funzione di costruzione anonima:

x = new function() { alert(1) }; 
y = new x.constructor; // shows the message too 

La risposta superiore per Module pattern vs. instance of an anonymous constructor include una citazione da Douglas Crockford in cui spiega perché pensa che l'approccio # 3 sia migliore del # 2.

+0

Bello. Non avevo pensato alla proprietà 'constructor'. –

0

Non c'è molta differenza tra gli approcci 2 e 3 per gli oggetti unici. (Se dovessi nominare la funzione usata nell'approccio 2, avresti definito un costruttore riutilizzabile.) La mia impressione è che l'approccio 3 sia più comunemente usato per queste situazioni, ma non vedo una grande differenza tra loro.

Si deve notare che entrambi gli approcci 2 e 3 possono prendere argomenti:

var approach2Obj = new function(formalArg) { 
    var privateProp = ...; 
    this.publicProp = ...; 
    // more constructor logic 
)(actualArg); 

var approach3Obj = (function(formalArg) { 
    var privateProp = ...; 
    // more creation logic 
    return { 
     publicProp : ...; 
    }; 
}(actualArg)); 

P.S. Come @Alexey Lebedev points out in his answer, una differenza tra i due (forse l'unico) è che approach2Obj.constructor e approach3Obj.constructor saranno diversi. approach3Obj.constructor sarà identicamente Object, mentre approach2Obj.constructor sarà la funzione anonima.

+0

Scusa, in sostanza, prop1 indica variabili private. La logica della funzione può continuare e utilizzare queste variabili ... Aggiornerò per riflettere questo – Umair

+0

@Umair - Non credo che la mia risposta cambi. Gli approcci 2 e 3 sono fondamentalmente equivalenti. –

4

Il primo e il terzo approccio sono quasi gli stessi, in un modo entrambi creano un oggetto letterale, che è figlio diretto della classe Object.La differenza tra i due è che nel terzo approccio si può avere un qualche tipo di incapsulamento di proprietà:

var obj = (function() { 
    var prop = {}; 

    return { 
     prop2: function(){ return prop }; 
    } 
})(); 

vista delle prestazioni si potrebbe prendere in considerazione che il terzo approccio crea chiusura, mentre il primo non lo fa!

Tuttavia nel secondo approccio si sta semplicemente creando un nuovo oggetto da una classe anonima che non è un figlio diretto della classe Object.

La forma corretta del secondo approccio è presente (almeno questo è standard ECMA):

var obj = new function() { 
    var prop1 = value1; 

    this.prop2 = value2; 
}(); 

La differenza tra l'approccio 2 e 3 è solo la catena di ereditarietà: (supponendo obj2 è dal 2 avvicinamento e obj3 è dal 3 approccio)

obj2.__proto__ == Object.prototype; // false 
obj3.__proto__ == Object.prototype; // true 

obj2 è stato creato da una classe anonima stessa:

obj2.__proto__.__proto__ == Object.prototype; // true (there's 2 level of inheritance here) 
+0

Cosa intendi per "bambino diretto"? –

+1

qualsiasi oggetto letterale è ereditato direttamente da 'Object.prototype' che lo rende diretto figlio della classe' Object': 'obj .__ proto__ == Object.prototype' –

0

La tua domanda dovrebbe essere 2 Approcci perché Approccio 3 è esattamente come Approccio 1 solo il modo per crearlo è la funzione di auto esecuzione.

Circa la differenza quando si crea un oggetto come approccio 1 si può pensare ad esso come un oggetto con solo la funzione statica come in java. quindi è sempre viva e non si fanno esempio fuori di esso (simile a Singleton) - in modo che quando si effettua questo oggetto:

var obj = { 
    prop: value, 
    func: function(){ 
    alert(this.prop); 
    } 
}; 

si può chiamare immediatamente:

obj.prop = 'something else'; 
obj.func(); 

Approccio 2 (senza il nuovo, come il commento avete ottenuto) è un oggetto classico, che è possibile creare istanze - fare ereditare (con "trucchi" js) e così via:

function Person(firstName,lastName){ // or var Person = function(... 
    this.firstName = firstName; 
    this.lastName= lastName; 

    this.getFullName = function(){ 
     return this.firstName + ' ' + this.lastName; 
    } 
} 

//use 
var person1 = new Person('yair','lapid'); 
var person2 = new Person('Naftali','Bennet'); 

you can put it in an array etc... 
var arr = [person1,person2, new Person('shelly','yekimovits')]; 
+0

L'approccio 3 crea una chiusura; l'approccio 1 no. Questo li rende piuttosto diversi. –

+0

Ma non è questa la domanda - puoi chiamare anche una funzione regolare che restituisce un oggetto o un aeroplano che restituisce un oggetto - chiede la differenza di creazione degli oggetti - e questa non è la definizione corretta di chiusura btw ... – Adidi

2

Approccio 1
Questo è un singolo oggetto, nessuna classe e non è possibile definire in modo più facile se è complesso

var obj = { 
    prop: value 
} 

Approccio 2
Una funzione non anonima.Si creerà un oggetto su un 'classe', normalle la funzione viene salvato come un nome di classe e può creare più oggetti dello stesso tipo facilmente come di seguito:

var Bycicle= function() { 
    var prop1 = value1; 

    this.prop2 = value2; 
} 
var obj1 = new Bycicle(), 
    obj2 = new Bycicle(); 

Approach 3
una funzione anonima , variabili dall'esterno la funzione non può interferire con le variabili all'interno della funzione:

var a = 10; 
var obj = (function() { 
    alert(a); // Alerts undefined 
    var prop1 = value1; 
    alert(prop1); // alerts the value of value1 
    return { 
     prop2: value2; 
    } 
})(); // Within the() you can pass arguments to the anonymous function. 

Ulteriori su funzioni anonime: http://helephant.com/2008/08/23/javascript-anonymous-functions/

Altri approcci
V'è anche un Object.create() e un new Object() per creare nuovi oggetti, che entrambi sono gli stessi Approach 1.

Conclusione
Alla fine, l'oggetto sarà sempre lo stesso, tranne per il 3 °, perché è anonimo.

0

Per comprendere l'approccio 2, il lettore deve conoscere alcune cose piuttosto tecniche sul modo in cui la nuova parola chiave funziona. Nello specifico, chiamerà la funzione anonima come costruttore, invece di istanziare un nuovo oggetto funzione e scaricarlo nella variabile obj.

Per comprendere l'approccio 3, il lettore deve solo capire il modello IIFE. Quel modello è diventato molto comune nel codice javascript negli ultimi due anni, e questo è probabilmente il motivo per cui quella versione è più comunemente usata.

Entrambe le versioni sono utilizzate per produrre l'incapsulamento ed entrambe le versioni richiedono la conoscenza di una caratteristica di linguaggio complessa da comprendere. Tuttavia, la caratteristica linguistica richiesta nell'approccio tre è più comunemente nota della funzionalità linguistica richiesta per comprendere l'approccio due. Ecco perché l'approccio tre è più comunemente usato in natura.

+0

Un collaboratore una volta rimuovere la parola chiave 'new' da un costruttore anonimo perché pensava che fosse un errore di battitura. –

2

C'è anche:

var obj = Object.create({prop: ...}); 

Questo funziona impostando un prototipo. È molto più efficiente utilizzare un prototipo se si hanno più oggetti che condividono proprietà o metodi.

var proto = {foo: function() {}}, 
    obj1 = Object.create(proto), 
    obj2 = Object.create(proto), 
    obj3 = {foo: function() {}}, 
    obj4 = {foo: function() {}}; 

In questo esempio, obj1 e obj2 condividono una funzione "foo", definita in "proto". Nel frattempo, obj3 e obj4 hanno ciascuno il proprio "foo". Se stai creando molti oggetti con molte proprietà, questo può fare una grande differenza nel consumo di memoria e persino nelle prestazioni.

Questo vantaggio è condiviso dall'utilizzo della parola chiave "new" se si utilizza una funzione denominata e si assegnano le proprietà al prototipo della funzione (ad esempio: f.prototype.prop) prima di utilizzare new.

16

7 modi per creare oggetti in JavaScript:

1. Oggetto del costruttore

Il modo più semplice per creare un oggetto è quello di utilizzare la funzione di costruzione dell'oggetto: vista plainprint?

var person = new Object(); 
person.name = "Diego"; 
person.getName = function(){ 
    return this.name; 
}; 

2. letterale notazione

vista plainprint?

var person = { 
    person.name : "Diego", 
    person.getName : function(){ 
     return this.name; 
    } 
} 

3. funzione fabbrica

La funzione di fabbrica permette di incapsulare e riutilizzare la logica per creare oggetti simili. Sfrutta qualsiasi costrutto precedente per questo. O: visualizza plainprint?

var newPerson=function(name){ 
    var result = new Object(); 
    result.name = name; 
    result.getName = function(){ 
     return this.name; 
    }; 
    return result; 
}; 
var personOne = newPerson("Diego"); 
var personTwo = newPerson("Gangelo"); 
console.log(personOne.getName()); // prints Diego 
console.log(personTwo.getName()); // prints Gangelo 

Oppure:

view plainprint? 
var newPerson=function(name){ 
    return { 
     person.name : name, 
     person.getName : function(){ 
      return this.name; 
     }; 
}; 
var personOne = newPerson("Diego"); 
var personTwo = newPerson("Gangelo"); 
console.log(personOne.getName()); // prints Diego 
console.log(personTwo.getName()); // prints Gangelo 

4. funzione di costruzione

in JavaScript è possibile chiamare qualsiasi funzione con il nuovo operatore di fronte ad essa. Data una funzione F, per la nuova F(): viene creato un nuovo oggetto vuoto X. X è impostato come contesto per il significato F in tutto F che punta a X. X viene restituito come risultato della vista grafica di F ?

function Person(name){ 
     this.name = name; 
     this.getName = function(){ 
      return this.name; 
     }; 
}; 
var personOne = new Person("Diego"); 
console.log(personOne.getName()); // prints Diego 
console.log(personOne instanceOf Person); // prints true 
console.log(personOne.constructor === Person); // prints true 
console.log(personOne instanceOf Object); // prints true 

5. Prototipo

funzioni sono molto speciale in Javascript. Sono oggetti, possono creare altri oggetti e ottengono automaticamente un campo chiamato prototipo. Un prototipo è un oggetto semplice con un singolo campo, chiamato costruttore, che punta alla funzione stessa. Ciò che lo rende speciale è che ogni oggetto creato attraverso una funzione eredita il prototipo della funzione. vedi documento?

function Person(){}; 
Person.prototype.name = "Diego"; 
var personOne = new Person(); 
var personTwo = new Person(); 
console.log(personOne.constructor == Person); // prints true 
console.log(personOne.name); // prints Diego 
console.log(personTwo.constructor == Person); // prints true 
console.log(personTwo.name); // prints Diego 

6. Funzione/combinazione Prototipo

La combinazione funzione/prototipo, come si potrebbe immaginare, si avvale di entrambi gli approcci :) vista plainprint?

function Person(name){ 
     this.name = name; 
}; 
Person.prototype.getName = function(){ 
      return this.name; 
     }; 
var personOne = new Person("Diego"); 
var personTwo = new Person("Filippo"); 
console.log(personOne.getName()); // prints Diego 
console.log(personTwo.getName()); // prints Filippo 
console.log(personOne.getName === personTwo.getName) //prints true 

7. Singleton

A volte, si consiglia di fare in modo che solo una singola istanza di una certa classe esiste. Per ottenere un Singleton in Javascript è semplice come definire e richiamare il costruttore allo stesso tempo: visualizza plainprint?

var singleton = new function(){ 
    this.name = "ApplicationName"; 
}; 
+0

cosa significa "visualizza plainprint?" significa anche? – Taurus