Ich habe tief gegraben, um dieses spezielle Verhalten zu verstehen, und ich glaube, ich habe eine gute Erklärung gefunden.
Bevor ich document.getElementById
erkläre , warum Sie keinen Alias verwenden können , werde ich versuchen zu erklären, wie JavaScript-Funktionen / -Objekte funktionieren.
Wenn Sie eine JavaScript-Funktion aufrufen, bestimmt der JavaScript-Interpreter einen Bereich und übergibt ihn an die Funktion.
Betrachten Sie folgende Funktion:
function sum(a, b)
{
return a + b;
}
sum(10, 20); // returns 30;
Diese Funktion wird im Fensterbereich deklariert. Wenn Sie sie aufrufen, ist der Wert this
innerhalb der Summenfunktion das globale Window
Objekt.
Für die 'Summen'-Funktion spielt es keine Rolle, welchen Wert' dies 'hat, da sie nicht verwendet wird.
Betrachten Sie folgende Funktion:
function Person(birthDate)
{
this.birthDate = birthDate;
this.getAge = function() { return new Date().getFullYear() - this.birthDate.getFullYear(); };
}
var dave = new Person(new Date(1909, 1, 1));
dave.getAge(); //returns 100.
Wenn Sie dave.getAge Funktion aufrufen, sieht der JavaScript - Interpreter , dass Sie getAge Funktion auf dem fordern dave
Objekt, so setzt sie this
auf dave
und ruft die getAge
Funktion. getAge()
wird korrekt zurückkehren 100
.
Möglicherweise wissen Sie, dass Sie in JavaScript den Bereich mithilfe der apply
Methode angeben können . Lass es uns versuchen.
var dave = new Person(new Date(1909, 1, 1)); //Age 100 in 2009
var bob = new Person(new Date(1809, 1, 1)); //Age 200 in 2009
dave.getAge.apply(bob); //returns 200.
In der obigen Zeile übergeben Sie den Bereich manuell als bob
Objekt , anstatt JavaScript den Bereich bestimmen zu lassen . getAge
wird jetzt zurückkehren 200
, obwohl Sie dachten, Sie hätten getAge
das dave
Objekt aufgerufen .
Was ist der Sinn all dieser Dinge? Funktionen werden "lose" an Ihre JavaScript-Objekte angehängt. ZB kannst du tun
var dave = new Person(new Date(1909, 1, 1));
var bob = new Person(new Date(1809, 1, 1));
bob.getAge = function() { return -1; };
bob.getAge(); //returns -1
dave.getAge(); //returns 100
Machen wir den nächsten Schritt.
var dave = new Person(new Date(1909, 1, 1));
var ageMethod = dave.getAge;
dave.getAge(); //returns 100;
ageMethod(); //returns ?????
ageMethod
Ausführung wirft einen Fehler! Was ist passiert?
Wenn Sie meine obigen Punkte sorgfältig lesen, werden Sie feststellen, dass die dave.getAge
Methode mit dave
als this
Objekt aufgerufen wurde, während JavaScript den 'Umfang' für die ageMethod
Ausführung nicht bestimmen konnte . Also hat es das globale "Fenster" als "dies" übergeben. Da window
keine birthDate
Eigenschaft vorhanden ist, schlägt die ageMethod
Ausführung fehl.
Wie kann ich das beheben? Einfach,
ageMethod.apply(dave); //returns 100.
Hat all das Sinn gemacht? Wenn dies der Fall ist, können Sie erklären, warum Sie keinen Alias verwenden können document.getElementById
:
var $ = document.getElementById;
$('someElement');
$
heißt mit window
asthis
und wenn die getElementById
Implementierung dies erwartet this
, schlägt document
sie fehl.
Um dies zu beheben, können Sie dies erneut tun
$.apply(document, ['someElement']);
Warum funktioniert es in Internet Explorer?
Ich kenne die interne Implementierung getElementById
in IE nicht, aber ein Kommentar in der jQuery-Quelle ( inArray
Methodenimplementierung) besagt, dass in IEwindow == document
. Wenn dies der Fall ist, document.getElementById
sollte Aliasing im IE funktionieren.
Um dies weiter zu veranschaulichen, habe ich ein ausführliches Beispiel erstellt. Schauen Sie sich die Person
Funktion unten an.
function Person(birthDate)
{
var self = this;
this.birthDate = birthDate;
this.getAge = function()
{
//Let's make sure that getAge method was invoked
//with an object which was constructed from our Person function.
if(this.constructor == Person)
return new Date().getFullYear() - this.birthDate.getFullYear();
else
return -1;
};
//Smarter version of getAge function, it will always refer to the object
//it was created with.
this.getAgeSmarter = function()
{
return self.getAge();
};
//Smartest version of getAge function.
//It will try to use the most appropriate scope.
this.getAgeSmartest = function()
{
var scope = this.constructor == Person ? this : self;
return scope.getAge();
};
}
Für die Person
obige Funktion getAge
verhalten sich die verschiedenen Methoden wie folgt.
Lassen Sie uns zwei Objekte mit der Person
Funktion erstellen .
var yogi = new Person(new Date(1909, 1,1)); //Age is 100
var anotherYogi = new Person(new Date(1809, 1, 1)); //Age is 200
console.log(yogi.getAge()); //Output: 100.
Die getAge-Methode ruft direkt das yogi
Objekt ab this
und gibt es aus 100
.
var ageAlias = yogi.getAge;
console.log(ageAlias()); //Output: -1
Der JavaScript-Interepreter setzt das window
Objekt auf this
und unsere getAge
Methode gibt zurück -1
.
console.log(ageAlias.apply(yogi)); //Output: 100
Wenn wir den richtigen Bereich festlegen, können Sie die ageAlias
Methode verwenden.
console.log(ageAlias.apply(anotherYogi)); //Output: 200
Wenn wir ein Objekt einer anderen Person übergeben, wird das Alter trotzdem korrekt berechnet.
var ageSmarterAlias = yogi.getAgeSmarter;
console.log(ageSmarterAlias()); //Output: 100
Die ageSmarter
Funktion hat das ursprüngliche this
Objekt erfasst, sodass Sie sich jetzt nicht mehr um die Bereitstellung des richtigen Bereichs kümmern müssen.
console.log(ageSmarterAlias.apply(anotherYogi)); //Output: 100 !!!
Das Problem dabei ageSmarter
ist, dass Sie den Bereich niemals auf ein anderes Objekt festlegen können.
var ageSmartestAlias = yogi.getAgeSmartest;
console.log(ageSmartestAlias()); //Output: 100
console.log(ageSmartestAlias.apply(document)); //Output: 100
Die ageSmartest
Funktion verwendet den ursprünglichen Bereich, wenn ein ungültiger Bereich angegeben wird.
console.log(ageSmartestAlias.apply(anotherYogi)); //Output: 200
Sie können weiterhin ein anderes Person
Objekt übergeben getAgeSmartest
. :) :)