简体   繁体   English

为什么(function(){return this;})。call('string literal')返回[String:'string literal']而不是'string literal'?

[英]Why does (function() { return this; }).call('string literal') return [String: 'string literal'] instead of 'string literal'?

Here is my latest discovery while experimenting with JS: 这是我在尝试使用JS时的最新发现:

(function() { return this; }).call('string literal');
// => [String: 'string literal'] in V8
// => String { "string literal" } in FF

I stumbled on this while doing the following: 在执行以下操作时我偶然发现了这一点:

(function() { return this === 'string literal'; }).call('string literal');
// => false

Can anyone tell me why this inside the function is not exactly what was passed as the first argument to call ? 谁能告诉我,为什么this里面的功能不完全是被作为第一个参数传递给call

Edit 1 编辑1

What is the difference between string primitives and String objects in JavaScript? JavaScript中的字符串原语和String对象有什么区别? has been marked as a possible duplicate of my question. 已被标记为我的问题的可能重复。

While the answers to both questions are related to how JS wraps primitives inside Objects, I believe the questions, and their answers, are not identical. 虽然这两个问题的答案都与JS如何在Objects中包含原语有关,但我相信这些问题及其答案并不相同。

My question was "why are the argument passed to call and the value of this inside the function different?", while the other question was "why is code block 1 faster than code block 2?" 我的问题是“为什么参数传递给调用并且函数内部的值不同?”而另一个问题是“为什么代码块1比代码块2更快?”

The correct answer to my question was "because you did not use strict mode" while the answer to the other question was related to how fast data is accessed internally by engines implementing ECMAScript. 我的问题的正确答案是“因为你没有使用严格模式”而另一个问题的答案与实现ECMAScript的引擎内部访问数据的速度有关。

I hope this clarification is correct 😅 我希望这个澄清是正确的😅

.call internally invokes [[Call]] , which performs .call内部调用[[Call]] ,执行

  1. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument). 执行OrdinaryCallBindThis(F,calleeContext,thisArgument)。

And OrdinaryCallBindThis (which sets the this value of the function that's going to be called) will wrap the new this in an object in non-strict mode: OrdinaryCallBindThis (这将把this ,那将被调用的函数的值),将包装的新this在非严格模式的对象:

  1. If thisMode is strict, let thisValue be thisArgument. 如果thisMode是严格的,那么让thisValue成为thisArgument。

  2. Else, 其他,

    a. 一种。 If thisArgument is undefined or null, then ... 如果thisArgument未定义或为null,则...

    b. Else, Let thisValue be ! 否则,让这个值得! ToObject(thisArgument). ToObject(thisArgument)。

In strict mode, you'll see that the string does not get wrapped in an object: 在严格模式下,您将看到字符串包含在对象中:

 'use strict'; (function() { console.log(this); console.log(this === 'string literal'); }).call('string literal'); 

Since you are calling a method on the string primitive, it is automatically converted to a String Object. 由于您在字符串原语上调用方法,因此它会自动转换为String对象。

The logs are how the two consoles render String Objects. 日志是两个控制台如何呈现字符串对象。

Further reading: What is the difference between string primitives and String objects in JavaScript? 进一步阅读: JavaScript中的字符串原语和String对象有什么区别?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM