Я глубоко копнул, чтобы понять это конкретное поведение, и думаю, что нашел хорошее объяснение.
Прежде чем я document.getElementByIdрасскажу, почему вы не можете использовать псевдоним , я попытаюсь объяснить, как работают функции / объекты JavaScript.
Каждый раз, когда вы вызываете функцию JavaScript, интерпретатор JavaScript определяет область видимости и передает ее функции.
Рассмотрим следующую функцию:
function sum(a, b)
{
return a + b;
}
sum(10, 20);
Эта функция объявлена в области Window, и когда вы ее вызываете, значение thisвнутри функции суммы будет глобальным Windowобъектом.
Для функции «сумма» не имеет значения, какое значение имеет «это», поскольку она его не использует.
Рассмотрим следующую функцию:
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();
При вызове функции dave.getAge, интерпретатор JavaScript видит , что вы вызываете функцию СеЬАда на daveобъекте, поэтому он устанавливает thisв daveи вызывает getAgeфункцию. getAge()правильно вернется 100.
Возможно, вы знаете, что в JavaScript вы можете указать область действия с помощью applyметода. Давай попробуем.
var dave = new Person(new Date(1909, 1, 1));
var bob = new Person(new Date(1809, 1, 1));
dave.getAge.apply(bob);
В приведенной выше строке вместо того, чтобы позволить JavaScript определять область действия, вы передаете область вручную как bobобъект. getAgeтеперь будет возвращаться , 200даже если вы «мысль» вы назвали getAgeна daveобъекте.
В чем смысл всего вышеперечисленного? Функции «слабо» привязаны к вашим объектам JavaScript. Например, вы можете сделать
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();
Сделаем следующий шаг.
var dave = new Person(new Date(1909, 1, 1));
var ageMethod = dave.getAge;
dave.getAge();
ageMethod();
ageMethodвыполнение выдает ошибку! Что случилось?
Если вы внимательно прочитаете мои пункты выше, то заметите, что dave.getAgeметод был вызван daveкак thisобъект, тогда как JavaScript не мог определить «область действия» для ageMethodвыполнения. Таким образом, он передал глобальное «Окно» как «это». Теперь, когда у windowнего нет birthDateсвойства, ageMethodвыполнение не удастся.
Как это исправить? Просто,
ageMethod.apply(dave);
Имеет ли все вышеперечисленное смысл? Если да, то вы сможете объяснить, почему не можете использовать псевдоним document.getElementById:
var $ = document.getElementById;
$('someElement');
$вызывается windowкак thisи, если getElementByIdреализация ожидает thisэтого document, она завершится ошибкой.
Опять же, чтобы исправить это, вы можете сделать
$.apply(document, ['someElement']);
Так почему это работает в Internet Explorer?
Я не знаю внутреннюю реализацию getElementByIdв IE, но комментарий в источнике JQuery ( inArrayреализация метода) говорит , что в IE, window == document. В этом случае псевдонимы document.getElementByIdдолжны работать в IE.
Чтобы проиллюстрировать это дальше, я создал подробный пример. Взгляните на Personфункцию ниже.
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();
};
}
Для приведенной Personвыше функции различные getAgeметоды будут вести себя следующим образом.
Создадим два объекта с помощью Personфункции.
var yogi = new Person(new Date(1909, 1,1));
var anotherYogi = new Person(new Date(1809, 1, 1));
console.log(yogi.getAge());
Прямо сейчас метод getAge получает yogiобъект как thisи выводит 100.
var ageAlias = yogi.getAge;
console.log(ageAlias());
Интерпретатор JavaScript устанавливает windowобъект как, thisи наш getAgeметод вернет -1.
console.log(ageAlias.apply(yogi));
Если мы установим правильный объем, вы можете использовать ageAliasметод.
console.log(ageAlias.apply(anotherYogi));
Если мы передадим объект другого человека, он все равно будет правильно вычислять возраст.
var ageSmarterAlias = yogi.getAgeSmarter;
console.log(ageSmarterAlias());
ageSmarterФункция захватила исходный thisобъект , так что теперь вам не придется беспокоиться о поставке правильной сферы.
console.log(ageSmarterAlias.apply(anotherYogi));
Проблема в ageSmarterтом, что вы никогда не можете установить область для какого-либо другого объекта.
var ageSmartestAlias = yogi.getAgeSmartest;
console.log(ageSmartestAlias());
console.log(ageSmartestAlias.apply(document));
ageSmartestФункция будет использовать исходный объем , если недействительная сфера поставляются.
console.log(ageSmartestAlias.apply(anotherYogi));
Вы по-прежнему сможете передать другой Personобъект getAgeSmartest. :)