JavaScript 函数上下文不正确

IT技术 javascript
2021-02-21 18:11:59

我在 javascript 中注意到一个奇怪的事情。考虑以下问题:

var fn = ''.toUpperCase.call
console.log(typeof fn); // "function"
fn(); // Uncaught TypeError: `fn` is not a function

以上是在我的 Chrome 开发者控制台上执行的。版本是43.0.2357.81 m.

typeof运营商清楚地表明,fn是一个函数,但其他错误提示。

我注意到Function.apply至少显示了一些有意义的错误消息。

那么,什么时候是函数,而不是函数呢?

3个回答

Javascript 中的上下文总是通过调用函数的方式建立的

var fn = ''.toUpperCase.call

这将call函数的原型实现分配fn如果您现在调用fn(),则调用没有上下文。call将尝试调用与其关联的函数对象。但是,该上下文是在调用时建立的。由于您在调用时没有为其提供任何上下文,因此 的某些内部组件call会引发错误。

你必须这样做:

fn.call(''.toUpperCase)

没错,你callcall函数,建立上下文,即toUpperCase字符串函数。在这种特定情况下,这将导致 内部的另一个错误toUpperCase,因为没有绑定到特定的上下文。您还需要明确建立该上下文:

var fn = ''.toUpperCase.call
fn.call(''.toUpperCase.bind(''))

另请参阅“this”关键字如何工作?

所以你认为,我的答案也是链接问题的答案吗?
2021-04-17 18:11:59
@Amit 是的,你基本上在那里说同样的话。
2021-04-27 18:11:59
Context in Javascript is always established by the way you call a function. 除非是箭头函数,否则函数已经被绑定了。
2021-05-12 18:11:59

deceze的回答是正确的,我只是想从不同的角度解释一下。

fn是一个引用Function.prototype.call,需要用一个函数作为它的this引用来调用它,在这种情况下,call是 is的上下文String.prototype.toUpperCase,它是通过继承''.toUpperCase

最重要的是,String.prototype.toUpperCase还必须使用特定的上下文调用,将字符串转换为大写。

这是另一种编写您想要的代码的方法,可以帮助您了解正在发生的事情。

    var str = 'aaa';
    var upper = ''.toUpperCase;
    var fn = upper.call;
    // Now we have to specify the context for both upper and fn
    console.log( fn.call(function() { return upper.call(str)}) ); // AAA

在您的示例中,fn()正在尝试调用call但它没有指定上下文,通常默认为window对象,但在这种情况下,它只是使它的undefined,这在 Chrome 中触发了一个奇怪的错误(如您所发现的),但 Firefox 更清楚这个问题,

TypeError: Function.prototype.call 在不兼容的 undefined 上调用

developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
2021-04-16 18:11:59

那么,什么时候是函数,而不是函数呢?

该函数是一个函数,但您没有正确执行它,如@deceze 的评论和答案中所述

我在 javascript 中注意到一个奇怪的事情。

您似乎对在测试环境中获得的消息感到困惑,该消息并非严格正确。

未捕获的类型错误:fn不是函数

chrome 的当前稳定版本(在我的 linux 安装上为 40.0.2214.91,chrome 无法在我的硬件上运行而不进行设置更改),chrome 是您测试的环境,提供了看似更正确的错误消息,更有意义。

Uncaught TypeError: undefined is not a function

那么,您是在问/想要问一个严肃的问题,还是只是在 chrome 版本中的一个错误中取笑?

在 Fedora 19 上,它是 40.0.2214.91,它使用包存储库中的 YUM 自动更新,我不打算自己构建它(我只记得这是铬而不是铬)。我知道不同的操作系统有不同的稳定版本,肯定会有差异。好的,您没有在问题中包含该信息,所以您真的想检查您是否正确回答了另一个问题?或者我还是不太明白这个问题是什么或者你期待什么样的答案?
2021-04-30 18:11:59
我还有很多其他工作要做,而不是在 chrome 上找点乐子。仅供参考,我在这里回答时遇到了这些东西,并不是每个人都使用您使用的 chrome 版本(我不会手动更新 chrome,它会自动更新),感谢您的回答。也感谢我上面的评论。
2021-05-05 18:11:59
40.0.2214.91不是当前稳定版的 Chrome;43.0.2357.81您从中获取 Chrome 的软件包源不是最新的。另外,我只想提出一个区别点(即使 OP 在询问之前就知道这个问题的答案),想要创建一个关于这个非常令人困惑的错误的信息库与“开玩笑”相去甚远。
2021-05-14 18:11:59