Why is the 'in' operator throwing an error with a string literal instead of logging false?

In a sense it is a matter of timing. String literals do not have any properties. The reason that you can call methods and lookup properties on primitive strings is because JavaScript automatically wraps the string primitive in a String object when a method call or property lookup is attempted. JavaScript does not interpret the in operator as a method call or property lookup so it does not wrap the primitive in an object and you get an error (because a string primitive is not an object).

See Distinction between string primitives and String objects

Also, the same docs referenced in your question specifically note that using in on a string primitive will throw an error.

You must specify an object on the right side of the in operator. For example, you can specify a string created with the String constructor, but you cannot specify a string literal.


It throws an error because in is an operator for objects:

prop in object

but when you declare a string as `` (` string(template) literals) or "" '' (",' string literals) you don't create an object.

Check

typeof new String("x") ("object")

and

typeof `x` ("string").

Those are two different things in JavaScript.


JavaScript operator in only applicable to an Objects instances.

When you using constructor new String('abc') this will causing creating of a String object instance.

In other side, when you using only string literals or call function String('abc') without new it creates an string primitive. (like Number and Boolen)

Some behaviour of primitives and objects is differrent, look at this simple example's output:

console.log(typeof (new String('ddd'))) // "object"
console.log(typeof ('ddd')) // "string"
console.log(eval('1 + 2')) // 3
console.log(eval(new String('1 + 2'))) // {"0":"1","1":" ","2":"+","3":" ","4":"2"}

In code where you use methods on string primitives javascript engine automatically wraps primitives with corresponding objects to perform methods call.

But in it is not an method call, its language operator an in this case wrapping is not applied.

PS: Sorry for my english.