为什么某些函数调用在 JavaScript 中被称为“非法调用”?

IT技术 javascript invocation
2021-01-19 14:09:02

例如,如果我这样做:

var q = document.querySelectorAll;

q('body');

我在 Chrome 中收到“非法调用”错误。我想不出有什么必要这样做。一方面,并​​非所有本机代码函数都如此。事实上,我可以这样做:

var o = Object; // which is a native code function

var x = new o();

一切正常。特别是我在处理文档和控制台时发现了这个问题。有什么想法吗?

3个回答

这是因为你已经失去了函数的“上下文”。

你打电话的时候:

document.querySelectorAll()

函数的上下文是document,并且可以this通过该方法的实现来访问

当您只是调用时q,不再有上下文 - 它是“全局”window对象。

querySelectorAll尝试使用的实现this不再是 DOM 元素,而是一个Window对象。该实现尝试调用Window对象上不存在的 DOM 元素的某些方法,并且解释器毫不奇怪地调用了 foul。

要解决此问题,请.bind在较新版本的 Javascript 中使用:

var q = document.querySelectorAll.bind(document);

这将确保所有后续调用q具有正确的上下文。如果你还没有.bind,请使用这个:

function q() {
    return document.querySelectorAll.apply(document, arguments);
}
@Alnitak:是的,它适用于除 IE 之外的任何地方,这就是为什么您应该经常正常传递参数,如function q(x){ return document.querySelectorAll(x); }. 我真正喜欢 IE 浏览器对象的另一件事是,如果您尝试从它们读取属性,它们中的一些会抛出异常,因此您需要使用if( 'funcname' in browserobject)而不是通常的if(browserobject.funcname)!
2021-03-14 14:09:02
脑洞大开。谢谢你。
2021-03-19 14:09:02
哦,很好的电话。你是对的,因为我可以做到: q.apply(document, ['body']); 它有效。
2021-03-30 14:09:02
请注意,这对于 IE 中的内置函数没有必要。例如, console.log 在那里没有 apply 方法。
2021-04-08 14:09:02
很好的答案,我真的对这种现象感到困惑,与 OP 的情况完全相同。
2021-04-13 14:09:02

在我的情况下,由于将未声明的变量作为参数传递给函数而发生非法调用。确保在传递给函数之前声明变量。

声明变量对这种特殊情况没有意义,因为非法调用正在发生,因为在 DOM 上下文之外调用了 dom 依赖方法,因为当您执行 q = document.something 时,该something方法会丢失文档的上下文
2021-03-23 14:09:02

你可以这样使用:

let qsa = document.querySelectorAll;
qsa.apply(document,['body']);