美文网首页
js中的运算符

js中的运算符

作者: jxnu薛哥 | 来源:发表于2016-10-19 13:51 被阅读0次

    运算符,加减乘除一直都是语言的基础,和小学数据逻辑也很接近,可以说是简单的已经不能再简单了。但是在js中,总有让你打脸的地方

    1. 加法运算#

    (1)加法运算符<code>(+)</code>是最常见的运算符之一,但是使用规则却相对复杂。因为在JavaScript语言里面,这个运算符可以完成两种运算,既可以处理算术的<b>加法</b>,也可以用作字符串<b>连接</b>。

    // 加法
    1 + 1 // 2  没有对象或字符串, 数值相加
    true + true // 2    Number(true)==1
    1 + true // 2
    
    // 字符串连接
    '1' + '1' // "11"
    '1.1' + '1.1' // "1.11.1"
    

    1.如果运算子是对象,先自动转成原始类型的值。

    即先执行该对象的<code>valueOf</code>方法,如果结果还不是原始类型的值,再执行<code>toString</code>方法;如果对象是<code>Date</code>实例,则先执行<code>toString</code>方法

    2.两个运算子都是原始类型的值以后,只要有一个运算子是字符串,则两个运算子都转为字符串,执行字符串连接运算。
    3.否则,两个运算子都转为数值,执行加法运算。

    '1' + {foo: 'bar'} // "1[object Object]" 对象调用toString之后字符串相加
    '1' + 1 // "11"  第一个是字符串,则使用字符串拼接
    '1' + true // "1true" 
    '1' + [1] // "11"
    

    上面代码中,由于运算符左边是一个字符串,导致右边的运算子都会先转为字符串,然后执行字符串连接运算。

    这种由于参数不同,而改变自身行为的现象,叫做“重载”(overload)。由于加法运算符是运行时决定到底执行那种运算,使用的时候必须很小心。

    '3' + 4 + 5 // "345"
    3 + 4 + '5' // "75"
    //相等于
    (3+4) + '5'
    

    加法运算符会将其他类型的值,自动转为字符串,然后再执行连接运算。

    var x = 1;
    x + '' // "1" 转字符串1
    
    [1, 2] + [3]  // 1,23
    //相等于
    "1,2" + "3"  // 数组先转为对应的字符串再进行拼接
    
    

    (2)加法运算符一定有左右两个运算子,如果只有右边一个运算子,就是另一个运算符,叫做“数值运算符”。

    + - 3 // 等同于 +(-3)
    + 1 + 2 // 等同于 +(1 + 2)
    + '1' // 1
    1 +  //   SyntaxError: Unexpected end of input
    

    <b>加法运算符以外的其他算术运算符(比如减法、除法和乘法),都不会发生重载。它们的规则是:所有运算子一律转为数值,再进行相应的数学运算。</b>

    1 - '2' // -1
    1 * '2' // 2
    1 / '2' // 0.5
    var now = new Date();
    typeof (now + 1) // "string"
    typeof (now - 1) // "number
    

    2. 余数运算符(%)#

    需要注意的是,运算结果的正负号由第一个运算子的正负号决定。

    -1 % 2 // -1
    1 % -2 // 1
    -1% -2 // -1 负数对比自己小的数求余都是自身
    -1 % -1 // -0
    

    3. 比较运算符的算法#

    1.如果运算子是对象,先自动转成原始类型的值(即先执行该对象的valueOf方法,如果结果还不是原始类型的值,再执行toString方法)。
    2.如果两个运算子都是字符串,则按照字典顺序比较(实际上是比较Unicode码点)。
    3.否则,将两个运算子都转成数值,再进行比较。

    [2] > [1] // true
    // 等同于  '2' > '1'
    
    [2] > [11] // true
    // 等同于 '2' > '11'
    
    {x: 2} > {x: 1} // false
    
    // 等同于 '[object Object]' > '[object Object]'
    

    4. 相等运算符和严格相等运算符#

    (1)简单说,它们的区别是相等运算符<code>(==)</code>比较两个值是否相等,严格相等运算符<code>(===)</code>比较它们是否为“同一个值”。如果两个值不是同一类型,严格相等运算符<code>(===)</code>直接返回false,而相等运算符<code>(==)</code>会将它们转化成同一个类型,再用严格相等运算符进行比较。

    /**类型不同,直接返回false*/
    1 === "1" // false  
    true === "true" // false 
    
    /**类型相同且值相同*/
    1 === 0x1 // true 注:typeof 0x1 === "number"
    
    NaN === NaN // false Nan与任何值都不相等
    +0 === -0 // true 除了作为分母,它俩性质一样
    

    (2)两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个对象。

    {} === {} // false
    [] === [] // false
    (function (){} === function (){}) // false
    
    var v1 = {};
    var v2 = v1;
    v1 === v2 // true
    

    (3)<code>undefined</code>和<code>null</code>与自身严格相等,所以,判断两个参数时,还需谨慎。

    undefined === undefined // true
    null === null // true
    
    var v1;
    var v2;
    v1 === v2 // true
    

    (4)注意,对于两个对象的比较,严格相等运算符比较的是地址,而大于或小于运算符比较的是值。

    new Date() > new Date() // false 值比较
    new Date() < new Date() // false 值比较
    new Date() === new Date() // false 地址比较
    

    5. 布尔值运算符#

    5.1概述
    布尔运算符用于将表达式转为布尔值,一共包含四个运算符。

    • 取反运算符:!
    • 且运算符:&
    • 或运算符:||
    • 三元运算符:?:

    5.2 !运算符
    对于非布尔值的数据,取反运算符会自动将其转为布尔值。规则是,以下六个值取反后为<code>true</code>,其他值取反后都为<code>false</code>(取反运算符有转换数据类型的作用)。

    !undefined // true
    !null      // true
    !false     // true
    !0         // true(包括+0和-0)
    !NaN       // true
    !''        // true
    
    !54 // false
    !'hello' // false
    ![] // false
    !{} // false
    
    !!x
    // 等同于
    Boolean(x)
    

    5.3 且运算符
    如果第一个运算子的布尔值为<code>true</code>,则返回第二个运算子的值(注意是值,不是布尔值);如果第一个运算子的布尔值为<code>false</code>,则直接返回第一个运算子的值,且不再对第二个运算子求值。

    't' && '' // ""
    't' && 'f' // "f"
    't' && (1 + 2) // 3
    '' && 'f' // ""
    '' && '' // ""
    
    var x = 1;
    (1 - 1) && ( x += 1) // 0
    x // 1
    

    5.4 或运算符
    如果第一个运算子的布尔值为<code>true</code>,则返回第一个运算子的值,且不再对第二个运算子求值;如果第一个运算子的布尔值为false,则返回第二个运算子的值。

        't' || '' // "t"
        't' || 'f' // "t"
        ''  || 'f' // "f"
        ''  || ''  // ""
    

    6. 位运算符#

    6.1 概述
    或运算(or):符号为|,表示若两个二进制位都为0,则结果为0,否则为1(有1则1)。
    与运算(and):符号为&,表示若两个二进制位都为1,则结果为1,否则为0(11则1)。
    否运算(not):符号为~,表示对一个二进制位取反。
    异或运算(xor):符号为^,表示若两个二进制位不相同,则结果为1,否则为0。(同0异1)

    位运算符直接处理每一个比特位(bit),所以是非常底层的运算,好处是速度极快,缺点是很不直观。位运算符只对整数起作用,如果一个运算子不是整数,会自动转为整数后再执行。另外,虽然在JavaScript内部,数值都是以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数。

    //转32为整数
    function toInt32(x) { 
    return x | 0;
    }
    toInt32(1.001) // 1
    toInt32(1.999) // 1
    toInt32(1) // 1
    toInt32(-1) // -1
    
    //一个整数大于32位的数位都会被舍去
    toInt32(Math.pow(2, 32) + 1) // 1
    toInt32(Math.pow(2, 32) - 1) // -1
    

    6.2 或和与

    0 | 3 // 3
    0 & 3 // 0
    
    /**
      *位运算只对整数有效,遇到小数时,会将小数部分舍去,只保留整数部分。
      *所以,将一个小数与0进行或运算,等同于对该数去除小数部分,即取整数位
      *不适用超过32位整数最大值2147483647的数
      */
    2.9 | 0 // 2
    -2.9 | 0 // -2
    

    6.3 取反运算
    将每个二进制位都变为相反值(0变为1,1变为0)

    ~ 3 // -4
    0000 0000 0000 0000 0000 0000 0000 0011
    ->
    1111 1111 1111 1111 1111 1111 1111 1100
    //JavaScript内部采用补码形式表示负数,即需要将这个数减去1,
    //再取一次反,然后加上负号,才能得到这个负数对应的10进制值
    ->减一
    1111 1111 1111 1111 1111 1111 1111 1011
    ->取反
    0000 0000 0000 0000 0000 0000 0000 0100
    ->加上负号
    -4
    //可以简单记忆成,一个数 与 自身的取反值相加,等于-1
    
    ~2 // -3
    ~-3 // 2
    
    //对一个整数连续两次“否运算”,得到它自身。
    ~~3 // 3
    
    

    所有的位运算都只对整数有效。否运算遇到小数时,也会将小数部分舍去,只保留整数部分。所以,对一个小数连续进行两次否运算,能达到取整效果。使用否运算取整,是所有取整方法中最快的一种
    对于其他类型的参数,否运算也是先用Number转为数值,然后再进行处理

    ~~2.9 // 2
    ~~47.11 // 47
    
    // 以下例子相当于~Number('011')
    ~'011' // -12
    ~'42 cats' // -1
    ~'0xcafebabe' // 889275713
    ~'deadbeef' // -1
    

    6.4 异或运算
    同0异1

    0 ^ 3 // 3
    

    “异或运算”有一个特殊运用:互换变量值

    var a = 1;
    var b = 2;
    a ^= b, b ^= a, a ^= b;
    a // 2
    b // 1
    
    0001
    0010
    
    a=0011
    ->
    b=0001
    ->
    a=0010
    

    6.5 左移运算符
    左移运算符表示将一个数的二进制值向左移动指定的位数,尾部补0,即乘以2的指定次方。

    4 << 1// 8
    -4 << 1// -8
    

    RGB转HEX

    var color = {r: 186, g: 218, b: 85};
    // RGB to HEX
    // (1 << 24)的作用为保证结果是6位数
    var rgb2hex = function(r, g, b) {
     return '#' + ((1 << 24) + (r << 16) + (g << 8) + b) .toString(16) .substr(1);
    }
    rgb2hex(color.r,color.g,color.b);
    //#bada55
    

    6.6 右移运算
    右移运算符表示将一个数的二进制值向右移动指定的位数,头部补0,即除以2的指定次方(最高位即符号位不参与移动)

    4 >> 1// 2
    /*
    4的二进制:0000 0000 0000 0000 0000 0000 0000 0100
    右移一位: 0000 0000 0000 0000 0000 0000 0000 0010
    */
    
    1>>1 // 0
    
    -4 >> 1 // -2
    /*
    

    7. void运算符#

    是不是经常会看到这样一句代码:

    <a href="javascript:void(0)">链接</a>
    

    虽然知道这个功能是点击链接没反应,但是,并不知道为什么要这样用,是吗?让我们一起探究一下吧

    void运算符的作用是执行一个表达式,然后不返回任何值,或者说返回undefined。因此,上面的a链接才不会执行跳转。

    var x = 3;
    void (x = 5) //undefined
    x // 5
    
    //void 的优先级很高,和其它运算符在一起,需要括号括起来
    void 4 + 7 // NaN
    //等于
    void(4) + 7
    

    8. 逗号运算符#

    逗号运算符用于对两个表达式求值,并返回后一个表达式的值。

    'a', 'b' // "b"
    var x = 0;
    var y = (x++, 10);
    x // 1
    y // 10
    

    相关文章

      网友评论

          本文标题:js中的运算符

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