28

As per MDN the in operator returns true if the property exists and accordingly the first example logs true. But when using a string literal, why is it throwing an error instead of logging false?

let let1 = new String('test');
console.log(let1.length);
console.log('length' in let1)

var let1 = 'test';
console.log(let1.length);
console.log('length' in let1);

3
  • I'd assume the temporary wrapper object created for the string is not enumerable ..? Commented Apr 4, 2019 at 18:49
  • @Teemu No. There is no temporary wrapper object created at all Commented Apr 4, 2019 at 18:51
  • @Bergi Well, that explains a lot. Commented Apr 4, 2019 at 18:52

5 Answers 5

41

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.

Sign up to request clarification or add additional context in comments.

2 Comments

This is the shortest and most concise correct answer shown.
Nice. I think I know a lot about JS after working with it for a few years now but I'm still finding out interesting quirks like this.
10

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.

1 Comment

actually my expectation was it will log false instead of throwing error.Actually I was doing if(!(prop in someObj))
4

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.

Comments

3

typeof('test') == string (string literal)

typof(new String('test')) == object (string object)

you can't use in with a string literal.

The in operator returns true if the specified property is in the specified object or its prototype chain.

Comments

2

The in operator can only be used to check if a property is in an object. You can't search in strings, or in numbers, or other primitive types.

The first example works and prints 'true' because length is a property of a string object.

The second example doesn't work and gives you an error because you are trying to look for a property length in something (a string) that is not an object.

7 Comments

Right. But let1 is a string, not an object in the second example.
The second example wouldn't work because let1 is not an object.
Just run the second snippet, the first console.log shows 4.
@Teemu, the second console log statement (rightly) throws an error in the second example.
Yes, but you're saying retrieving the length woud throw the error. On the very first line it logs 4, the length of let1. Take a look at benvc's answer on this post.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.