认识JavaScript(4)JavaScript 的运算符

JavaScript 的运算符

1、算数运算符

1.1 所有算数运算符

  • 加法运算符:x + y
  • 减法运算符: x - y
  • 乘法运算符: x * y
  • 除法运算符:x / y
  • 指数运算符:x ** y
  • 余数运算符:x % y
  • 自增运算符:++x 或者 x++
  • 自减运算符:–x 或者 x–
  • 数值运算符: +x
  • 负数值运算符:-x
  • 赋值运算符 :=

1.2 加法运算符

1、俩数值相加

2 + 3    // 5

2、布尔值相加

true + true   	// 2
false + false   // 0

1 + true        // 2
false + 1       // 1

上面代码中,第一行是两个布尔值相加,第二行是数值与布尔值相加。这两种情况,布尔值都会自动转成数值(true= =1、false==0),然后再相加。

3、两个字符串相加

'a' + 'bc'    // "abc"

上面代码中,如果是两个字符串相加,这时加法运算符会变成连接运算符,返回一个新的字符串,将两个原字符串拼接在一起。

1 + 'a'     	// "1a"
false + 'a' 	// "falsea"

如果一个运算子是字符串,另一个运算子是非字符串,这时非字符串会转成字符串,再连接在一起。

所以加法运算符是在运行时决定,到底是执行相加,还是执行连接。也就是说,运算子的不同,导致了不同的语法行为,这种现象称为“重载”(overload)。

'3' + 4 + 5 		// "345"
3 + 4 + '5' 		// "75"

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

1 - '2' 	// -1
1 * '2' 	// 2
1 / '2' 	// 0.5

上面代码中,减法、除法和乘法运算符,都是将字符串自动转为数值(隐式类型转换),然后再运算。

1.3 余数运算符

余数运算符(%)返回前一个运算子被后一个运算子除,所得的余数。

在这里插入图片描述

12 % 5	 // 2

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

-1 % 2 		// -1
1 % -2 		// 1

所以,为了得到负数的正确余数值,可以先使用绝对值函数。

// 错误的写法
function isOdd(n) {
  return n % 2 === 1;
}
isOdd(-5) // false
isOdd(-4) // false

// 正确的写法
function isOdd(n) {
  return Math.abs(n % 2) === 1;
}
isOdd(-5) // true
isOdd(-4) // false

1.4 自增和自减运算符

自增和自减运算符,是一元运算符,只需要一个运算子。它们的作用是将运算子首先转为数值,然后加上1或者减去1。它们会修改原始变量。

var x = 1;

++x 	// 2
x 	    // 2

--x     // 1
x       // 1

上面代码的变量x自增后,返回2,再进行自减,返回1。这两种情况都会使得,原始变量x的值发生改变。

自增和自减运算符有一个需要注意的地方,就是放在变量之后,会先返回变量操作前的值,再进行自增/自减操作;放在变量之前,会先进行自增/自减操作,再返回变量操作后的值。

var x = 1;
var y = 1;

x++ // 1
++y // 2

上面代码中,x是先返回当前值,然后自增,所以得到1;y是先自增,然后返回新的值,所以得到2。

1.5 数值运算符,负数值运算符

数值运算符的作用在于可以将任何值转为数值(与Number函数的作用相同)。

+true 	// 1
+[] 	// 0
+{}	    // NaN

负数值运算符(-),也同样具有将一个值转为数值的功能,只不过得到的值正负相反。连用两个负数值运算符,等同于数值运算符。

var x = 1;
-x 		// -1
-(-x)   // 1

数值运算符号和负数值运算符,都会返回一个新的值,而不会改变原始变量的值。

1.6 指数运算符

指数运算符(**)完成指数运算,前一个运算子是底数,后一个运算子是指数。
在这里插入图片描述

2 ** 4    // 16

注意,指数运算符是右结合,而不是左结合。即多个指数运算符连用时,先进行最右边的计算。

2 ** 3 ** 2
// 512
// 相当于 2 ** (3 ** 2)

1.7 赋值运算符

赋值运算符用于给变量赋值。
最常见的赋值运算符,当然就是等号(=)。

// 将 1 赋值给变量 x
var x = 1;

// 将变量 y 的值赋值给变量 x
var 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

2、比较运算符

2.1 概念

比较运算符用于比较两个值的大小,然后返回一个布尔值,表示是否满足指定的条件。

2 > 1   // true

所有比较运算符:
JavaScript 一共提供了8个比较运算符。

  • 大于运算符: >
  • 小于运算符:<
  • 小于或等于运算符: <=
  • 大于或等于运算符: >=
  • 相等运算符: ==
  • 严格相等运算符:===
  • 不相等运算符:!=
  • 严格不相等运算符: !==

2.2 字符串的比较

'cat' > 'dog' // false
'cat' > 'catalog' // false

JavaScript 引擎内部首先比较首字符的 Unicode 码点。如果相等,再比较第二个字符的 Unicode 码点,以此类推。

'cat' > 'Cat' // true'

上面代码中,小写的c的 Unicode 码点(99)大于大写的C的 Unicode 码点(67),所以返回true。

2.3 非字符串的比较

5 > '4' 		 // true
// 等同于 5 > Number('4')
// 即 5 > 4

true > false	 // true
// 等同于 Number(true) > Number(false)
// 即 1 > 0

2 > true 		 // true
// 等同于 2 > Number(true)
// 即 2 > 1

上面代码中,字符串和布尔值都会先转成数值,再进行比较。

这里需要注意与NaN的比较。任何值(包括NaN本身)与NaN比较,返回的都是false。

1 > NaN 		// false
1 <= NaN 		// false
'1' > NaN 		// false
'1' <= NaN 		// false
NaN > NaN	    // false
NaN <= NaN      // false

如果运算子是对象,会转为原始类型的值,再进行比较。

对象转换成原始类型的值,算法是先调用valueOf方法;如果返回的还是对象,再接着调用toString方法。

var x = [2];
x > '11'     // true
// 等同于 [2].valueOf().toString() > '11'
// 即 '2' > '11'

x.valueOf = function () { return '1' };
x > '11'     // false
// 等同于 [2].valueOf() > '11'
// 即 '1' > '11'

两个对象之间的比较也是如此。

[2] > [1]		 // true
// 等同于 [2].valueOf().toString() > [1].valueOf().toString()
// 即 '2' > '1'

[2] > [11] 		 // true
// 等同于 [2].valueOf().toString() > [11].valueOf().toString()
// 即 '2' > '11'

{ x: 2 } >= { x: 1 }    // true
// 等同于 { x: 2 }.valueOf().toString() >= { x: 1 }.valueOf().toString()
// 即 '[object Object]' >= '[object Object]'

2.4 严格相等运算符

JavaScript 提供两种相等运算符:== 和 ===。

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

  • 如果两个值的类型不同,直接返回false。
1 === "1" // false
true === "true" // false

上面代码比较数值的1与字符串的“1”、布尔值的true与字符串"true",因为类型不同,结果都是false。

  • 同一类的原始类型值

同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false。需要注意的是,NaN与任何值都不相等(包括自身)。另外,正0等于负0。

NaN === NaN    // false
+0 === -0      // true
  • 复合类型值

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

{} === {} 		// false
[] === [] 		// false
(function () {} === function () {}) 	// false

上面代码分别比较两个空对象、两个空数组、两个空函数,结果都是不相等。原因是对于复合类型的值,严格相等运算比较的是,它们是否引用同一个内存地址,而运算符两边的空对象、空数组、空函数的值,都存放在不同的内存地址,结果当然是false。

如果两个变量引用同一个对象,则它们相等。

var v1 = {};
var v2 = v1;
v1 === v2    // true

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

var obj1 = {};
var obj2 = {};

obj1 > obj2 	// false
obj1 < obj2     // false
obj1 === obj2   // false

上面的三个比较,前两个比较的是值,最后一个比较的是地址,所以都返回false。

  • undefined 和 null与自身严格相等。
undefined === undefined    // true
null === null      // true

由于变量声明后默认值是undefined,因此两个只声明未赋值的变量是相等的。

var v1;
var v2;

v1 === v2   // true

2.5 严格不相等运算符

严格相等运算符有一个对应的“严格不相等运算符”(!==),它的算法就是先求严格相等运算符的结果,然后返回相反值。

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

上面代码中,感叹号!是求出后面表达式的相反值。

2.6 相等运算符

相等运算符用来比较相同类型的数据时,与严格相等运算符完全一样。

1 == 1.0
// 等同于
1 === 1.0

比较不同类型的数据时,相等运算符会先将数据进行类型转换,然后再用严格相等运算符比较。下面分成四种情况,讨论不同类型的值互相比较的规则。

  • 原始类型值

原始类型的值会转换成数值再进行比较。

1 == true // true
// 等同于 1 === Number(true)

0 == false // true
// 等同于 0 === Number(false)

2 == true // false
// 等同于 2 === Number(true)

2 == false // false
// 等同于 2 === Number(false)

'true' == true // false
// 等同于 Number('true') === Number(true)
// 等同于 NaN === 1

'' == 0 // true
// 等同于 Number('') === 0
// 等同于 0 === 0

'' == false  // true
// 等同于 Number('') === Number(false)
// 等同于 0 === 0

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

'\n  123  \t' == 123 // true
// 因为字符串转为数字时,省略前置和后置的空格

上面代码将字符串和布尔值都转为数值,然后再进行比较。

  • 对象与原始类型值比较

对象(这里指广义的对象,包括数组和函数)与原始类型的值比较时,对象转换成原始类型的值,再进行比较。

// 对象与数值比较时,对象转为数值
[1] == 1 	// true
// 等同于 Number([1]) == 1

// 对象与字符串比较时,对象转为字符串
[1] == '1' 	// true
// 等同于 String([1]) == '1'
[1, 2] == '1,2' 	// true
// 等同于 String([1, 2]) == '1,2'

// 对象与布尔值比较时,两边都转为数值
[1] == true 	// true
// 等同于 Number([1]) == Number(true)
[2] == true 	// false
// 等同于 Number([2]) == Number(true)

上面代码中,数组[1]与数值进行比较,会先转成数值,再进行比较;与字符串进行比较,会先转成字符串,再进行比较;与布尔值进行比较,对象和布尔值都会先转成数值,再进行比较。

  • undefined和null与其他类型的值比较时,结果都为false,它们互相比较时结果为true。
false == null 		// false
false == undefined  // false

0 == null		    // false
0 == undefined      // false

undefined == null   // true

2.7 不相等运算符

相等运算符有一个对应的“不相等运算符”(!=),它的算法就是先求相等运算符的结果,然后返回相反值。

1 != '1' // false

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

3、布尔运算符

3.1 概念

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

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

3.2 取反运算符(!)

取反运算符是一个感叹号,用于将布尔值变为相反值,即true变成false,false变成true。

!true 		// false
!false 		// true

对于非布尔值,取反运算符会将其转为布尔值。可以这样记忆,以下六个值取反后为true,其他值都为false。

  • undefined
  • null
  • false
  • 0
  • NaN
  • 空字符串(’’)
!undefined // true
!null // true
!0 // true
!NaN // true
!"" // true

!54 // false
!'hello' // false
![] // false
!{} // false

上面代码中,不管什么类型的值,经过取反运算后,都变成了布尔值。

3.3 且(与)运算符(&&)

它的运算规则是:两个变量参与&&运算时,只有当两个变量均为true时,运算结果才为true,否则结果为false。

3.4 或运算符(||)

它的运算规则是:两个变量参与||运算时,当两个变量有一个为true时,结果即为true,只有当两个变量均为false时结果为false。

3.5 三元条件运算符(?:)

三元条件运算符由问号(?)和冒号(:)组成,分隔三个表达式。它是 JavaScript 语言唯一一个需要三个运算子的运算符。如果第一个表达式的布尔值为true,则返回第二个表达式的值,否则返回第三个表达式的值。

't' ? 'hello' : 'world'    // "hello"
0 ? 'hello' : 'world'      // "world"

上面代码的t和0的布尔值分别为true和false,所以分别返回第二个和第三个表达式的值。

通常来说,三元条件表达式与if…else语句具有同样表达效果,前者可以表达的,后者也能表达。但是两者具有一个重大差别,if…else是语句,没有返回值;三元条件表达式是表达式,具有返回值。所以,在需要返回值的场合,只能使用三元条件表达式,而不能使用if…else。

上一节:JavaScript 的数组方法大全
下一节:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值