JS运算符

95 阅读4分钟

number 运算

  • 加减乘除
  • 余数 x % 7
  • 指数 x ** 3
  • 自增自减 x++ / ++x / x-- / --x
  • 求值运算符 +x
  • 负数运算符 -x
  • string 运算:连接运算 '123' + '456' 注意一下,其中除法不能除以0:

9/0=Infinity(正无穷大)

-9/0=Infinity(负无穷大)

10 % 7 = 17 % 7 余数有个规律,两个数相隔差7,那么他们除以7的余数会相等

但是,-1%7并不会等于6%7而是-1

指数: 7的平方 = 7 ** 2

自增: n在前,值为前;n在后,值为后(n为任意数值)

let a = 1
let b = 2
a++的值为1
++a的值为2
b--的值为2
--b的值为1

求值运算符 +x:只是求值。。不会变正数

负数运算符 -x:正数变负数,负数变正数

string运算 '123' + '456',只支持+号运算符

1 + '2' = '12'其他语言中,数字和字符串一般不能相加, 但是js是个可以。它会先把1变成字符串'1',然后再相加

1 + '2' = '1' + '2' = '12'

如果一个数字和字符串相加,那么js会先把数字变成字符串再相加。

但是,减号则又是另一种情况,字符串是不支持减号的 '2' - 1 = 1

'2'会变转换成数字2,再减去1,然后得出一个数字1

  • 尽量少用自增自减 因为容易你和别人都记错

  • 不同类型不要加起来 把 1 和 '2' 加起来是几个意思

比较运算符

>
<
>=
<=
==     //相等(模糊相等)
!=     //不等(不模糊相等)
===    //全等
!==    //不全等

JS三位一体

image.png

0 == []
0 == '0'
0 == '\t'
//但是右边三个互不相等
  • 注意! 永远不要使用 ==!

用 === 代替

== 的问题在于,它总是自作聪明(自动类型转换)

  • x == y 真值表(了解即可,永远不要用==)

image.png

令人难以理解

[]==false但不是 falsy
[]==false但{}==true 
[[]]==false

x === y 真值表

image.png

没有任何费解

  • 基本类型看值是否相等
  • 对象看地址是否相等
[] !== []    //false,因为空数组地址不同  []/*#101*/ !== []/*#108*/
{} !== {}    //false,理由同上

NaN !== NaN(唯一特例,强行记忆一下) NaN是个数字,但是不相等

布尔运算符

  • 或且非
||   //或
&&   //且
!    //非
  • 短路逻辑 &&短路逻辑:
console = undefined/{}      //假设console不存在或者被占用,
                            那么console.log就会报错
                       
if(console){
  if(console.log){
    console.log('hi')        
    }
}                        
//这样写的话,就不会报错,如果console不存在的话第一层就不通过,
如果console存在,但是却被其他值占用,那么第二层console.log也不通过,
这种写法叫“防御性编程”

console && console.log && console.log('hi')   
//可以简写成这样,以防 console 不存在报错

||短路逻辑:

a = a || 100 (100是a的保底值)

function add(n){
  n = n || 0    //相当于if(!n){n=0}else{n=n},n不存在为0,存在为n
return n+1
}
//但是这种写法有一个bug,当n等于5个falsy值的时候,都会让n为假,比如''
//所以js除了一个新语法代替它

function add(n=0){     //意思是如果n为null或undefined的时候,n = 0
    return n+1
    }
    
add('')              //值为'1' , ''+1 = '1'
add(null/undefined)  //1
add(NaN)             //NaN

二进制运算符

  • 或|、与&、否~
0b1111 | 0b1010    
//15

(0b1001 | 0b1111).toString(2)   //要想显示成二进制数,就调用toString
//"1111"
  • | 两个位都为0,则结果为0,否则为1 image.png

  • & 两个位都为1,则结果为1,否则为0

0b1111 & 0b1010
//10
  • ~ 运算符是对位求反,1变0, 0变1,也就是求二进制的反码
// 1的二进制表示为: 00000000 00000000 00000000 00000001
// 3的二进制表示为: 00000000 00000000 00000000 00000011
// -----------------------------
// 1反码二进制表示: 11111111 11111111 11111111 11111110
// 由于第一位(符号位)是1,所以这个数是一个负数。JavaScript 内部采用补码形式表示负数,
   即需要将这个数减去1,再取一次反,然后加上负号,才能得到这个负数对应的10进制值。
// -----------------------------
// 1的反码减1:     11111111 11111111 11111111 11111101
// 反码取反:       00000000 00000000 00000000 00000010
// 表示为10进制加负号:-2
console.log(~ 1)     // -2

简单记忆:一个数与自身的取反值相加等于-1。

  • 异或^
(0b0111 ^ 
 0b1010).toString(2)
//"1101"

^ 两个位相同,则结果为0,否则为1

  • 左移<< 和 右移>>
(0b0001 << 1).toString(2)   //0010
"10"
(0b0010 >> 1).toString(2)   //0001
"1"
(0b0011 >> 1).toString(2)   //0001右边1会被蹭掉
"1"
(0b0011 << 1).toString(2)   //0110空位会自动补0
"110"

头部补零的右移运算符 >>> ,基本跟上面的右移动一样

平时工作很少用就是为了应付面试

使用与运算符判断奇偶

代码:

偶数 & 1 = 0
奇数 & 1 = 1

使用~, >>, <<, >>>, |来取整

代码:

console.log(~~ 6.83)    // 6 ,两次取反得到数字的正数部分
console.log(6.83 >> 0)  // 6 ,左移0位取整...
console.log(6.83 << 0)  // 6 ,右移0位取整...
console.log(6.83 | 0)   // 6 ,| 两个位都为0,则结果为0,否则为1。0进行或运算,等于自身。。
console.log(6.83 >>> 0)   // 6
//这些运算都会抹除小数部分

使用^来交换 a b 的值

代码:

var a = 5
var b = 8
a ^= b           //a ^= b意思是a = a ^ b
b ^= a           //b = b ^ a
a ^= b           //a = a ^ b
console.log(a)   // 8
console.log(b)   // 5

image.png

点运算符

  • 语法 对象 . 属性名 = 属性值
  • 作用 读取对象的属性值 / 设置对象的属性值
  • 有个疑问 不是对象,为什么也可以有属性?比如'a-b-c'.split('-')

因为 . 前面如果不是对象就临时创建一个封装对象,然后对象里面有原型,原型里面有split,执行完了以后,自动删除这个临时的对象

再比如,

let a = 1
a.toString()     //'1' ,1不是对象,为啥会得到'1'的值

//当js发现a不是对象的时候,会临时创建一个a1
a1 = new Number(a)
//然后执行toString
a1.toString()     //'1'
a1.valueOf()     //为啥是'1'?因为a1的值为1
//执行完toString后会删除a1
a1 = null

用内存图表示一下, image.png

JS 有特殊逻辑,点前面不是对象,就把它封装成对象

  1. number 会变成 Number 对象
  2. string 会变成 String 对象
  3. bool 会变成 Boolean 对象 程序员从来不用这三种对象,只用简单类型

void 运算符 (了解一下)

  • 语法 void 表达式/语句
  • 作用 求表达式的值,或执行语句

然后 void 的值总是为 undefined

  • 需求
<a href="http://example.com" onclick="f(); return false;">点击</a>

return 假值可以阻止默认动作 <a href="javascript: void(f())">文字</a> 改用 void 可以炫技

逗号运算符

  • 语法 表达式1, 表达式2, ..., 表达式n
  • 作用 将最后一个值作为整体的值
  • 使用 let a = (1,2,3,4,5)

那么 a 的值就是 5

let f = (x) => (console.log('平方值为'), x*x)

注意上面的括号不能省

运算符优先级

优先级是什么?

  • 不同运算符

1 + 2 * 3 是先算(1 + 2) * 3还是 1 + (2 * 3)

if(!a === 1) 是先算(! a) === 1还是 ! (a === 1)

总结一句话,圆括号优先级最高,比如

if((!a) === 1)  //则先算!a
if(!(a === 1))  //就先算a === 1
  • 相同运算符 从左到右 a + b + c

从右到左 a = b = c = d

let a,b,c,d

a = b = c = d
//等价于
a = (b = (c = (d = 2)))    //圆括号优先级最高

优先级就是先算什么后算什么

  • 技巧 圆括号优先级最高