【问题标题】:JavaScript Function Context IncorrectJavaScript 函数上下文不正确
【发布时间】:2015-06-02 11:59:34
【问题描述】:

我注意到 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 至少显示了一些有意义的错误消息。

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

【问题讨论】:

  • 请说明您如何准确地致电fn
  • 我在拨打fn 时收到undefined is not a function不是 fn is not a function
  • 当然。不过,请展示一个完整的示例,说明什么代码会产生什么错误。
  • 请澄清 consoele 是否是错字,如果不是,请编辑
  • Firebug 有更深入的错误消息:TypeError: Function.prototype.call called on incompatible undefined。基本上call()需要在一个对象(this)上调用,这个对象丢失了,在原始语句之外被调用。

标签: javascript


【解决方案1】:

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

var fn = ''.toUpperCase.call

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

你必须这样做:

fn.call(''.toUpperCase)

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

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

另见How does the "this" keyword work?

【讨论】:

  • 你认为my answer 也是链接问题的答案吗?
  • @Amit 是的,你基本上是在说同样的话。
  • Context in Javascript is always established by the way you call a function. 除非是箭头函数,或者函数被绑定了。
【解决方案2】:

deceze's answer是对的,我只是想换个角度解释一下。

您的fn 是对Function.prototype.call 的引用,需要使用函数作为其this 引用来调用它,在这种情况下,call 的上下文是String.prototype.toUpperCase,它是通过@987654327 继承的@

除此之外,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 在不兼容的未定义上调用

【讨论】:

  • developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
【解决方案3】:

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

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

我注意到 javascript 中有一个奇怪的东西。

您似乎对您在测试环境中收到的消息感到困惑,该消息并不完全正确。

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

铬的当前稳定版本(在我的 linux 安装上为 40.0.2214.91,chrome 无法在我的硬件上运行而无需更改设置),chrome 是您测试的环境,提供看似更正确的错误消息,使更多感觉。

Uncaught TypeError: undefined is not a function

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

【讨论】:

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