Ответ 1
Потому что в JavaScript функции arent привязаны к контексту (this
). Вы можете использовать bind()
:
var f = document.getElementById.bind(document);
Предполагается, что JavaScript имеет первоклассные функции, поэтому это выглядит следующим образом:
var f = document.getElementById;
var x = f('x');
Но он не работает во всех браузерах с другим загадочным сообщением об ошибке на каждом из них. Safari говорит "Ошибка типа". Хром говорит "Незаконный призыв". Firefox говорит: "Не удалось преобразовать аргумент JavaScript".
Почему?
Потому что в JavaScript функции arent привязаны к контексту (this
). Вы можете использовать bind()
:
var f = document.getElementById.bind(document);
Когда вы вызываете obj.method()
в Javascript, метод передается obj
как this
. Вызов document.getElementById('x')
, поэтому установите this
в document
.
Однако, если вы просто пишете f = document.getElementById
, теперь у вас есть новая ссылка на функцию, но эта ссылка больше не привязана к document
.
Таким образом, ваш код не работает, потому что, когда вы вызываете f
в качестве голой функции, оно оказывается привязанным к глобальному объекту (window
). Как только внутренняя функция функции попытается использовать this
, она обнаруживает, что теперь она имеет window
вместо document
, и неудивительно, что ей это не нравится.
Вы можете сделать f
работать, если вы его так называете:
var x = f.call(document, 'x');
который вызывает f
, но явно устанавливает контекст в document
.
Другой способ исправить это - использовать Function.bind()
, который доступен только в ES5:
var f = document.getElementById.bind(document);
и на самом деле является просто обобщенным сокращением для создания собственной оболочки, которая правильно устанавливает контекст:
function f(id) {
return document.getElementById(id);
}
Используя оператор распространения ES6, вы также можете попробовать:
function f(){
return document.getElementById(...arguments);
};
Вавилон дает следующее:
function f() {
var _document;
return (_document = document).getElementById.apply(_document, arguments);
};