开发者

Are string literals objects or not?

开发者 https://www.devze.com 2022-12-16 03:16 出处:网络
Trying to get my JavaSscript funda开发者_开发问答mentals strong. So the question is about string literals. Aren\'t they Objects? If your answer is \'yes\' then my question is why is instanceof returni

Trying to get my JavaSscript funda开发者_开发问答mentals strong. So the question is about string literals. Aren't they Objects? If your answer is 'yes' then my question is why is instanceof returning false?

> var s = new String
> s.constructor.toString()
function String() { [native code] }

> typeof s
object

> s instanceof String
true

> s instanceof Object
true

> s instanceof Number
false

So far so good.

> typeof 'c'
string

> 'c' instanceof Object
false

> 'c' instanceof String
false

> 'c'.length
1

> 'c'.charAt(0)
c

> 'c'.constructor.toString()
function String() { [native code] }


String literals are primitives (String values), String objects can be created with the String constructor in a new expression:

"foo" instanceof String // false

new String("foo") instanceof String // true

Edit: Something that seems to be confusing (by looking at the accepted answer here), is that you can still access properties defined on the prototype objects of primitive values, for example:

"foo".indexOf == String.prototype.indexOf // true
"foo".match == String.prototype.match // true
String.prototype.test = true;
"foo".test // true
true.toString == Boolean.prototype.toString
(3).toFixed == Number.prototype.toFixed // true
// etc...

The reason of that relies on the Property Accessors, the dot notation . and the bracket notation [].

Let's give a look to the algorithm in the ECMA-262 specification:

The production MemberExpression : MemberExpression [ Expression ] (or MemberExpression . Identifier) is evaluated as follows:

  1. Evaluate MemberExpression.

  2. Call GetValue(Result(1)).

  3. Evaluate Expression.

  4. Call GetValue(Result(3)).

  5. Call ToObject(Result(2)).

  6. Call ToString(Result(4)).

  7. Return a value of type Reference whose base object is Result(5) and whose property name is Result(6).

In the Step 5, the ToObject internal operator type-converts the MemberExpression to object, depending on it's type.

The primitives are converted to Objects without noticing, and that's why you can access the properties defined on the prototype.


Great explanation of this here. Copied for reference below.


That's because those things are primitives, and unless they need to be used as objects (when you are calling methods on them, for example) they remain so. The only time they "become" objects is when they need to be wrapped. If you are familiar with the concept of "boxing" in .NET, then think of it in that way.

Here is an example - take a look at this code:

Number.prototype.times = function(func) {
   for(var index = 1; index <= this; index++) {
      func(index);
   }
};

So, the following code will fail:

3.times(print); // assume 'print' writes to standard out

3, by itself is a primitive. That said, the following will work:

(3).times(print); // assume 'print' writes to standard out

That would display the numbers 1, 2, and 3. Because of the parenthesis, the JavaScript interpreter will temporarily wrap the primitive 3 in a Number object, call the method, and then garbage collect the object since it isn't needed any longer.

Anyway, a full discussion of this can be found in "JavaScript: The Definitive Guide."

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号