JavaScript据称拥有一流函数,因此似乎以下内容应该有效:
var f = document.getElementById;
var x = f('x');
但是在所有浏览器上都失败了,并且每个浏览器都显示不同的加密错误信息。Safari 显示“类型错误”。Chrome 显示“非法调用”。Firefox 显示“无法转换 JavaScript 参数”。
为什么?
JavaScript据称拥有一流函数,因此似乎以下内容应该有效:
var f = document.getElementById;
var x = f('x');
但是在所有浏览器上都失败了,并且每个浏览器都显示不同的加密错误信息。Safari 显示“类型错误”。Chrome 显示“非法调用”。Firefox 显示“无法转换 JavaScript 参数”。
为什么?
obj.method()
时,方法会将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);
}
由于在JavaScript中函数并不会 绑定 到上下文 (this
)。您可以使用bind()
:
var f = document.getElementById.bind(document);
function f(){
return document.getElementById(...arguments);
};
function f() {
var _document;
return (_document = document).getElementById.apply(_document, arguments);
};