为什么不能直接将document.getElementById分配给其他函数?

问题描述

| 因此,我试图定义一个类似于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。