(54)Wangdao.com第七天_JavaScript 运算符

JavaScript 运算符,也叫操作符

    • 对一个或者多个值进行运算,都是会返回结果的。
    • 比如:
    • typeof    返回一个值的类型,返回值类型是字符串。

 

隐式类型转换:

 

  • 任意值 = 任意值 + "";    // 就能转换成字符串
  • 任意值 = 任意值 - 0;    // 就能转换成Number
  • 任意值 = +任意值;    // 就能转换成 Number,更简洁
  • 任意值 = !!任意值;    // 即可将 任意值 转换成布尔类型的值

 

 

 


 

  • 算术运算符

不会对等号右边的值产生影响;

对非 Number 的值进行运算时,都会先转换成 Number 再运算,除非有字符串进行运算;

任何值与 NaN 进行运算,都得 NaN 。

 

+    对两个值进行相加,返回一个数字 Number ,但是又字符串进行运算会返回一个字符串

      • 两个字符串相加,会拼串成一个字符串:
        • b = "123"+"456";    // b 还是一个字符串,"123456"
      • 任何值和字符串进行运算,都会先转换成字符串,然后拼串:
        • c = 123+"4";    // c 等于字符串"1234"
          result = 1 + 2 + '3';    // result 为字符串 '33'
          result = '1' + 2 + 3;    // result 为字符串 '123'
  • 啊加法运算符是在运行时决定,到底是执行相加,还是执行连接。
  • 也就是说,运算子的不同,导致了不同的语法行为,这种现象称为 “重载”(overload)
  • 运算子是对象,必须先转成原始类型的值,然后再相加
  • 对象转成原始类型的值
    • 首先,自动调用对象的valueOf方法,对象的valueOf方法总是返回对象自身
    • 再自动调用对象的toString方法,将其转为字符串
      • var obj = { p: 1 };
        obj.valueOf()    // { p: 1 }
        
        obj.valueOf().toString()    // "[object Object]"

         

    • 自己定义valueOf方法或toString方法,得到想要的结果。

      var obj = {
          valueOf: function () {    // 重写 .valueOf()
              return 1;
          }
      };
      
      obj + 2     // 3
      
      
      
      var obj = {
          toString: function () {    // 重写 .toString()
              return 'hello';
          }
      };
      
      obj + 2     // "hello2"

       

 


 

-    对两个值进行相减,返回一个数字 Number

*    对两个值进行相乘,返回一个数字 Number

/    对两个值进行相除,返回一个数字 Number

 对两个值进行取余,返回一个数字 Number

  • 为了得到负数的正确余数值,可以先使用绝对值函数
    • // 正确的写法
      function isOdd(n) {
          return Math.abs(n % 2) === 1;
      }
      isOdd(-5)    // true
      isOdd(-4)    // false

       

  • 可以用于浮点数的运算。但是,由于浮点数不是精确的值,无法得到完全准确的结果

** 指数运算符

  • 前一个运算子是底数,后一个运算子是指数
    • 2 ** 4     // 16    即 2 的 4 次方

       

  • 多个指数运算符连用时,先进行最右边的计算
    • 2 ** 3 ** 2    // 512    相当于 2 ** (3 ** 2)

 


 

  • 一元运算符

只需要一个操作数

对于非数字运算,会先转换成 Number 再进行运算

    • + 正号    不会对操作数产生任何影响
      • var result = 1 + +'2' + 3;    // result 为 Number 类型的 6
    • - 负号    会对数组进行符号的取反
    • ++    自增1
      • var a = 1;
        a++;    // a 在这条语句执行完以后,a = 2
        ++a;    // a 在这条语句执行过程中 a = 2
    • --    自减1
      • var b =  2;
        result = b-- + b;    // b = 1 , result = 3
        result = --b + b;    // b = 1, result = 2

         

 


 

  • js 的三种逻辑运算符    &&    ||    
  • 对操作值无影响
  • 对于非布尔值进行
    • 与运算时,会先将其转换成布尔值比较,再返回原值。
    • 若两个值都是 true,则返回后边的值;若两个值中有 false,则返回前面的false 。
    • 若第一个值为 true,则必然返回第二个值;若第一个值为 false,则返回第一个值。
    • 或运算,会先将其转换成布尔值运算,再返回原值。
    • 若第一个值为 true,则返回第一个值;若第一个值为 false,则必然返回第二个值。

!    对右侧的值进行非运算,并返回布尔类型的值:true 变 false;false 变 true

      • var a = false;
        a = !!a;    // 如果对一个值进行两次取反,不会发生变化。
      • var b = 10;
        b = !b;    // 对非布尔类型的值进行非运算,会先转换成 Boolean 类型,再进行运算

        可以利用这个特性进行隐式类型转换,b = !!b;    // 即可将 b 变成一个布尔值

&&    对符号两侧的值进行与运算,并返回布尔类型的值:只要有一个值为 false ,就返回 false

      • 如果第一个值为 false,则直接返回它的值,不会再对第二个运算子进行操作。    称 "短路 short cut"
      • 有些程序员喜欢用它取代 if 结构
      • if (i) {
            doSomething();
        }
        
        // 等价于
        
        i && doSomething();

         

 

||    对符号两侧的值进行或运算,并返回布尔类型的值:只要有一个值为 true,就返回 true

      • 如果第一个值为 true,则不会再判断第二个值了。

 


  • 赋值运算符

=    将 右侧的值 赋给 左侧的变量

  • 与算术运算符的结合
  • x += y    // 等同于 x = x + y
    
    x -= y    // 等同于 x = x - y
    
    x *= y    // 等同于 x = x * y
    
    x /= y    // 等同于 x = x / y
    
    x %= y    // 等同于 x = x % y
    
    x **= y    // x = x ** y

     

  • 与位运算符的结合
  • x >>= y    // 等同于 x = x >> y
    
    x <<= y    // 等同于 x = x << y
    
    x >>>= y    // 等同于 x = x >>> y
    
    x &= y    // 等同于 x = x & y
    
    x |= y    // 等同于 x = x | y
    
    x ^= y    // 等同于 x = x ^ y

 


  •  关系运算符

比较两个值之间的大小关系,关系成立则返回 true,关系不成立则返回 false 。

对于非数字进行比较,则先转换成数字再比较。。。

如果两个字符串比较,不会转换成数字,会比较Unicode 。。。一位一位比,出结果就不比了。。。可以进行英文名排序。

任何值和 NaN 进行任何比较,都返回 false 。

  • result = 5 < 4;    // 关系不成立,result 为false 。
    
    //
    console.log("123456" < "5");    // 希望得到一个数字上的正确比较
    // 则可以写成
    console.log("123456" < +"5");    // 即,为其中一个字符串加 "+" 转换成数字,再进行比较

>    

==

!=    

<    

>=    

<=    

 undefinednull与其他类型的值比较时,结果都为false,它们互相比较时结果为true


  • 相等运算符    ==

比较两个值是否相等。

相等返回true,不等返回false

  • var a = 10;
    console.log(a == 2);    // 很明显 打印 false

     

  • 如果两个值的类型不同时,会自动进行类型转换,
    • console.log('1' == 1);    // 会打印 true
    • 具体转换成什么类型是不一定的,大部分情况转换成 Number
    • 在上面的例子里,是将 '1' 转换成了 Number 类型。

    • console.log(null == 0);    // 这是特殊情况,没有转换成 Number,所以打印 false
      console.log(null == undefined);    // 这也是特殊情况,由于 undefined 衍生自 null,所以打印 true
      console.log(NaN == NaN); // 这也是特殊情况,NaN 不和任何值相等,包括它本身,所以打印 false

      可以通过 isNaN() 函数判断一个值是否是NaN
      var b = NaN;
      console.log(isNaN(b)); // 如果是 NaN 返回true,否则返回 false

 


  • 不相等运算符    !=

比较两个值是否不相等。

不等返回true,相等返回false

如果两个值的类型不同时,会自动进行类型转换,再进行比较。

 


  • 条件运算符,也叫 三元运算符
    • 语法
      • (条件表达式)?:(语句1):(语句2);
    • 在需要返回值的场合,只能使用三元条件表达式,而不能使用if..else
    • 流程:
      • 首先对表达式进行求值
        • 所得值为 true,则执行语句1,并返回执行结果
        • 所得值为 false,则执行语句2,并返回执行结果
    • 实例
      • var a = 10;
        var b = 20;
        
        a > b : alert('a大'):alert('b大');
        
        /***************************/
        
        // 获取 a 和 b 中的最大值
        var max = a > b ? a:b;
        
        // 获取 a , b , c 中的最大值
        var max = ( a > b)? (a>c?a:c):(b>c?b:c);

         

    • 如果 条件表达式 非布尔值,会转换成布尔值

  • 其他运算符

===    全等    

      • 判断两个值是否全等
      • 不会进行类型转换,如果类型不同,直接返回 false
      • console.log(1 === '1');    // false
        console.log(null === undefined);    // false
      • 两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个地址。
        • {} === {}    // false
          [] === []    // false
          (function () {} === function () {})    // false
          
          // 结果都是不相等
          // 原因是对于复合类型的值,严格相等运算比较的是,它们是否引用同一个内存地址
          // 而运算符两边的空对象、空数组、空函数的值,都存放在不同的内存地址,结果当然是false
        • 如果两个变量引用同一个对象,则它们相等
        • var v1 = {};
          var v2 = v1;
          v1 === v2    // true
      • undefinednull与自身严格相等
      • 两个只声明未赋值的变量是相等的 都是 undefined

 

!==    不全等    

      • 判断两个值是否不全等,
      • 不会进行类型转换,如果类型不同,直接返回 true
      • console.log(1 !== '1');    // true
        console.log(null !== undefined);    // true

        1 !== '1'    // true
        // 等同于
        !(1 === '1')

 

void 运算符

作用是执行一个表达式,然后不返回任何值,或者说返回undefined

  • 优先级很高
    • void 4 + 7    // 实际上等同于 (void 4) + 7
      void (x = 5)     // 执行完 x=5 后 , 返回 undefined

       

  • 主要作用
    • 浏览器的书签工具(bookmarklet),
    • 在超级链接中插入代码防止网页跳转。
      • <a href="javascript: void(f())">文字</a>
        
        
        <a href="javascript: void(document.form.submit())">
          提交
        </a>

         


 

  • 逗号运算符,
  • 使用 ',' 可以分割多个语句,一般可以在声明变量时使用。
  • var a , b , c;
    var a = 1 , b , c = 3;

     

  • 用于对两个表达式求值,并返回后一个表达式的值
    • 'a', 'b'    // "b"
      
      var x = 0;
      var y = (x++, 10);
      x     // 1
      y     // 10

      在返回一个值之前,先进行一些辅助操作

      var value = (console.log('Hi!'), true);
      // Hi!
      
      value // true

       


运算符的优先级

  • 在 js 中有一个 运算符优先级 的表,越靠上优先级越高
  • 表并不需要记忆,遇到优先级不清楚的,可以使用括号改变优先级。

 


 二进制位运算符

用于直接对二进制位进行计算,一共有7个

|     或运算符 or    两个二进制位都为0,则结果为0   

  • x = x | 0    保持原位不变
  • (不管是整数或小数)转为32位整数
    • function toInt32(x) {
          return x | 0;
      }
      
      toInt32(1.001)    // 1
      toInt32(1.999)    // 1
      toInt32(1)    // 1
      toInt32(-1)    // -1
      toInt32(Math.pow(2, 32) + 1)    // 1
      toInt32(Math.pow(2, 32) - 1)    // -1

       

&    与运算符 and    两个二进制位都为1,则结果为 1   

  • 0 & 3    // 0
  • 0(二进制00)和3(二进制11)进行二进制与运算会得到00

 

~    否运算符 not   对一个二进制位取反

  • ~ 3     // -4    可以理解成   -3减一
  • 3进行二进制否运算,得到-4。之所以会有这样的结果,是因为位运算时,JavaScirpt 内部将所有的运算子都转为32位的二进制整数再进行运算
  • // 3的32位整数形式是00000000000000000000000000000011
    // 二进制否运算以后得到11111111111111111111111111111100
    // 由于第一位(符号位)是1,所以这个数是一个负数
    // JavaScript 内部采用补码形式表示负数,
    // 即需要将这个数减去1,再取一次反,然后加上负号,才能得到这个负数对应的10进制值
    // 这个数减去1等于11111111111111111111111111111011,再取一次反得到00000000000000000000000000000100,再加上负号就是-4

     

  • 对一个整数连续两次二进制否运算,得到它自身。
  • 二进制否运算遇到小数时,也会将小数部分舍去,只保留整数部分。
    • 对一个小数连续进行两次二进制否运算,能达到取整效果
    • ~~2.9    // 2
      ~~47.11    // 47
      ~~1.9999    // 1
      ~~3    // 3
      
      // 使用二进制否运算取整,是所有取整方法中最快的一种
  • 对于其他类型的值, 进行二进制否运算,JavaScript 引擎会先调用 Number函数,将字符串转为数值

 

^    异或运算符 xor    两个二进制位不同,则结果为 1    

  • 连续对两个数ab进行三次异或运算,a^=b; b^=a; a^=b;,可以互换它们的值
  • // 在不引入临时变量的前提下,互换两个变量的值
    var a = 10;
    var b = 99;
    
    a ^= b, b ^= a, a ^= b;
    
    a     // 99
    b     // 10

    这是互换两个变量的值的最快方法。

  • 异或运算也可以用来取整
    • 12.9 ^ 0    // 12

       

<<  左移运算符 left shift

  • 表示将一个数的二进制值向左移动指定的位数,尾部补0,即乘以 2 的指定次方。
  • // 4 的二进制形式为100,
    // 左移一位为1000(即十进制的8)
    // 相当于乘以2的1次方
    
    4 << 1    // 8
    
    -4 << 1    // -8

     

  • 左移0位,就相当于将该数值转为32位整数,等同于取整,对于正数和负数都有效
  • 13.5 << 0    // 13
    
    -13.5 << 0    // -13

     

  • 将颜色的 RGB 值转为 HEX 值
  • // RGB to HEX
    // (1 << 24)的作用为保证结果是6位数
    // 自定义 将颜色的 RGB 值转为 HEX 值
    var rgb2hex = function(r, g, b) {
        return '#' + ((1 << 24) + (r << 16) + (g << 8) + b)
            .toString(16) // 先转成十六进制,然后返回字符串
            .substr(1);   // 去除字符串的最高位,返回后面六个字符串
    }

     

>>  右移运算符 right shift

  • 将一个数的二进制值向右移动指定的位数,头部补0即除以 2的指定次方(最高位即符号位不参与移动)
  • 4 >> 1
        // 2
        // 因为4的二进制形式为 00000000000000000000000000000100,
        // 右移一位得到 00000000000000000000000000000010,
        // 即为十进制的2
    
    -4 >> 1
        // -2
        // 因为-4的二进制形式为 11111111111111111111111111111100,
        // 右移一位,头部补1,得到 11111111111111111111111111111110,
        // 即为十进制的-2

     

  • 右移运算可以模拟 2 的整除运算
  • 5 >> 1    // 相当于 5 / 2 = 2
    
    21 >> 2    // 相当于 21 / 4 = 5
    
    21 >> 3    // 相当于 21 / 8 = 2
    
    21 >> 4    // 相当于 21 / 16 = 1

     

>>> 带符号位的右移运算符 zero filled right shift

  • 表示将一个数的二进制形式向右移动,包括符号位也参与移动,头部补0。所以,该运算总是得到正值。
  • 对于正数,该运算的结果与右移运算符(>>)完全一致,区别主要在于负数。
  • 是查看一个负整数在计算机内部的储存形式,最快的方法
    -1 >>> 0    // 4294967295
    // -1作为32位整数时,内部的储存形式使用无符号整数格式解读,值为 4294967295(即(2^32)-1,等于11111111111111111111111111111111)

     

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

 

  • 开关作用
    • 位运算符可以用作设置对象属性的开关
    • // 位运算符可以用作设置对象属性的开关
      // 可以设置一个四位的二进制数,它的每个位对应一个开关
      var FLAG_A = 1;     // 0001
      var FLAG_B = 2;     // 0010
      var FLAG_C = 4;     // 0100
      var FLAG_D = 8;     // 1000

       

    • // 与运算 检验当前设置 是否打开了指定开关
      var flags = 5; // 二进制的0101
      
      if (flags & FLAG_C) {    // 0101 & 0100 => 0100 => true
        // 如果打开了就......
      }

       

    • // 假设需要打开A、B、D三个开关,我们可以构造一个掩码变量
      var mask = FLAG_A | FLAG_B | FLAG_D;    // 0001 | 0010 | 1000 => 1011

       

    • flags = flags & mask;    // 与运算可以将当前设置中凡是与开关设置不一样的项
      
      flags = flags ^ mask;    // 异或运算可以切换(toggle)当前设置,即第一次执行可以得到当前设置的相反值,再执行一次又得到原来的值。
      
      flags = ~flags;    // 否运算可以翻转当前设置,即原设置为0,运算后变为1;原设置为1,运算后变为0

       

posted @ 2018-09-18 23:06  耶梦加德  阅读(172)  评论(0编辑  收藏  举报