问题描述
|
因此,我试图定义一个类似于document.getElementById的函数g()。以下工作正常:
var g = function(id){return document.getElementById(id)};
但是,为什么这个更直接的代码不起作用?
var g = document.getElementById;
解决方法
问题在于上下文。触发对象的函数时,将以对象的值
this
触发该函数(除非另行指定)。 g = document.getElementById
将函数getElementById
放入变量g
,但不设置上下文。
因此,当您运行g(someId)
时,没有可以在其上运行函数的上下文。它以全局对象window
作为this
的值运行,但这不起作用。 (确切地说,它不起作用,因为您可以使用任何document
对象,而不仅仅是window.document
,并且您未指定任何对象。)
您可以使用call
解决此问题,在其中设置上下文:
g.call(document,someId);
但是,这不是原始版本的改进!
, 因为当您调用\“ g(\'somestr \')\”时,\“ this \”值绑定到\“ window \”,而\“ document.getElementById \”似乎希望绑定到\“ document \“代替\” window \“(对我来说有意义=))。正在做:
var g = document.getElementById;
g(\'somestr\');
就好像:
document.getElementById.call(window,\'somestr\');
, 问题在于上下文。 document.getElementById(xxx)
在document
的上下文中运行,但是当您将其分配给某物时,会收到TypeError,因为上下文可能是window
。看到这个jsFiddle:http://jsfiddle.net/minitech/as3AQ/
因此,您可以使用call
或apply
,但这很丑陋。而是采取第二种方法,或者将其分配给document
,如果目标是最小化代码,则将document
分配给某些对象。
, @minitech和@Tim Down
非常感谢您的反馈。
我们有很多像这样的旧代码
var $ = document.getElementById;
$(\"First\");
在现代浏览器中失败,并显示错误消息
未捕获的TypeError:非法调用
我所做的全部被替换为
var $ = function(x) { return document.getElementById(x); };
$(\"First\");
现在我们回到游戏中了:)
, 正如lonesomeday的答案已经表明的那样,问题在于执行上下文。我想补充一下,有一种方法可以用执行上下文创建函数。打开浏览器的此页面的开发人员工具,然后在控制台中尝试以下操作:
> 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
与以前一样,直接调用分配给document.getElementById
的变量_d
失败。但是您可以使用“ 27”来绑定执行上下文。
bind()
方法创建一个新函数,该函数在被调用时将其关键字设置为提供的值,并在调用新函数时提供给定的参数序列。
> var d = document.getElementById.bind(document);
// undefined
> d(\'notify-container\');
// <div id=\"notify-container\"></div>
如果要使用bind
,也不必担心浏览器的兼容性:请参阅https://caniuse.com/#feat=es5。