Javascript 什么&x2019;代码中的数字对象持有属性并递增数字时会发生什么情况?

Javascript 什么&x2019;代码中的数字对象持有属性并递增数字时会发生什么情况?,javascript,Javascript,包含此JavaScript片段 > function dis() { return this } undefined 有人能一步一步地解释一下里面发生了什么吗 > function dis() { return this } undefined > five = dis.call(5) Number {[[PrimitiveValue]]: 5} > five.wtf = 'potato' "potato" > five.wtf "potato" > fiv

包含此JavaScript片段

> function dis() { return this }
undefined
有人能一步一步地解释一下里面发生了什么吗

> function dis() { return this }
undefined
> five = dis.call(5)
Number {[[PrimitiveValue]]: 5}
> five.wtf = 'potato'
"potato"
> five.wtf
"potato"
> five * 5
25
> five.wtf
"potato"
> five++
5
> five.wtf
undefined
> five.wtf = 'potato?'
"potato?"
> five.wtf
undefined
> five
6
特别是,我不清楚:

  • 为什么
    dis.call(5)
    的结果是一个带有某种
    [[PrimitiveValue]]
    属性的
    Number
    ,但是
    five++
    five*5
    的结果似乎只是普通的数字
    5
    25
    (不是
    Number
    s)
  • 为什么
    five.wtf
    属性在
    five++
    增量后消失
  • 为什么
    five.wtf
    属性在
    five++
    增量之后甚至不再可设置,尽管
    five.wtf='potato?'
    赋值显然设置了值
  • 这很简单

    function dis () { return this; }
    
    这将返回
    This
    上下文。因此,如果你调用(5),你就把这个号码作为一个对象传递

    调用
    函数不提供参数,您给出的第一个参数是
    的上下文。通常,如果您希望它在上下文中,您可以给它
    {}
    因此
    dis.call({})
    ,这意味着函数中的
    this
    是空的
    this
    。但是,如果您传递
    5
    ,它似乎将被转换为一个对象。看

    所以返回值是
    object

    执行
    five*5
    时,JavaScript将对象
    five
    视为基本类型,因此相当于
    5*5
    。有趣的是,do
    '5'*5
    ,它仍然等于
    25
    ,因此JavaScript显然是在幕后操纵此行未对基础
    five
    类型进行任何更改


    但是当您执行
    ++
    操作时,它会将对象转换为原语
    数字
    类型,从而删除
    .wtf
    属性因为您影响的是基础类型

    有两种不同的方式来表示数字:

    var a = 5;
    var b = new Number(5);
    
    第一个是基元,第二个是对象。对于所有意图和目的,它们的行为都是相同的,只是在打印到控制台时它们看起来不同。一个重要的区别是,作为一个对象,
    newnumber(5)
    像任何普通的
    {}
    一样接受新属性,而原语
    5
    不:

    a.foo = 'bar';  // doesn't stick
    b.foo = 'bar';  // sticks
    
    至于首字母
    dis.call(5)
    部分,请参见。让我们假设
    call
    的第一个参数被用作
    this
    的值,并且该操作将数字强制转换为更复杂的
    number
    对象形式。*稍后
    ++
    将其强制转换回原语形式,因为加法操作
    +
    会生成一个新的原语

    > five = dis.call(5)  // for all intents and purposes same as new Number(5)
    Number {[[PrimitiveValue]]: 5}
    > five.wtf = 'potato'
    "potato"
    > five.wtf
    "potato"
    
    Number
    对象接受新属性

    > five++
    
    ++
    产生一个新的原语
    6

    > five.wtf
    undefined
    > five.wtf = 'potato?'
    "potato?"
    > five.wtf
    undefined
    
    …不具有且不接受自定义属性


    *请注意,在严格模式下,
    参数的处理方式会有所不同,不会转换为
    数字
    。有关实现的详细信息,请参阅。

    首先,看起来这是通过nodejs控制台运行的

    一,

    创建函数dis(),但由于未将其设置为
    var
    ,因此没有返回值,因此输出为
    undefined
    ,即使定义了
    dis()
    。另一方面,
    没有返回,因为函数没有执行

    二,

    这将返回javascript的
    Number
    对象,因为您只需将函数
    dis()
    This
    值设置为原语5

    三,

    第一个返回
    “potato”
    ,因为您刚刚将
    five
    的属性
    wtf
    设置为
    “potato”
    。Javascript返回您设置的变量的值,这样可以很容易地链接多个变量并将它们设置为相同的值,如下所示:
    a=b=c=2

    四,

    这将返回
    25
    ,因为您刚刚将原始数
    5
    乘以
    5
    five
    的值由
    Number
    对象的值确定

    五,

    我以前跳过了这一行,因为我会在这里重复它。 它只返回您在上面设置的属性
    wtf
    的值

    六,

    正如@Callum所说,
    +
    将从对象
    number{[[PrimitiveValue]]:5}
    中的相同值将类型转换为
    number

    现在,因为
    five
    是一个
    数字
    ,所以在执行以下操作之前,您不能再为其设置属性:

        five = dis.call(five)
        five.wtf = "potato?"
    

    还请注意,第二种方法的行为与第一种方法不同,因为它定义的是通用对象,而不是以前创建的
    Number
    对象

    我希望这会有所帮助,javascript喜欢假设一些事情,因此当从
    Number
    对象更改为基元
    Number
    时,它可能会变得混乱。 您可以使用
    typeof
    关键字write来检查某物的类型 五类 初始化之后,它返回
    'object'
    ,执行
    five++
    之后,它返回
    'number'


    @deceze非常好地描述了数字对象和原语数字之间的差异。

    原语值不能有属性。但当您尝试访问基元值上的属性时,它会透明地转换为临时数字对象

    因此:


    声明函数
    dis
    。函数返回其上下文

    function dis() { return this }
    undefined
    
    使用上下文
    5
    调用
    dis
    。在严格模式()中作为上下文传递时,基元值被装箱。所以
    five
    现在是object(装箱编号)

    声明
    wtf
    正确
        five * 5
    
        five.wtf
    
        five++
    
        five = dis.call(five)
        five.wtf = "potato?"
    
        five = { value: 6, wtf: "potato?" }
    
    > function dis() { return this }
    undefined
    // Like five.dis(), so dis return the temporaty Number object and 
    // reference it in five
    > five = dis.call(5)
    Number {[[PrimitiveValue]]: 5}
    
    // Write the wtf attribut on the Number object referenced by five
    > five.wtf = 'potato'
    "potato"
    // Read the wtf attribut on the Number object referenced by five
    > five.wtf
    "potato"
    
    // Return 5*5 but dont change the reference of five
    > five * 5
    25
    // Read the same wtf attribut on the Number object referenced by five
    > five.wtf
    "potato"
    
    // Change the five reference to a new primitive value (5+1). Five
    // reference a primitive now.
    > five++
    5
    
    // Read the wtf attribut on a new temporary Number object construct from
    // the primitive referenced by five. So wtf does not exist.
    > five.wtf
    undefined
    
    // Write the wtf attribut on a new temporary Number object construct from
    // the primitive referenced by five. But this object not referenced by
    // five. It will be lost.
    > five.wtf = 'potato?'
    "potato?"
    
    // Read the wtf attribut on a new temporary Number object construct from
    // the primitive referenced by five. So wtf does not exist.
    > five.wtf
    undefined
    > five
    6
    
    function dis() { return this }
    undefined
    
    five = dis.call(5)
    Number {[[PrimitiveValue]]: 5}
    
    five.wtf = 'potato'
    "potato"
    
    five.wtf
    "potato"
    
    five * 5
    25
    
    five.wtf
    "potato"
    
    five++
    5
    
    five.wtf
    undefined
    
    five.wtf = 'potato?'
    "potato?"
    
    five.wtf
    undefined
    
    five
    6
    
    01 > function dis() { return this }
    02 undefined
    03 > five = dis.call(5)
    04 Number {[[PrimitiveValue]]: 5}
    05 > five.wtf = 'potato'
    06 "potato"
    07 > five.wtf
    08 "potato"
    09 > five * 5
    10 25
    11 > five.wtf
    12 "potato"
    13 > five++
    14 5
    15 > five.wtf
    16 undefined
    17 > five.wtf = 'potato?'
    18 "potato?"
    19 > five.wtf
    20 undefined
    21 > five
    22 6
    
    > function dis() { "use strict"; return this }
    
    > five.valueOf = function () { return 10 }
    undefined
    > five * 5
    50
    
    var obj = { a : 1 };
    var string = 'mystr' + obj;
    var number = 3 + obj;
    
    five = dis.call(5)
    
    five.wtf = 'potato'
    
    five * 5
    
    five++
    
    five.wtf
    five.wtf = 'potato?'
    five.wtf
    
    (new Number(6)).wtf;
    (new Number(6)).wtf = 'potato?';
    (new Number(6)).wtf;
    
    (new Number(3) === 3)  // returns false
    (new Number(3) == 3)   // returns true, as the '==' operator coerces
    (+new Number(3) === 3) // returns true, as the '+' operator coerces
    
    > function dis() { return this }
    undefined
    > five = dis.call(5)
    [Number: 5]
    
    > five.wtf = 'potato'
    'potato'
    > five.wtf
    'potato'
    
    > five * 5
    25
    > five.wtf
    'potato'
    
    > five++
    5
    > five.wtf
    undefined
    
    > five.wtf = 'potato?'
    'potato?'
    > five.wtf
    undefined
    
    > five
    6
    
    > function dis() { return this }
    undefined
    
    > five = dis.call(5)
    Number {[[PrimitiveValue]]: 5}
    
    > five.wtf = 'potato'
    "potato"
    
    > five.wtf
    "potato"
    
    > five * 5
    25
    > five.wtf
    'potato'
    
    > five++
    5
    
    > num = 5
    5
    > num++
    5
    
    >num
    6
    
    >five
    6
    
    > five.wtf
    undefined
    
    > five.wtf = 'potato?'
    'potato?'
    
    > five.wtf
    undefined