所以我试图定义一个类似于document.getElementById的函数g()。以下工作正常:
var g = function(id){return document.getElementById(id)};
但为什么这个更直接的代码不起作用?
var g = document.getElementById;
答案 0 :(得分:12)
问题在于 context 。当您触发对象的函数时,将使用该对象作为this
的值触发(除非您另行指定)。 g = document.getElementById
将函数getElementById
放入变量g
,但不设置上下文。
因此,当您运行g(someId)
时,没有可以运行该函数的上下文。它以全局对象window
作为this
的值运行,但不起作用。 (确切地说,它不起作用,因为您可以使用任何document
对象操作,而不仅仅是window.document
,并且您没有指定一个。)
您可以使用call
解决此问题,您可以在其中设置上下文:
g.call(document, someId);
然而,这并不是对原作的改进!
答案 1 :(得分:2)
因为当你调用“g('somestr')”时,“this”值被绑定到“window”并且“document.getElementById”变为期望被绑定到“document”而不是“window”(有意义)对我=))。这样做的:
var g = document.getElementById;
g('somestr');
就像:
document.getElementById.call(window, 'somestr');
答案 2 :(得分:1)
问题是上下文。 document.getElementById(xxx)
在document
的上下文中运行,但是当您将其分配给某个东西时,会得到一个TypeError,因为上下文可能是window
。看到这个jsFiddle:http://jsfiddle.net/minitech/as3AQ/
所以,您可以使用call
或apply
,但这很难看。只需改为第二种方式,或者将其分配给document
并指定document
,如果您的目标是缩小代码。
答案 3 :(得分:0)
@minitech和@Tim Down 非常感谢您的反馈。
我们有很多旧代码,就像这样工作
var $ = document.getElementById;
$("First");
它在现代浏览器中失败并显示错误消息 未捕获的TypeError:非法调用
我所做的一切都被替换为
var $ = function(x) { return document.getElementById(x); };
$("First");
现在我们回到游戏中:))
答案 4 :(得分:0)
正如lonesomeday's answer已经显示的那样,问题在于执行上下文。我想补充说,有一种方法可以使用执行上下文创建一个函数。打开浏览器的此页面的开发者工具,然后在控制台中尝试以下操作:
> document.getElementById('notify-container');
// <div id="notify-container"></div>
> var _d = document.getElementById;
// undefined
> _d
// ƒ getElementById() { [native code] }
> _d('notify-container');
// Uncaught TypeError: Illegal invocation
// at <anonymous>:1:1
和以前一样,直接调用分配给_d
的变量document.getElementById
失败。但是您可以使用Function.prototype.bind
来绑定执行上下文。
bind()
方法创建一个新函数,在调用时,将其this关键字设置为提供的值,并在调用新函数时提供任何前面提供的给定参数序列。
> var d = document.getElementById.bind(document);
// undefined
> d('notify-container');
// <div id="notify-container"></div>
如果您想使用bind
,也不必担心浏览器兼容性:请参阅https://caniuse.com/#feat=es5。