Ich habe tief gegraben, um dieses spezielle Verhalten zu verstehen, und ich glaube, ich habe eine gute Erklärung gefunden.
Bevor ich document.getElementByIderklä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 thisinnerhalb der Summenfunktion das globale WindowObjekt.
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 daveObjekt, so setzt sie thisauf daveund ruft die getAgeFunktion. getAge()wird korrekt zurückkehren 100.
Möglicherweise wissen Sie, dass Sie in JavaScript den Bereich mithilfe der applyMethode 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 bobObjekt , anstatt JavaScript den Bereich bestimmen zu lassen . getAgewird jetzt zurückkehren 200, obwohl Sie dachten, Sie hätten getAgedas daveObjekt 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 ?????
ageMethodAusführung wirft einen Fehler! Was ist passiert?
Wenn Sie meine obigen Punkte sorgfältig lesen, werden Sie feststellen, dass die dave.getAgeMethode mit daveals thisObjekt aufgerufen wurde, während JavaScript den 'Umfang' für die ageMethodAusführung nicht bestimmen konnte . Also hat es das globale "Fenster" als "dies" übergeben. Da windowkeine birthDateEigenschaft vorhanden ist, schlägt die ageMethodAusfü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 windowasthis und wenn die getElementByIdImplementierung dies erwartet this, schlägt documentsie 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 getElementByIdin IE nicht, aber ein Kommentar in der jQuery-Quelle ( inArrayMethodenimplementierung) besagt, dass in IEwindow == document . Wenn dies der Fall ist, document.getElementByIdsollte Aliasing im IE funktionieren.
Um dies weiter zu veranschaulichen, habe ich ein ausführliches Beispiel erstellt. Schauen Sie sich die PersonFunktion 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 getAgeverhalten sich die verschiedenen Methoden wie folgt.
Lassen Sie uns zwei Objekte mit der PersonFunktion 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 yogiObjekt ab thisund gibt es aus 100.
var ageAlias = yogi.getAge;
console.log(ageAlias()); //Output: -1
Der JavaScript-Interepreter setzt das windowObjekt auf thisund unsere getAgeMethode gibt zurück -1.
console.log(ageAlias.apply(yogi)); //Output: 100
Wenn wir den richtigen Bereich festlegen, können Sie die ageAliasMethode 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 ageSmarterFunktion hat das ursprüngliche thisObjekt 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 ageSmarterist, 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 ageSmartestFunktion 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 PersonObjekt übergeben getAgeSmartest. :) :)