标签: 原始值

  • JavaScript 加号运算符

    JavaScript 加号运算符的作用

    作用 示例 结果
    1, 相加数值 7 + 7 数值 14
    2, 连接字符串 ‘7’ + ‘7’ 字符串 ’77’
    3, 转换操作数为数值 + ‘7’ 数值 7

    1, 两个操作数

    有两个操作数 a + b 时,会相加数值或者连接字符串。

    在 JavaScript 中对两个操作数进行 + 运算时,可能会触发将其转换为原始值(ToPrimitive)、转换为数字(ToNumber)、转换为字符串(ToString)。

    ToPrimitive 转换顺序:

    1. 若操作数是原始值,则返回它;
    2. 若它的 valueOf() 的返回值是原始值,则返回 valueOf() 的返回值;
    3. 若它的 toString() 的返回值是原始值,则返回 toString() 的返回值;
    4. 抛出 TypeError 错误。

    ToPrimitive 的转换顺序并不是完全绝对的,其中第 2 步和第 3 步可以调换,目前只有 Date 对象是在转换为原始值时是先调用 toString,再调用 toValueOf,其余均符合上面的转换顺序。

    JavaScript 的原始值包括:undefined、null、布尔值、数字、字符串。

    a + b

    把操作数 a、b 转换为原始值还不能马上进行 + 运算,还需要再进行 ToNumber 或者 ToString 转换为相同类型。

    ToNumber 转换顺序:

    • undefined => NaN
    • null => 0
    • true => 1
    • false => 0
    • 数字 => 自身
    • 字符串 => 转换为数字,例如 “2.2” 转换为 2.2、”2.2a” 转换为 NaN

    字符串转换为数字可以参考(实际中不是像下面这样做的,但结果一致):

    "2.2" / 1 // 2.2
    "2.a" / 1 // NaN
    

    ToString 转换书序:

    • undefined => “undefined”
    • null => “null”
    • true => “true”
    • false => “false”
    • 数字 => 转换为字符串,例如 1 转换为 “1”、NaN 转换为 “NaN”
    • 字符串 => 自身

    ToString 很好理解,简单地看就是在原来非字符串的两侧加上引号。

    当 a + b 时,先将 a、b 转换为原始值,如果其中有一个是字符串,则将另外一个也转换为字符串,连接两个字符串并返回;将两个操作数转换为数字,相加并返回。

    var a = true;
    var b = false;
    a + b // ? a 原始值是 true, b 原始值是 false, 均不是字符串, 因此是 1
    
    var a = 1;
    var b = [2];
    a + b // ? a 原始值是 1, b 原始值是 "2", 因此是 "12"
    
    var a = 1;
    var b = new Date;
    a + b // ?
    

    2, 一个操作数

    只有一个操作数时,会转换操作数为数值。这个比较好理解,可以按照上面提到的除以 1,结果其实就是操作数除以 1 或者乘以 1。

    3, 看似两个操作数

    var a = {};
    var b = [];
    a + b // 根据转换为原始值的规则, 结果是 "[object Object]"
    
    {} + [] // 结果是 0, 为什么呢
    

    因为 JavaScript 解释器(一般浏览器环境)会将第一行的 {} 代码块忽略掉,因此如下的代码看似两个操作数,实际在浏览器中是一个,即只有 + []

    在 NodeJS 里面就不会将第一行的 {} 代码块忽略掉,其执行结果是 “[object Object]”。

    另外,关于转换为原始值中出现 TypeError,可以进行简单的重现:

    var a = {
        toString: function() {
            return [];
        },
        valueOf: function() {
            return [];
        }
    };
    var b = null;
    a + b // 将会看到 TypeError: Cannot convert object to primitive value
    
  • JavaScript 弱类判断速查表

    JavaScript 弱类 == 判断速查表

    JavaScript 弱类判断

    通过此表可以快速查询弱类判断结果。

    JavaScript == 判断遵循规则如下:

    1. null == undefined => true
    2. 字符串 == 数字 => 先将字符串转换为数字,再比较两者的值
    3. 布尔值 == 非布尔值 => 将 true 转换为 1,false 转换为 0,再进行比较
    4. 对象 == 原始值 => 先将对象转换为原始值,再进行比较。JavaScript 内置类转换为原始值,先尝试调用 valueOf 方法,取得结果不是原始值再调用 toString 方法。日期类 Date 对象特殊,Date 对象只使用 toString 转换为原始值。
    5. 其他比较不相等。

    原始值转换还体现在操作符 +,它可以对两个数值相加,也可以连接两个字符串,更可以转换操作数为数值。当参与 + 运算的操作数只有一个时,得到的结果与 parseFloat 非常相似。区别在于 + 右侧的操作数必须是合法的数值形式,parseFloat 从左到右尽可能地识别数字。

    • + ‘5.2’ => 5.2
    • parseFloat(‘5.2’) => 5.2
    • + ‘5.2.5’ => NaN
    • parseFloat(‘5.2.5’) => 5.2
    • + ‘5.2a’ => NaN
    • parseFloat(‘5.2a’) => 5.2

    + 的趣味更体现在原始值转换中,此处 Date 对象转换原始值只是一个引子。