Het is een geweldige tijd voor JavaScript. Niet alleen wordt het een veel meer gerespecteerde taal, maar het groeit ook met grote sprongen - zowel in populariteit als functies. Naarmate meer browsers de functies van de ECMAScript 5e editie standaard beginnen te implementeren, wordt JavaScript een nog krachtiger platform waarop u zich verder kunt ontwikkelen. In deze zelfstudie bespreken we de nieuwe methoden die voor u beschikbaar zijn.
ECMAScript is de officiële naam van wat we allemaal JavaScript noemen. Dat betekent niet dat we verkeerd zijn; het is gewoon dat de naam "JavaScript" een handelsmerk is van Oracle; dus gebruikt Ecma International (oorspronkelijk de European Computer Manufacturers Association -dus ECMA) de term "ECMAScript" om te verwijzen naar de standaard van JavaScript. De nieuwste versie van deze standaard is de 5e editie en werd iets meer dan een jaar geleden goedgekeurd (op 3 december 2009). Het omvat een groot aantal geweldige toevoegingen, en een aantal daarvan beginnen in browsers te verschijnen. De implementaties van ECMAScript 5 wordt JavaScript 1.8.5 genoemd.
In deze zelfstudie gaan we kijken naar de JavaScript 1.8.5-functies die voor ons beschikbaar zijn in de Firefox 4-bèta's. U zult blij zijn te ontdekken dat de meeste van de nieuwste versies van andere browsers deze ook hebben ... behalve één. Deze keer is het Opera, omdat IE9 er veel van heeft opgenomen.
Deze methode is erg belangrijk; het maakt prototypische erfenis echt schoon. Eerder (in ECMAScript 3e editie), om een object te maken en het prototype in te stellen, zou je zoiets als dit doen:
functie Cat (naam) this.name = name; this.paws = 4; this.hungry = false; this.eaten = []; Cat.prototype = constructor: Cat, play: function () this.hungry = true; terug "spelen!"; , feed: functie (voedsel) this.eaten.push (voedsel); this.hungry = false; , spreek: function () terug "Miauw";
Ben ik de enige die vindt dat het raar lijkt om het prototype te hebben buiten de constructorfunctie? En erven wordt nog rommeliger. Met Object.create
, dingen worden een stuk eenvoudiger. Het bovenstaande kan als volgt worden gecodeerd:
var dog = name: "dog", paws: 4, hungry: false, eaten: null, play: function () this.hungry = true; terug "spelen!"; , feed: function (food) if (! this.eaten) this.eaten = []; this.eaten.push (voedsel); this.hungry = false; , spreek: function () terug "Woof!" ; var my_dog = Object.create (hond);
Wat hier aan de hand is, is dit: ik bel object.create
, het doorgeven van een object om als het prototype van het nieuwe object dat te gebruiken Object.create
komt terug. Tijdens gebruik Object.create
, Ik hoef me geen zorgen te maken over het afzonderlijk definiëren van het prototype. In feite heb ik veel meer flexibiliteit om te beslissen hoe het gaat om het maken en erven van objecten. Ik kan het bijvoorbeeld niet plaatsen gegeten
array op het prototype, omdat een array een referentiewaarde is, dus elk object is gemaakt van hond
zal die array delen. Ik heb besloten het te controleren voordat ik het hier zou gebruiken, maar als ik het wilde verpakken Object.create (hond)
in een make_dog
functie, ik zou het daar net zo gemakkelijk kunnen toewijzen.
Dat is waar het goed in is Object.create
; je kunt kiezen hoe je het moet doen.
Er is een tweede parameter die Object.create
neemt; het is een eigenschappendescriptorobject. Het is een beetje ingewikkeld, maar het is ook een deel van de volgende functie die we zullen bekijken, dus laten we dat eens bekijken.
Als u een object heeft waarvoor u een eigenschap wilt definiëren, doet u dit waarschijnlijk op de volgende manier:
my_dog.age = 2;
Dit werkt nog steeds prima in ES5, maar als je wat meer fijnmazige besturing wilt, kun je het hebben Object.defineProperty
. De eerste parameter is het object waaraan u de eigenschap toewijst. De tweede parameter is de naam van de eigenschap, als een tekenreeks. De uiteindelijke eigenschap is het descriptor-object. Dit is hoe dat werkt. Het is (uiteraard) een object en het kan een combinatie van de volgende eigenschappen hebben, die allemaal de eigenschap beschrijven die we toevoegen:
onbepaald
.waar
. Standaardwaarden voor vals
.waar
. Standaardwaarden voor vals
.vals
.onbepaald
.onbepaald
.Merk op dat de standaardwaarden voor de booleaanse opties hierboven het omgekeerde zijn van het oude obj.prop = val
normen. Weet ook dat je niet kunt definiëren waarde
of beschrijfbaar
wanneer krijgen
of reeks
zijn gedefinieerd en vice versa.
Hoe zou je dit gebruiken? Probeer dit:
// neem mijn_dog van bovenaf Object.defineProperty (my_dog, "age", set: function (age) this.human_years = age * 7;, get: function () return this.human_years / 7;, opsombaar : true); my_dog.age = 2; my_dog.human_years; // 14
Afgezien van het feit dat hondenjaren niet echt 7 menselijke jaren zijn, zou je moeten opmerken dat we niet hebben vastgesteld waarde
of beschrijfbaar
hier, omdat we gebruiken krijgen
en reeks
. Deze functies zijn nooit rechtstreeks toegankelijk. Ze worden "magisch" achter de schermen weergegeven wanneer u een eigendom toewijst of aanvraagt. In dit voorbeeld gebruik ik deze functies om te behouden leeftijd
en human_years
in "sync." Als u niet wilt dat de "andere" waarde toegankelijk is, kunt u een anonieme, zichzelf aanroepende functie gebruiken om deze met sluiting te verbergen:
Object.defineProperty (my_dog, "age", (function () var human_years; return set: function (age) human_years = age * 7;, get: function () return human_years / 7;, opsombaar: true; ()));
Natuurlijk is er niets dat je ervan weerhoudt om iets stoms vanbinnen te doen krijgen
of reeks
, gebruik het dus verstandig.
U kunt een vorm van het eigenschapsdescriptorobject gebruiken om eigenschappen aan objecten toe te voegen Object.create
. Doe het als volgt:
var your_dog = Object.create (dog, age: get: function () / * ... * /, set: function () / * ... * /, enumerable: true, gender: value: " vrouw" );
Gebruik gewoon de eigenschapnaam als eigenschap van het descriptorobject; stel vervolgens de attributen in via een object in de waarde.
Als u meerdere eigenschappen tegelijkertijd wilt definiëren, kunt u een eigenschapbeschrijvingsobject gebruiken net als bij Object.create
om ze te definiëren, met behulp van Object.defineProperties
.
Object.defineProperties (my_dog, age: get: function () / * ... * /, set: function () / * ... * /, opsommen: true, gender: value: "female" );
U zult willen opmerken - voor het zeldzame geval dat u geen letterlijk object gebruikt als de tweede parameter - dat alleen de opsombare eigenschappen van het eigenschappenobject zullen worden gebruikt.
Als u ooit de details van een eigenschap wilt weten, kunt u deze functie gebruiken, Object.getOwnPropertyDescriptor
. Noteer het "Eigen"; dit werkt alleen met eigenschappen op het object zelf, niet in de prototypeketen.
var person = name: "Joe"; Object.getOwnPropertyDescriptor (persoon, "naam"); // configureerbaar: true, opumerable: true, value: "Joe", writable: true
Zoals u kunt zien, werkt dit met eigenschappen die zowel op de oude als op de nieuwe manier zijn ingesteld. Object.getOwnPropertyDescriptor
neemt twee parameters: het object en de eigenschapnaam als een tekenreeks.
Ooit al de sleutels van een object willen hebben? Nu kun je dat gemakkelijk doen met Object.keys
. Geef deze functie een object door, en het retourneert een array van alle opsombare eigenschappen van dat object. U kunt ook een array doorgeven en u krijgt een aantal indices terug.
var horse = name: "Ed", leeftijd: 4, job: "jumping", eigenaar: "Jim"; var horse_keys = Object.keys (paard); // ["naam", "leeftijd", "taak", "eigenaar"];
Deze is net zoals Object.keys
, behalve dat het alle eigenschappen bevat, zelfs degenen die dat zijn zijn niet opgesomd. Door de langere functienaam kun je vertellen dat ze het gebruik ervan ontmoedigen. Meestal wil je dat sleutels
in plaats daarvan.
Als u ooit een functie wilt maken die geen nieuwe parameters accepteert, kunt u dat nu doen. Laat je object door Object.preventExtensions
, en het zal alle pogingen weigeren om nieuwe parameters toe te voegen. Deze functie gaat hand in hand met Object.isExtensible
, welke terugkeert waar
als je het object kunt uitbreiden en vals
als je dat niet kunt.
var product = name: "Foobar", rating: 3,5; Object.isExtensible (product); // true Object.preventExtentions (product); Object.isExtensible (product); // false product.price = "$ 10.00"; // werkt niet product.price; // undefined
Houd er rekening mee dat alle eigenschappen van het object op het moment dat u het uitvoert Object.preventExtensions
kan nog steeds worden gewijzigd of verwijderd (ervan uitgaande dat hun kenmerken dat toestaan).
Het verzegelen van een object gaat een stap verder dan het voorkomen van extensies. Met een verzegeld object kunt u geen eigenschappen toevoegen of verwijderen, of eigenschappen van een waarde (zoals een tekenreeks) wijzigen in een accessor (een methode) of omgekeerd. Uiteraard kun je nog steeds eigenschappen lezen en schrijven. U kunt achterhalen of een object is verzegeld door het te gebruiken Object.isSealed
.
var pet = name: "Browser", type: "dog"; Object.seal (pet); pet.name = "Oreo"; pet.age = 2; // werkt niet pet.type = function () / ** /; // werkt niet delete pet.name; // werkt niet
Het nog een stap verder bevriezen. Een bevroren object kan op geen enkele manier worden veranderd; het is alleen-lezen. Je kunt de bevrorenheid van een object verifiëren met, je raadt het al, Object.isFrozen
.
var obj = groet: "Hallo!" ; Object.freeze (obj); Object.isFrozen (obj); // waar
Je zou denken dat het niet te moeilijk zou zijn om vast te stellen dat een gegeven variabele een array is. Immers, al het andere werkt prima met de soort van
operator. JavaScript-arrays zijn echter van inconsistente ilk. Het zijn eigenlijk dichterbij geplaatste array-achtige objecten (hoewel we die term gewoonlijk gebruiken om naar dingen als te verwijzen argumenten
en nodelist
s). Deze functie geeft je een manier om 100% zeker te zijn dat waar je mee werkt een array is. Geef het een variabele, en het geeft de booleaanse waarde.
var names = ["Collis", "Cyan"]; Array.isArray (namen); // waar
Kijk voor meer informatie over waarom we deze functie nodig hebben op de documenten die hieronder zijn gekoppeld.
Dit is niet te groot, maar als u ooit datums in JSON wilt opslaan, vindt u dit misschien handig. Datumobjecten hebben nu een toJSON
functie die de datum naar een JSON-stringdatum zal converteren.
nieuwe datum (). toJSON (); // "2010-12-06T16: 25: 40.040Z"
U bent waarschijnlijk bekend met het gebruik telefoontje
en van toepassing zijn
om de waarde van opnieuw toe te wijzen deze
in een functie.
var arr1 = ["1", "2", "3"], arr2 = ["4", "5", "6"]; Array.prototype.push.apply (arr1, arr2);
Met deze methoden kunt u de waarde van wijzigen deze
binnen een functie. Als je zoiets vaak wilt doen, Function.prototype.bind
geeft een nieuwe functie met deze
gebonden aan wat je doorgeeft, dus je kunt het opslaan in een variabele.
var tooltip = text: "Klik hier om ...", overlay = text: "Voer het aantal deelnemers in"; functie show_text () // echt, doe hier iets nuttigers console.log (this.text); tooltip.show = show_text.bind (tooltip); tooltip.show (); overlay.show = show_text.bind (overlay); overlay.show ();
Natuurlijk is dit misschien niet het meest praktische voorbeeld, maar het geeft je het idee!
Dat zijn de ECMAScript 5e editie (of JavaScript 1.8.5) functies die zijn toegevoegd aan de Firefox 4 bèta's. Er zijn nog enkele andere wijzigingen in JavaScript die ook worden geïmplementeerd, die u kunt bekijken in de release-opmerkingen.
Er zijn echter een aantal ECMAScipt 5-functies die al werden ondersteund in Firefox 3 en verschillende andere browsers. Heb je met een van deze gespeeld??
Opmerking: deze zijn gekoppeld aan hun MDN-documentatie.
Als je wilt zien welke browsers en versies deze functies ondersteunen, kun je deze compatibiliteitstabel raadplegen, gemaakt door Juriy Zaytsev (Kangax). Het leuke aan de meeste van deze functies is dat als een browser het niet ondersteunt, je meestal ondersteuning kunt toevoegen, met zoiets als dit:
if (typeof Object.create! == 'function') Object.create = function (o) function F () F.prototype = o; retourneer nieuwe F (); ; // Hoffelijkheid van Douglas Crockford: http://javascript.crockford.com/prototypal.html
De reeks nieuwe functies die we hier hebben bekeken, is eigenlijk maar een klein deel van de goedheid die in de 5e editie aan de ECMAScript-standaard is toegevoegd. Zijn er nog andere functies waar u specifiek op uitkijkt of misschien nu al gebruikt? Laten we het hier in de reacties plaatsen!