JavaScript 基本类型的装箱与拆箱

作者: 老邵 | 来源:发表于2019-05-13 18:27 被阅读4次

    在 JavaScript 中,有时会碰到以下两种类型的代码:

    1.  var num = 123;
       var str = '123';
       num.toFixed(2); // '123.00'
       str.split(''); // ['1','2','3']
      
    2.  var num = [1,2,3];
       var str = {
             name:'hahaha'
       };
       console.log(num+1); //1,2,31
       String(str); //'[object Object]'
      

    在第一段代码中,我们在两个基本类型的值上调用方法。众所周知,在 JavaScript 中只有 Object 类型才有方法。在第二段代码中,我们可以把两个 Object 类型的值当做基本类型的值直接使用。这就是 JavaScript 装箱与拆箱在代码中的具体体现。

    下面我分别来解释一下 JavaScript 中的装箱与拆箱。

    一:装箱

    所谓装箱,就是把基本类型转变为对应的对象。装箱分为隐式和显示。

    隐式装箱
    每当读取一个基本类型的值时,后台会创建一个该基本类型所对应的对象。在这个基本类型上调用方法,其实是在这个基本类型对象上调用方法。这个基本类型的对象是临时的,它只存在于方法调用那一行代码执行的瞬间,执行方法后立刻被销毁。具体到代码如下:

        num.toFixed(2); // '123.00'
    //上方代码在后台的真正步骤为
        var c = new Number(123);
        c.toFixed(2);
        c = null;
    

    当我们访问 num 时,要从内存中读取这个数字的值,此时访问过程处于读取模式。在读取模式中,后台进行了三步处理:

    1. 创建一个 Number 类型的实例。
    2. 在实例上调用方法。
    3. 销毁实例。

    显式装箱
    通过内置对象 Boolean、Object、String 等可以对基本类型进行显示装箱。

        var obj = new String('123');
    

    二:拆箱

    拆箱与装箱相反,把对象转变为基本类型的值。拆箱过程内部调用了抽象操作 ToPrimitive 。该操作接受两个参数,第一个参数是要转变的对象,第二个参数 PreferredType 是对象被期待转成的类型。第二个参数不是必须的,默认该参数为 number,即对象被期待转为数字类型。有些操作如 String(obj) 会传入 PreferredType 参数。有些操作如 obj + " " 不会传入 PreferredType。

    具体转换过程是这样的。默认情况下,ToPrimitive 先检查对象是否有 valueOf 方法,如果有则再检查 valueOf 方法是否有基本类型的返回值。如果没有 valueOf 方法或 valueOf 方法没有返回值,则调用 toString 方法。如果 toString 方法也没有返回值,产生 TypeError 错误。

    PreferredType 影响 valueOf 与 toString 的调用顺序。如果 PreferrenType 的值为 string。则先调用 toString ,再调用 valueOf。

    具体测试代码如下:

    var obj = {
        valueOf : () => {console.log("valueOf"); return []},
        toString : () => {console.log("toString"); return []}
    }
    
    String(obj)
    // toString
    // valueOf
    // Uncaught TypeError: Cannot convert object to primitive value
    
    obj+' '
    //valueOf
    //toString
    // Uncaught TypeError: Cannot convert object to primitive value
    
    Number(obj)
    //valueOf
    //toString
    // Uncaught TypeError: Cannot convert object to primitive value
    
    Gwen Weustink 2016-03-02 09-53-30 .jpg

    相关文章

      网友评论

        本文标题:JavaScript 基本类型的装箱与拆箱

        本文链接:https://www.haomeiwen.com/subject/vjjboqtx.html