• 技术文章 >web前端 >js教程

    理解Javascript中的“+”运算符

    巴扎黑巴扎黑2017-04-15 09:06:01原创742
    在网上或面试题中经常会看到一些“奇怪”的语句,比如

    {}+{}
    // "[object Object][object Object]"
    
    {}+[]
    // 0
    
    []+{}
    // "[object Object]"
    
    []+[]
    // ""

    在Javascript中+运算符是个重载运算符,可用来拼接字符串,以及把两个“数字”相加。至于是哪种情况要看运算符两边参数的类型。
    在日常的开发中我们也不会碰到这么麻烦的事,但弄弄清楚总是好的。在规范 中巴拉巴拉地说了一堆,简单来说就是:

    1. 对于原生类型,参数中只要有一方是字符串,则按字符串连接处理,否则按数字相加处理,不是数字的会先转成数字再相加。

    原生类型有:undefined, null, boolean, number, string。

    下面是一些示例:

    0 + '1'     // '01'
    null + 1    // 1
    true + 1    // 2
    false + 1   // 0
    undefined + 2   // NaN,  因为undefined转成Number是NaN

    2. 对于引用类型,则需要先转换成原生类型,再按以上规则相加。如何转换在规范中有详细的说明,但规范看起来是有点费劲。 简单来说就是:默认情况下都转化成字符串,要搞特殊的话,请重写valueOf()方法。

    来个例子:

    function Complex(a, b) {
      this.a = a;
      this.b = b;
    }
    
    Complex.prototype.valueOf() {
      return this.a;
    }
    
    new Complex(2, 3) + new Complex(4, 5);
    // 6

    但由于Js不支持真正的操作符重载,即不能相加得到自定义类型的对象, 所以以上示例在实践代码中非常少用。

    不过目前的知识足够回答原先的问题了。但是慢着,{}+[] 为什么和 []+{}不一样? 这其实是个语法问题。前者相当于:

    {}
    +[]

    其实是两个句子, [] 转换成数字是 0。很容易验证 ({}+[]) === '[object Object]'

    +[]  // 0

    有人可能要问,那 new Date()valueOf() 不是转换成数字吗?为什么相加结果还是字符串类型呢?

    new Date().valueOf();
    // 1491904757087
    
    1 + new Date();
    // "1Tue Apr 11 2017 18:02:16 GMT+0800 (CST)"

    这是Date类做了特殊处理, @@toPrimitive, 默认情况下对 Date 的相加以字符串方式连接,但比较时则会转换成数字。

    new Date() < new Date('2018-01-01')
    // true, 现在是2017

    将引用类型转换成原生类型在很多操作符中都有用到,比如 <, >, 所以有必要对其研究一番, 以下js代码大概描述了其行为。

    /**
     * @param input     即要转换的对象
     * @preferredType   期望转换成的类型,可以是string或number
     */
    function ToPrimitive(input, preferredType) {
      if (typeof input !== 'object') {
        return input;   // 本来就是原生类型
      }
    
      var hint = preferredType || 'default';
      if (typeof input['@@toPrimitive'] === 'function') {   // @@toPrimitive是个内部方法,这里只是示例说明其工作原理
        return input['@@toPrimitive'](input, hint);   // 这就是为什么Date能特殊处理的原因
      }
    
      if (hint === 'string') {
        return input.toString();
      }
    
      return input.valueOf();
    }

    详细的请参考规范


    在网上或面试题中经常会看到一些“奇怪”的语句,比如

    {}+{}
    // "[object Object][object Object]"
    
    {}+[]
    // 0
    
    []+{}
    // "[object Object]"
    
    []+[]
    // ""

    在Javascript中+运算符是个重载运算符,可用来拼接字符串,以及把两个“数字”相加。至于是哪种情况要看运算符两边参数的类型。
    在日常的开发中我们也不会碰到这么麻烦的事,但弄弄清楚总是好的。在规范 中巴拉巴拉地说了一堆,简单来说就是:

    1. 对于原生类型,参数中只要有一方是字符串,则按字符串连接处理,否则按数字相加处理,不是数字的会先转成数字再相加。

    原生类型有:undefined, null, boolean, number, string。

    下面是一些示例:

    0 + '1'     // '01'
    null + 1    // 1
    true + 1    // 2
    false + 1   // 0
    undefined + 2   // NaN,  因为undefined转成Number是NaN

    2. 对于引用类型,则需要先转换成原生类型,再按以上规则相加。如何转换在规范中有详细的说明,但规范看起来是有点费劲。 简单来说就是:默认情况下都转化成字符串,要搞特殊的话,请重写valueOf()方法。

    来个例子:

    function Complex(a, b) {
      this.a = a;
      this.b = b;
    }
    
    Complex.prototype.valueOf() {
      return this.a;
    }
    
    new Complex(2, 3) + new Complex(4, 5);
    // 6

    但由于Js不支持真正的操作符重载,即不能相加得到自定义类型的对象, 所以以上示例在实践代码中非常少用。

    不过目前的知识足够回答原先的问题了。但是慢着,{}+[] 为什么和 []+{}不一样? 这其实是个语法问题。前者相当于:

    {}
    +[]

    其实是两个句子, [] 转换成数字是 0。很容易验证 ({}+[]) === '[object Object]'

    +[]  // 0

    有人可能要问,那 new Date()valueOf() 不是转换成数字吗?为什么相加结果还是字符串类型呢?

    new Date().valueOf();
    // 1491904757087
    
    1 + new Date();
    // "1Tue Apr 11 2017 18:02:16 GMT+0800 (CST)"

    这是Date类做了特殊处理, @@toPrimitive, 默认情况下对 Date 的相加以字符串方式连接,但比较时则会转换成数字。

    new Date() < new Date('2018-01-01')
    // true, 现在是2017

    将引用类型转换成原生类型在很多操作符中都有用到,比如 <, >, 所以有必要对其研究一番, 以下js代码大概描述了其行为。

    /**
     * @param input     即要转换的对象
     * @preferredType   期望转换成的类型,可以是string或number
     */
    function ToPrimitive(input, preferredType) {
      if (typeof input !== 'object') {
        return input;   // 本来就是原生类型
      }
    
      var hint = preferredType || 'default';
      if (typeof input['@@toPrimitive'] === 'function') {   // @@toPrimitive是个内部方法,这里只是示例说明其工作原理
        return input['@@toPrimitive'](input, hint);   // 这就是为什么Date能特殊处理的原因
      }
    
      if (hint === 'string') {
        return input.toString();
      }
    
      return input.valueOf();
    }

    以上就是理解Javascript中的“+”运算符的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:javascript,运算符
    上一篇:用Vue.js 和 Chart.js如何制作很炫的图表 下一篇:JavaScript实现选择排序算法的实例分析(图)
    VIP课程(WEB全栈开发)

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• 这些核心知识点,前后端沟通必须掌握!• JavaScript DOM 常用事件最新总结!• js实现图片跟随鼠标移动的两种方法• 利用js实现图片固定在屏幕的某个位置!• 教你用JavaScript实现一个“按键精灵”!
    1/1

    PHP中文网