Investigué profundamente para comprender este comportamiento en particular y creo que he encontrado una buena explicación.
Antes de explicar por qué no puede crear un alias document.getElementById, intentaré explicar cómo funcionan las funciones / objetos de JavaScript.
Siempre que invoca una función de JavaScript, el intérprete de JavaScript determina un alcance y lo pasa a la función.
Considere la siguiente función:
function sum(a, b)
{
return a + b;
}
sum(10, 20);
Esta función se declara en el ámbito de la ventana y cuando la invoca, el valor de thisdentro de la función de suma será el Windowobjeto global .
Para la función 'suma', no importa cuál sea el valor de 'esto' ya que no lo está usando.
Considere la siguiente función:
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();
Cuando se llama a la función dave.getAge, el intérprete de JavaScript ve que está llamando la función getAge en el daveobjeto, por lo que pone thisa davey llama a la getAgefunción. getAge()regresará correctamente 100.
Es posible que sepa que en JavaScript puede especificar el alcance utilizando el applymétodo. Probemos eso.
var dave = new Person(new Date(1909, 1, 1));
var bob = new Person(new Date(1809, 1, 1));
dave.getAge.apply(bob);
En la línea anterior, en lugar de dejar que JavaScript decida el alcance, está pasando el alcance manualmente como bobobjeto. getAgeahora regresará 200a pesar de que "pensó" que llamó getAgeal daveobjeto.
¿Cuál es el punto de todo lo anterior? Las funciones se adjuntan "libremente" a sus objetos JavaScript. Por ejemplo, puedes hacer
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();
dave.getAge();
Demos el siguiente paso.
var dave = new Person(new Date(1909, 1, 1));
var ageMethod = dave.getAge;
dave.getAge();
ageMethod();
ageMethod¡la ejecución arroja un error! ¿Que pasó?
Si usted lee mis puntos por encima con cuidado, que le cuenta que dave.getAgeel método fue llamado con davecomo thisobjeto mientras que JavaScript no pudo determinar el 'alcance' de ageMethodejecución. Así que pasó la 'Ventana' global como 'esto'. Ahora windowque no tiene una birthDatepropiedad, la ageMethodejecución fallará.
¿Cómo arreglar esto? Sencillo,
ageMethod.apply(dave);
¿Todo lo anterior tenía sentido? Si es así, entonces podrá explicar por qué no puede usar un alias document.getElementById:
var $ = document.getElementById;
$('someElement');
$se llama con windowtan thisy si getElementByIdla aplicación está a la espera thisde ser document, se producirá un error.
Nuevamente para solucionar esto, puede hacer
$.apply(document, ['someElement']);
Entonces, ¿por qué funciona en Internet Explorer?
No sé la implementación interna de getElementByIden IE, pero un comentario en la fuente de jQuery ( inArrayimplementación del método) dice que en el IE, window == document. Si ese es el caso, entonces el aliasing document.getElementByIddebería funcionar en IE.
Para ilustrar esto aún más, he creado un ejemplo elaborado. Eche un vistazo a la Personfunción a continuación.
function Person(birthDate)
{
var self = this;
this.birthDate = birthDate;
this.getAge = function()
{
if(this.constructor == Person)
return new Date().getFullYear() - this.birthDate.getFullYear();
else
return -1;
};
this.getAgeSmarter = function()
{
return self.getAge();
};
this.getAgeSmartest = function()
{
var scope = this.constructor == Person ? this : self;
return scope.getAge();
};
}
Para la Personfunción anterior, así es como getAgese comportarán los distintos métodos.
Creemos dos objetos usando la Personfunción.
var yogi = new Person(new Date(1909, 1,1));
var anotherYogi = new Person(new Date(1809, 1, 1));
console.log(yogi.getAge());
Directo, el método getAge obtiene el yogiobjeto como thisy la salida 100.
var ageAlias = yogi.getAge;
console.log(ageAlias());
El intérprete de JavaScript establece el windowobjeto como thisy nuestro getAgemétodo regresará -1.
console.log(ageAlias.apply(yogi));
Si configuramos el alcance correcto, puede usar el ageAliasmétodo.
console.log(ageAlias.apply(anotherYogi));
Si pasamos algún objeto de otra persona, aún calculará la edad correctamente.
var ageSmarterAlias = yogi.getAgeSmarter;
console.log(ageSmarterAlias());
La ageSmarterfunción capturó el thisobjeto original, por lo que ahora no tiene que preocuparse por suministrar el alcance correcto.
console.log(ageSmarterAlias.apply(anotherYogi));
El problema ageSmarteres que nunca se puede establecer el alcance en otro objeto.
var ageSmartestAlias = yogi.getAgeSmartest;
console.log(ageSmartestAlias());
console.log(ageSmartestAlias.apply(document));
La ageSmartestfunción utilizará el alcance original si se proporciona un alcance no válido.
console.log(ageSmartestAlias.apply(anotherYogi));
Aún podrá pasar otro Personobjeto a getAgeSmartest. :)