Я глубоко копнул, чтобы понять это конкретное поведение, и думаю, что нашел хорошее объяснение.
Прежде чем я 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
. :)