What’s happening in this code with Number objects holding properties and incrementing the number?

后端 未结 10 1323
孤街浪徒
孤街浪徒 2020-12-07 06:57

A recent tweet contained this snippet of JavaScript.

Can someone please explain what is happening in it step by step?

> function dis() { return th         


        
10条回答
  •  温柔的废话
    2020-12-07 07:24

    A couple of concepts explain what happens

    5 is a number, a primitive value

    Number {[[PrimitiveValue]]: 5} is an instance of Number (let's call it object wrapper)

    Whenever you access a property/method on a primitive value, the JS engine will create an object wrapper of the appropriate type (Number for 5, String for 'str' and Boolean for true) and resolve the property access/method call on that object wrapper. This is what happens when you do true.toString() for example.

    When performing operations on objects, they are converted to primitive values (by using toString or valueOf) in order to resolve those operations - for example when doing

    var obj = { a : 1 };
    var string = 'mystr' + obj;
    var number = 3 + obj;
    

    string will hold the string concatenation of mystr and obj.toString() and number will hold the addition of 3 and obj.valueOf().

    Now to put it all together

    five = dis.call(5)
    

    dis.call(5) behaves just like (5).dis() if 5 actually had the method dis. In order to resolve the method call, the object wrapper is created and the method call is resolved on it. At this point five points to an object wrapper around the primitive value 5.

    five.wtf = 'potato'
    

    Setting a property on an object, nothing fancy here.

    five * 5
    

    This is actually five.valueOf() * 5 obtaining the primitive value from the object wrapper. five still points to the initial object.

    five++
    

    This is actually five = five.valueOf() + 1. Before this line five holds the object wrapper around the value 5, while after this point five holds the primitive value 6.

    five.wtf
    five.wtf = 'potato?'
    five.wtf
    

    five is no longer an object. Each of those lines creates a new instance of Number in order to resolve the .wtf property access. The instances are independent, so setting a property on one will not be visible on another. The code is completely equivalent to this one:

    (new Number(6)).wtf;
    (new Number(6)).wtf = 'potato?';
    (new Number(6)).wtf;
    

提交回复
热议问题