8

Here is my latest discovery while experimenting with 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?

Edit 1

What is the difference between string primitives and String objects in JavaScript? 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.

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?"

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.

I hope this clarification is correct

Boann
  • 48,794
  • 16
  • 117
  • 146
bartocc
  • 727
  • 1
  • 7
  • 19
  • this is something really useful but also dangerous. Read that link it will help you a lot to understand the state uf this in certain situations. https://codeburst.io/all-about-this-and-new-keywords-in-javascript-38039f71780c – Patrick Lüthi Sep 06 '19 at 09:23
  • Not sure it'll be of any help, but `new String('string literal')` outputs `String {"string literal"}` in V8 – Thor Jacobsen Sep 06 '19 at 09:23
  • 1
    That is probably because `this` has to be an object and `'string literal'` is coerced to a `String` object. – Titus Sep 06 '19 at 09:23
  • Possible duplicate of [What is the difference between string primitives and String objects in JavaScript?](https://stackoverflow.com/questions/17256182/what-is-the-difference-between-string-primitives-and-string-objects-in-javascrip) – Joachim Sauer Sep 06 '19 at 09:24
  • A string literal is a primitive string and you can't call methods on primitive values, so it's automagically turned into a `String` object in order to be able to call a method on it. – Joachim Sauer Sep 06 '19 at 09:24

2 Answers2

8

.call internally invokes [[Call]], which performs

  1. Perform 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:

  1. If thisMode is strict, let thisValue be thisArgument.

  2. Else,

    a. If thisArgument is undefined or null, then ...

    b. Else, Let thisValue be ! 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');
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
3

Since you are calling a method on the string primitive, it is automatically converted to a String Object.

The logs are how the two consoles render String Objects.

Further reading: What is the difference between string primitives and String objects in JavaScript?

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335