上次的笔记主要说了一些JavaScript基本信息和基本数据类型,这次我们来说下运算符和表达式。
运算符
运算符也叫操作符,通过运算符可以对一个或多个值进行运算,并获得运算结果。
比如:typeof就是运算符,可以获得一个值的类型。它会将该值的类型以字符串的形式返回。
返回值:number、string、boolean、undefined、object。
var a = 123;
var result = typeof a;
console.log(typeof result);
算数运算符
算术运算符包括:加+
、减-
、乘*
、除/
、求余运算符%
、数值取反运算符-
。
-
当对非Number类型的值进行运算时会将其转换为Number再计算。
- 加法有一种特殊情况,如果两个字符串相加,会进行拼串操作。将两个字符串拼接成一个字符串。任何一个类型与字符串相加,都会现将其转化为字符串,再进行拼串操作。
var a = 123; b = a + ""; console.log(typeof a); console.log(a); console.log(typeof b); console.log(b);
- 我们可以利用这一特点,来将一个任意的数据类型转换为String,我们只需要为任意数据类型加一个空串,即可将其转换为String。这是一种隐式的类型转换,由浏览器自动完成,实际上它也是调用了
String();
。
result = 1 + 2 + "3";//33
result = "1" + 2 + 3;//123
- 任何值与NAN运算结果都是NAN。
- 利用任何值做减法、乘法、除法运算时都会转换为Number这一特性,可以使用值减去0(或者:乘1、除以1)快速吧值转换为数字。原理和
Number();
一样,但是使用起来简单一些。
一元运算符:(+)正号,(-)负号。
- 对于Number类型:正号不会对数字产生任何影响。负号可以对数字进行负号的取反。
- 对于非NUmber类型:会先将其转换为Number类型。可以对一个其他的数据类型转换为Number,原理和
Number();
也一样。
a = "18";//String类型
a = +a;//转换为Number类型
console.log("a = " + a);//"a = 18"
console.log(typeof a);"number"
自增(++)和自减(–)
-
前置递增(++n):先递增,再赋值。
-
前置递减(–n):先递减,再赋值。
-
后置递增(n++):先赋值,再递增。
-
后置递减(n–):先赋值,在递减。
对于a++和++a,都会是原变量的值自增1,不同的是a++和++a的值,a++的值等于自增前的值,++a等于自增后的值。
逻辑运算符
逻辑运算符用于测定变量或值之间的逻辑,JS中为我们提过了三种逻辑运算符:!-->非
,&&-->与
,||-->或
。
给定 x=6 以及 y=3,下表解释了逻辑运算符:
运算符 | 描述 | 例子 |
---|---|---|
&& | and | (x < 10 && y > 1) 为 true |
|| | or | (x == 5 || y == 5) 为 false |
! | not | !(x==y) 为 true |
逻辑与运算:只有两个值同时为true的时候才会返回true,只要有一个值为false就返回false。JS中的与属于短路的与:第一个值为true会检查第二个值,第一个值为false则不会检查第二个值。
逻辑或运算:只要有一个值为true就会返回true。。JS中的或属于短路的或:第一个值为true则不会检查第二个值,第一个值为false则才会检查第二个值。
逻辑非运算:逻辑非运算就是指对一个布尔值进行取反操作。可以为一个任意数据类型取反两次,可以将其转化为布尔型。
-
对于非布尔值,进行与、或运算时,则会先将其转换为布尔值,然后进行运算,并且返回原值。
-
与运算:如果第一个值为true则返回第二个,如果第一个值为false则返回第一个。
true && true
:与运算,如果两个值都为true,则会返回后面的。
false && true
,true && false
,false && flase
:如果两个值中有false则返回靠前的false。
- 或运算:如果第一个值为true,则直接返回第一个值。第一个值为false,则返回第二个值。
简单说来就是与运算找false,或运算找true。
赋值运算符
赋值运算符用于给 JavaScript 变量赋值。
给定 x=10 和 y=5,下面的表格解释了赋值运算符:
算符 | 例子 | 等同于 | 运算结果 |
---|---|---|---|
= | x=y | x=5 | |
+= | x+=y | x=x+y | x=15 |
-= | x-=y | x=x-y | x=5 |
*= | x*=y | x=x*y | x=50 |
/= | x/=y | x=x/y | x=2 |
%= | x%=y | x=x%y | x=0 |
关系运算符
关系运算符在逻辑语句中使用,以测定变量或值是否相等。
x=5,下面的表格解释了比较运算符:
运算符 | 描述 | 比较 | 返回值 |
---|---|---|---|
== | 等于 | x==8 | false |
x==5 | true | ||
=== | 绝对等于(值和类型均相等) | x===“5” | false |
x===5 | true | ||
!= | 不等于 | x!=8 | true |
!== | 不绝对等于(值和类型有一个不相等,或两个都不相等) | x!==“5” | true |
x!==5 | false | ||
> | 大于 | x>8 | false |
< | 小于 | x<8 | true |
>= | 大于或等于 | x>=8 | false |
<= | 小于或等于 | x<=8 | true |
非数值的情况:
console.log(1>true);//false
console.log(1>=true);//true
console.log(1>"0");//true
console.log(10 < "hello")//false
console.log(10 > "hello")//false
console.log(10 <= "hello")//false
console.log("1" < "5");//true
console.log("11" < "5");//true
console.log("11876786556445335897908" < "5");//true
console.log("11876786556445335897908" < +"5");//false
console.log("abc" < "b");//true
console.log("bbc" < "b");//false
- 对于非数值进行比较时,会将其转换为数字然后再比较。
- 任何数值与NAN比较结果都是false。
- 如果符号两侧的值都是字符串时,不会将其转换为数字进行比较,而是分别比较字符串中的Unicode编码。比较字符编码的时候是一位一位进行比较的,,如果前面的相同,则比较下一位。以此类推。比较中文时,没有意义。如果比较两个字符串类型的数字,可能得到不可预期的结果,所以注意,在比较两个字符串型的数字时,一定要转型。
- 当使用
==
进行类型比较时,如果类型不同,则会进行自动类型转换:- 布尔值false转换为0,true转换为1.
- 如果一个操作数是字符串,另一个操作数是数字,则先尝试把字符串转换成数字。
- 如果一个操作数是字符串,另一个操作数是对象,则先尝试把对象转换为字符串。
- 如果一个操作数是数字,另一个操作数是对象,则先尝试把对象转换为数字。
- 如果两个值都是对象,则比较引用地址。如果尹同地址相同,则相等,否则不相等。
- null和undefined值相等,但是它们是不同类型的数据,在相等比较中,null和undefined不允许被转换为其他类型的值。
- NaN不和任何值相等,包括它自己。可以通过
isNaN();
函数来判断一个值是否是NaN,如果是NaN则返回true,否则返回false
- 使用
!=
进行不相等运算。与上面的==
相反。- 不相等也会对类型进行自动的转换。
- 使用
===
来判断两个值是否全等,和相等类似,不同的是,不会做类型转换,如果两个值的类型不同,直接返回false。 - 使用
!==
用来判断两个值是否不全等,和不相等类似,同的是,不会做类型转换,如果两个值的类型不同,直接返回true。
条件运算符
条件运算符是唯一的三元运算符,其语法:b?x:y;
b操作数必须是一个布尔型的表达式,x和y是任意类型。
- 如果操作数b的返回值是true,则执行x操作数,并返回该表达式的值。
- 如果操作数b的返回值是false,则执行y操作数,并返回该表达式的值。
//获取a和b中的最大值
var max = a > b ? a : b;
//再获取a、b、c中的最大值
max = max > c ? max : c;
运算符的优先级
就和数学一样在JS中运算符也有优先级,比如:先乘除后加减。
在JS中有一个运算符优先级的表,在表中月考上优先级越高,优先级越高越优先计算,如果优先级一样,则会从左到右计算。
优先级 | 运算符 | 说明 | 结合性 |
---|---|---|---|
1 | [] 、. 、() | 字段访问、数组索引、函数调用和表达式分组 | 从左向右 |
2 | ++ – -~!delete new typeof void | 一元运算符、返回数据类型、对象创建、未定 义的值 | 从右向左 |
3 | *、/、% | 相乘、相除、求余数 | 从左向右 |
4 | +、- | 相加、相减、字符串串联 | 从左向右 |
5 | <<、>>、>>> | 左位移、右位移、无符号右移 | 从左向右 |
6 | <、<=、>、>=、instanceof | 小于、小于或等于、大于、大于或等于、是否 为特定类的实例 | 从左向右 |
7 | == 、!= 、``=、 !` | 相等、不相等、全等,不全等 | 从左向右 |
8 | & | 按位“与” | 从左向右 |
9 | ^ | 按位“异或” | 从左向右 |
10 | | | 按位“或” | 从左向右 |
11 | && | 短路与(逻辑“与”) | 从左向右 |
12 | || | 短路或(逻辑“或”) | 从左向右 |
13 | ?: | 条件运算符 | 从右向左 |
14 | =、+=、-=、*=、/=、%=、&=、|=、^=、<、<=、>、>=、>>= | 混合赋值运算符 | 从右向左 |
15 | , | 多个计算 | 按优先级计算,然后从右向左 |
但是这个表我们并不需要记忆,如果遇到优先级不清楚,用括号括起来。
表达式
在语法概念中,运算符属于词,表达式属于短语。表达式是由一个或多个运算符、操作数组成的运算式。表达式的功能室执行计算,并返回一个值。
表达式的形式
表达式是一个比较富有弹性的运算单元。简单的表达式就是一个直接量、常量或变量。例如:
1//数值直接量,计算后返回数值1
"string"//字符串直接量,计算后返回字符串"string"
...
它们也是最原始的表达式,一般很少使用。
使用运算符吧一个或多个简单的表达式连接起来,就可以构成复杂的表达式。复杂的表达式还可以嵌套组成更复杂的表达式。但是,不管表达式的形式多么复杂,最后都要求返回一个唯一的值。
表达式的类型
根据功能不同,表达式可以分成很多的类型。
- 定义表达式,如:定义变量、定义函数、
var a = [];
var f = function(){};
- 初始化表达式,与定义表达式和赋值表达式常常混用。
var a = [1,2];
var o = {x:1,y:2};
- 访问表达式。
console.log([1,2][1])//返回2
console.log(({x:1,y:2}).x);//返回1
console.log(({x:1,y:2})["x"]);//返回1
- 调用表达式。
console.log([1,3,2].sort());//返回1,2,3
- 实例化对象表达式。
console.log(new Object());//返回实例对象
根据运算符的类型,表达式还可以分为:算术表达式、关系表达式、逻辑表达式、赋值表达式等。
表达式的运算顺序
-
表达式可以嵌套组成复杂的表达式。JavaScript在解析时,先计算最小单元的表达式,然后把返回值投入到外围表达式中运算,依次逐级上移。
-
表达式严格遵循“从左到右”的顺序执行运算,但是也会受每个运算符的优先级和结合性的影响。同时,为了控制计算,用户可以通过小括号分组提升子表达式的优先级。
表达式的优化
在复杂的表达式中,一些不良的逻辑结构与人的思维方式相悖,会影响代码阅读,这就应该根据人的思维习惯来优化表达式的逻辑结构。简单说,如果我们要用表达式描述年龄大于等于6岁小于等于18岁的人,来应该这样写
if(age >= 6 && age <= 18)
这样更容易理解。