【发布时间】:2012-01-07 22:20:29
【问题描述】:
据称 JavaScript 具有一流的功能,所以这似乎应该起作用:
var f = document.getElementById;
var x = f('x');
但它在所有浏览器上都失败了,每个浏览器都有不同的神秘错误消息。 Safari 显示“类型错误”。 Chrome 显示“非法调用”。 Firefox 提示“无法转换 JavaScript 参数”。
为什么?
【问题讨论】:
标签: javascript
据称 JavaScript 具有一流的功能,所以这似乎应该起作用:
var f = document.getElementById;
var x = f('x');
但它在所有浏览器上都失败了,每个浏览器都有不同的神秘错误消息。 Safari 显示“类型错误”。 Chrome 显示“非法调用”。 Firefox 提示“无法转换 JavaScript 参数”。
为什么?
【问题讨论】:
标签: javascript
当您在 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);
【讨论】:
document.getElementById() 中的this 是document,而您执行作用域的this 是全局作用域,也就是this 是window对象。
使用 ES6 的扩展运算符,你也可以试试:
function f(){
return document.getElementById(...arguments);
};
Babel 给出了这个:
function f() {
var _document;
return (_document = document).getElementById.apply(_document, arguments);
};
【讨论】: