为什么我不能直接将document.getElementById分配给不同的函数?

时间:2011-06-11 21:40:50

标签: javascript

所以我试图定义一个类似于document.getElementById的函数g()。以下工作正常:

var g = function(id){return document.getElementById(id)};

但为什么这个更直接的代码不起作用?

var g = document.getElementById;

5 个答案:

答案 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/

所以,您可以使用callapply,但这很难看。只需改为第二种方式,或者将其分配给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