È un ottimo momento per JavaScript. Non solo sta diventando una lingua molto più rispettata, ma sta anche crescendo a passi da gigante - sia in termini di popolarità che di funzionalità. Man mano che altri browser iniziano a implementare le funzionalità dello standard ECMAScript 5th edition, JavaScript diventa una piattaforma ancora più potente su cui sviluppare. In questo tutorial parleremo dei nuovi metodi disponibili.
ECMAScript è il nome ufficiale di ciò che tutti chiamiamo JavaScript. Ciò non significa che abbiamo torto; è solo che il nome "JavaScript" è un marchio di fabbrica di Oracle; così Ecma International (in origine l'European Computer Manufacturers Association - da qui l'ECMA) usa il termine "ECMAScript" per riferirsi allo standard di JavaScript. L'ultima versione di questo standard è la quinta edizione ed è stata approvata poco più di un anno fa (il 3 dicembre 2009). Comprende una vasta gamma di grandi aggiunte e molte di queste stanno iniziando a essere visualizzate nei browser. Le implementazioni di ECMAScript 5 sono chiamate JavaScript 1.8.5.
In questo tutorial, esamineremo le funzioni di JavaScript 1.8.5 che sono a nostra disposizione nelle beta di Firefox 4. Sarai felice di scoprire che la maggior parte delle ultime versioni di altri browser hanno anche questi ... tranne uno. Questa volta, è Opera, come IE9 ha incluso molti di questi.
Questo metodo è molto importante; pulisce davvero l'eredità prototipale. In precedenza (in ECMAScript 3a edizione), per creare un oggetto e impostarne il prototipo, dovresti fare qualcosa del genere:
funzione Cat (nome) this.name = nome; this.paws = 4; this.hungry = false; this.eaten = []; Cat.prototype = costruttore: Cat, play: function () this.hungry = true; ritorna "giocando!"; , feed: function (food) this.eaten.push (cibo); this.hungry = false; , speak: function () return "Meow";
Sono l'unico a pensare che sembra strano avere il prototipo al di fuori la funzione del costruttore? E l'ereditarietà diventa ancora più caotica. Con Object.create
, le cose diventano molto più facili. Quanto sopra potrebbe essere codificato in questo modo:
var dog = nome: "cane", zampe: 4, affamato: falso, mangiato: null, play: function () this.hungry = true; ritorna "giocando!"; , feed: function (food) if (! this.eaten) this.eaten = []; this.eaten.push (cibo); this.hungry = false; , speak: function () return "Woof!" ; var my_dog = Object.create (cane);
Quello che sta succedendo qui è questo: sto chiamando object.create
, passandogli un oggetto da utilizzare come prototipo del nuovo oggetto Object.create
sta tornando. Quando si usa Object.create
, Non devo preoccuparmi di definire il prototipo separatamente. In effetti, ho molta più flessibilità per decidere come procedere per creare ed ereditare oggetti. Ad esempio, non riesco a mettere il mangiato
array sul prototipo, perché un array è un valore di riferimento, quindi ogni oggetto creato da cane
condividerò quell'array. Ho deciso di controllarlo prima di usarlo qui, ma se volessi avvolgere Object.create (cane)
in un make_dog
funzione, potrei assegnarlo lì altrettanto facilmente.
Questo è il bello Object.create
; puoi scegliere come farlo.
C'è un secondo parametro Object.create
prende; è un oggetto descrittore di proprietà. È un po 'complicato, ma è anche una parte della prossima funzione che vedremo, quindi diamo un'occhiata.
Se hai un oggetto su cui vuoi definire una proprietà, probabilmente lo farai in questo modo:
my_dog.age = 2;
Funziona ancora bene con ES5, ma se vuoi un controllo più preciso, puoi farlo con Object.defineProperty
. Il primo parametro è l'oggetto a cui stai assegnando la proprietà. Il secondo parametro è il nome della proprietà, come una stringa. La proprietà finale è l'oggetto descrittore. Ecco come funziona. È (ovviamente) un oggetto e può avere una combinazione delle seguenti proprietà, ognuna delle quali descrive la proprietà che stiamo aggiungendo:
non definito
.vero
. Predefinito a falso
.vero
. Predefinito a falso
.falso
.non definito
.non definito
.Si noti che i valori predefiniti per le opzioni booleane sopra riportate sono il contrario del vecchio obj.prop = val
standard. Inoltre, sappi che non puoi definire valore
o scrivibile
quando ottenere
o impostato
sono definiti e viceversa.
Quindi, come useresti questo? Prova questo:
// presume my_dog da sopra Object.defineProperty (my_dog, "age", set: function (age) this.human_years = age * 7;, get: function () return this.human_years / 7;, enumerable : vero ); my_dog.age = 2; my_dog.human_years; // 14
A parte il fatto che gli anni del cane non sono in realtà 7 anni umani, dovresti notare che non abbiamo impostato valore
o scrivibile
qui, perché stiamo usando ottenere
e impostato
. Queste funzioni non sono mai accessibili direttamente. Sono "magicamente" corri dietro le quinte quando assegni o chiedi una proprietà. In questo esempio, sto usando queste funzioni per mantenere età
e human_years
in "sync". Se non si desidera che il valore "other" sia accessibile, è possibile utilizzare una funzione anonima di auto-richiamo per nasconderlo con la chiusura:
Object.defineProperty (my_dog, "age", (function () var human_years; return set: function (age) human_years = age * 7;, get: function () return human_years / 7;, enumerable: vero ; ()));
Certo, non c'è niente che ti impedisca di fare qualcosa di stupido dentro ottenere
o impostato
, quindi usalo saggiamente.
È possibile utilizzare un modulo dell'oggetto descrittore di proprietà per aggiungere proprietà agli oggetti Object.create
. Fallo come segue:
var your_dog = Object.create (dog, age: get: function () / * ... * /, set: function () / * ... * /, enumerable: true, gender: value: " femmina ");
Basta usare il nome della proprietà come proprietà dell'oggetto descrittore; quindi, imposta gli attributi tramite un oggetto nel valore.
Se si desidera definire più proprietà contemporaneamente, è possibile utilizzare un oggetto descrittore di proprietà proprio come con Object.create
per definirli, usando Object.defineProperties
.
Object.defineProperties (my_dog, age: get: function () / * ... * /, set: function () / * ... * /, enumerable: true, gender: value: "female" );
Avrai voglia di notare - per il raro caso in cui non utilizzi un oggetto letterale come secondo parametro - che verranno utilizzate solo le proprietà enumerabili dell'oggetto properties.
Se si desidera conoscere le specifiche di una proprietà, è possibile utilizzare questa funzione, Object.getOwnPropertyDescriptor
. Prendi nota del "Proprio"; questo funziona solo con le proprietà sull'oggetto stesso, non sulla sua catena di prototipi.
var person = name: "Joe"; Object.getOwnPropertyDescriptor (person, "name"); // configurabile: true, enumerable: true, value: "Joe", scrivibile: true
Come puoi vedere, questo funziona con le proprietà impostate sia nel vecchio che nel nuovo modo. Object.getOwnPropertyDescriptor
prende due parametri: l'oggetto e il nome della proprietà come una stringa.
Hai mai voluto ottenere tutte le chiavi di un oggetto? Ora puoi farlo facilmente con Object.keys
. Passa a questa funzione un oggetto e restituirà una matrice di tutte le proprietà enumerabili di quell'oggetto. Puoi anche passargli una matrice, e otterrai una serie di indici.
var horse = name: "Ed", età: 4, lavoro: "saltando", proprietario: "Jim"; var horse_keys = Object.keys (cavallo); // ["nome", "età", "lavoro", "proprietario"];
Questo è proprio come Object.keys
, tranne che include tutte le proprietà, anche quelle non sono enumerabile. Con il nome della funzione più lungo, puoi dire che scoraggiano l'uso di esso. Di solito, vorresti chiavi
anziché.
Se hai mai desiderato creare una funzione che non accetta nuovi parametri, puoi farlo ora. Gestisci il tuo oggetto Object.preventExtensions
, e rifiuterà tutti i tentativi di aggiungere nuovi parametri. Questa funzione va di pari passo con Object.isExtensible
, che ritorna vero
se puoi estendere l'oggetto e falso
se non puoi.
var product = name: "Foobar", valutazione: 3.5; Object.isExtensible (prodotto); // true Object.preventExtentions (prodotto); Object.isExtensible (prodotto); // false product.price = "$ 10.00"; // non funziona product.price; // non definito
Si noti che tutte le proprietà sull'oggetto al momento dell'esecuzione Object.preventExtensions
può ancora essere cambiato o cancellato (assumendo che i loro attributi lo consentano).
Sigillare un oggetto è un passo avanti rispetto alla prevenzione delle estensioni. Un oggetto sigillato non ti consente di aggiungere o eliminare proprietà o di modificare le proprietà da un valore (come una stringa) a un accessorio (un metodo) o viceversa. Sarai comunque in grado di leggere e scrivere proprietà, ovviamente. Puoi scoprire se un oggetto è sigillato usando Object.isSealed
.
var pet = nome: "Browser", digitare: "dog"; Object.seal (pet); pet.name = "Oreo"; pet.age = 2; // non funziona pet.type = function () / ** /; // non funziona delete pet.name; // non funziona
Congelarlo ancora un altro passo avanti. Un oggetto congelato non può essere modificato in alcun modo; è di sola lettura. Puoi verificare il congelamento di un oggetto con, hai indovinato, Object.isFrozen
.
var obj = saluto: "Ciao!" ; Object.freeze (obj); Object.isFrozen (obj); // vero
Penseresti che non sarebbe troppo difficile determinare che una determinata variabile sia una matrice. Dopotutto, tutto il resto funziona bene con tipo di
operatore. Tuttavia, gli array JavaScript sono di tipo inconsistente. In realtà sono oggetti simili ad array più vicini (anche se di solito usiamo questo termine per riferirci a cose come argomenti
e NodeList
S). Questa funzione ti dà il modo di essere sicuro al 100% che quello con cui stai lavorando è un array. Passa una variabile e restituisce il valore booleano.
var names = ["Collis", "Cyan"]; Array.isArray (nomi); // vero
Per ulteriori informazioni sul motivo per cui abbiamo bisogno di questa funzione, controlla i documenti, collegati qui sotto.
Questo non è troppo grande, ma se vuoi memorizzare le date in JSON, potresti trovarlo utile. Gli oggetti data ora hanno un toJSON
funzione che convertirà la data in una data stringa JSON.
new Date (). toJSON (); // "2010-12-06T16: 25: 40.040Z"
Probabilmente hai familiarità con l'utilizzo chiamata
e applicare
riassegnare il valore di Questo
in una funzione.
var arr1 = ["1", "2", "3"], arr2 = ["4", "5", "6"]; Array.prototype.push.apply (arr1, arr2);
Questi metodi ti permettono di cambiare il valore di Questo
all'interno di una funzione. Se vuoi fare qualcosa di simile spesso, Function.prototype.bind
restituisce una nuova funzione con Questo
legato a qualsiasi cosa tu passi, così puoi salvarlo su una variabile.
var tooltip = text: "Fai clic qui per ...", overlay = text: "Inserisci il numero di partecipanti"; function show_text () // davvero, fai qualcosa di più utile qui console.log (this.text); tooltip.show = show_text.bind (tooltip); tooltip.show (); overlay.show = show_text.bind (overlay); overlay.show ();
Naturalmente, questo potrebbe non essere l'esempio più pratico, ma ti dà l'idea!
Quelle sono le funzioni ECMAScript 5th Edition (o JavaScript 1.8.5) che sono state aggiunte alle beta di Firefox 4. Ci sono alcune altre modifiche a JavaScript che stanno implementando, che puoi verificare nelle note di rilascio.
Tuttavia, ci sono un sacco di funzioni di ECMAScipt 5 che erano già supportate in Firefox 3 e in molti altri browser. Hai giocato con qualcuno di questi?
Nota: questi sono collegati alla loro documentazione MDN.
Se vuoi vedere quali browser e versioni supportano queste funzioni, puoi consultare questa tabella di compatibilità, creata da Juriy Zaytsev (Kangax). La cosa bella della maggior parte di queste funzioni è che se un browser non lo supporta, di solito puoi aggiungere il supporto, con qualcosa di simile a questo:
if (typeof Object.create! == 'function') Object.create = function (o) function F () F.prototype = o; ritorna nuovo F (); ; // Per gentile concessione di Douglas Crockford: http://javascript.crockford.com/prototypal.html
La gran quantità di nuove funzioni che abbiamo visto qui è solo una piccola parte della bontà aggiunta allo standard ECMAScript nella quinta edizione. Ci sono altre funzionalità che stai specificatamente non vedendo l'ora di usare, o forse addirittura usare adesso? Andiamo qui nei commenti!