JavaScript中的常用操作符和语句
操作符
ECMA-262 描述了一组可用于操作数据值的操作符,包括数据操作符(加、减、乘、除、),位操作符、关系操作符、相等操作符,可用于各种值,但在应用给对象时会调用valueOf()和 / 或 toString()方法来取的可以计算得值。
一元操作符
只操作一个值得叫做一元操作符
- 递增( ++ ) / 递减( - - )操作符
- 前缀 ++i / --i : 变量的值会在语句被求值之前改变
- 后缀 i++ / i–: 变量的值会在语句被求值之后改变
- 这四个操作符可以用于任何值(数字、字符串、布尔值、对象…),操作规则如下:
- 对于字符串,首先变量类型会变成数值,然后如果是有效数值形式,则转为数值在应用,反之则将变量值设置为NaN
- 对于布尔值,首先变量类型会变成数值, 然后 false -> 0,true -> 1
- 对于浮点值,加1或者减1
- 对于对象,首先变量类型会变成数值,调用valueOf()方法取值,对得到的值按上述规则套用,如果是NaN,则调用toString()取值,在此套用上述规则。
- 一元加和减(+ / -)
- 一元加放在变量前头,对数值没有任何影响,对于非数值,执行Number()函数类型转换规则。
- 一元减放在变量头,对于数值,主要把数值变成负值(取反);如果遇到非数值,则先遵循一元加的转换规则转换成数值,然后再取赋值
布尔操作符
- 逻辑非( ! ):首先将操作数值转换为布尔值,然后再取反(只有0 , “”, false, null, undefined转换为布尔值时是false)
- 也可以使用!!,把任意值转换为布尔值,结果等同于Boolean()
- 操作符返回的始终是布尔值
- 逻辑与( && )
- 如果第一个操作数是对象,则返回第二个操作数
- 如果第二个操作数是对象,则只有第一个操作数是对象(或者求值为true)时才返回该对象
- 如果有一个操作数是 null / NaN / undefined,则将null / NaN / undefined返回
- 如果第一个操作符决定了结果,则永远不会对第二个操作符求值
- 如果第一个值是false,那么第二个操作符不论是什么值,结果都是false
- 逻辑或( || ):返回值不一定是布尔值
- 第一个操作数如果是对象(或两个操作数都是对象),则返回第一个操作数;如果第一个操作数为false,则返回第二个操作数
- 如果两个操作数都是null / NaN / undefined,则将null / NaN / undefined返回
- 第一个操作数为true,第二个操作数不被计算。(同逻辑与都具有短路操作)
数值操作符
- 加性操作符
- 加法( + ):求两个数的和
- 两个操作数都是数值,执行加法操作
- -Infinity +(-Infinity)= -Infinity
- Infinity + Infinity = Infinity
- -Infinity + Infinity = NaN
- -0 + (-0) = -0 、+0 + (+0) = +0、-0 + 0 = +0
- 两个操作数都是数值,执行加法操作
- ‘
+
’ 字符串拼接- 两个都是字符串,则直接拼接。
- 如果有一边是字符串,则将另一个操作数转换为字符串,然后拼接到一起。
- 如果有一边是对象 / 布尔值,则会按照
对象[Symbol.toPrimitive]
->对象['value']()
->对象.toString()
这三步走,以获取字符串,然后再应用上面字符串规则;{} + 10
=> 10 , 此操作中,{}
在加号左侧,会被当做一个代码块。有且仅有这一种情况var = {} + 10 =>"[object,object]10"
10 + {}
=>"10[object,object]"
- 目前只有Date具备
[Symbol.toPrimitive]
- 非标准对象【原始值对应的对象类型实例】,还有Date 的
valueof
获取的值才是原始值。
- 对于null和undefined,则调用String()方法函数,分别来获取“null”和“undefined”。
- 减法( - ):大致规则同加法运算符
- -Infinity - Infinity = NaN
- -Infinity - (-Infinity ) = NaN
- -Infinity - Infinity = -Infinity
- Infinity - (-Infinity )= Infinity
- -0 - (-0) = -0 、+0 - (+0) = +0、-0 + 0 = -0
- 对于字符串、布尔值、null和undefined,先后台使用Number()转换为数值,
- 对于对象则调用valueOf()取得表示它他的数值 /,或者调用它的toString()方法,再将得到的字符串转换为数值
- 加法( + ):求两个数的和
- 乘性操作符
- 乘法(*):计算两个数的乘积
- 如果有任意操作数是NaN,则返回NaN
- 如果操作数都是数值,则直接计算乘积,否则后台调用Number()转为数值,在应用上述规则
- 除法( / ),求第一个操作数除以第二个操作数的商,
- 规则同乘法操作符一样
- 如果 0 除以 0 ,则则返回NaN
- 非0的有限值除以0,则根据第一个操作数的符号返回(+ / -)Infinity
- Infinity 除以任何数值,则根据第二个操作数的符号返回(+ / -)Infinity
- 取模( % ),求第一个操作数除以第二个操作数的余数
- 同其他乘性操作符规则一样
- Infinity 除以任何数值,返回NaN
- 任何数除以0,返回NaN
- 第一个数是有限值,第二个数是无限值,返回第一个数
- 0 除以任何非0数,返回0
- 乘法(*):计算两个数的乘积
- 指数操作符(**):Math.pow()(ES7新增)
- Math.pow(3,2) === Math.pow(3 **2) => 9
- **= 指数赋值操作符 :let a =3; a** = 2; a => 9
关系操作符
- 关系操作符执行比较两个值的操作
- 包括大于( > ),小于( < ),大于等于( >= ),小于等于( <= )
- 规则同数学规则,返回值均为布尔值
- 应用到不同的数据类型时也会发生类型转换
- 两个操作数都是数值,直接比较 ;都是字符串比较对应的字符编码
- 如果有任一操作数是数值,则将另一操作数转换为数值,比较数值
- 如果有任一操作数是布尔值,则将其转为数值,再进相比较
- 有任一操作数是对象,则调用其valueOf()或者toString()方法,在按照上述规则比较
- null和undefined相等,不能转换其他类型值再比较
相等操作符
判断两个变量是否相等
- 判断之前执行转换
- 等于(==):两个操作数相等,返回true
- 不等于(!= ):两个操作数不相等,返回true
- 这两个操作符都会先进行类型转换(强类型转换),再进相比较
- 对于任 一操作数是布尔值和字符串,先转换为数值再比较
- 任一操作数是对象时,则调用其valueOf()或者toString()方法,在按照上述规则比较
- 任意操作数是NaN,==直接返回false,!=直接返回true,(NaN不等于任何数,包括他自己)
- 两个操作数都是对象,若为同一个对象则 == 返回true,,否则两个不相等
- 判断之前不执行转换
- 全等(===)
- 不全等(!==)
- 比较规则同等与不等与相似,但是不进行类型转换直接比较
- null和undefined不全等
条件操作符
- 语法:variable = boolean_expression ? true_value : false_value ;
- 根据条件表达式boolean_expression 的值决定将哪一个值赋值给变量variable
- 简单的IF/ELSE的特殊处理方式
赋值操作符
- 简单的的赋值用等号(=)表示,将右边的值赋值给左边的变量
- 复合赋值使用乘性、加性或者位操作符后跟等号表示,仅仅是写法简单,不提升性能
- 乘后赋值(*=)
- 除后赋值(/=)
- 取模后赋值(%=)
- 加后赋值(+=)
- 减后赋值(-=)
- …
逗号操作符
- 用来在一条语句中执行多个操作
- 赋值时使用逗号操作符分割值,最终会返回表达式的最后一个。
* &(和号)、| (管道符)、^(脱字符)
语句
语句(流程控制语句)通常使用一到多个关键字完成既定任务,可简单,可复杂。
if语句
- 语法:if(conditin) statement1 else statement2 ;
- conditin 可以是任何表达式,且求值结果不一定是布尔值,
- ECMAScript会自动调用Boolean()函数将这个表达式的值转换为布尔值,true执行statement1 ,false执行statement2
- statement1 和statement2 若是多行代码,需要用花括号({})包裹起来
- 条件操作符(variable = boolean_expression ? true_value : false_value )可以完成简单的if语句
- if(conditin1) {statement1 }else if(conditin2) {statement2 }else{statement3};
switch语句
- switch语句是与if语句紧密相联的流程控制语句,实现一个变量在不同值情况下的不同操作
- 每一种 CASE 情况结束后最好都加上BREAK。
- 不加BREAK,当前条件成立执行完成以后,后面的条件不论是否是否成立都要执行,直到遇到break为止。
- 不加break可以实现变量在某些值的情况下做相同的事情(当变量在某几值之下要做相同的事情,不加break可以更好地实现效果,时代码更简洁。)
- default 等价于 else,以上都不成立做的事情。
- 每一种case情况的比较,用的都是“===”(绝对相等),不转换,直接比较。
let a = 10;
if(a === 0){
console.log("哈哈");
}else if(a === 5){
console.log("呵呵");
}else if(a === 10){
console.log("嘿嘿");
}else{
console.log("嘻嘻");
}
//switch case 重写
switch(a){
case 1:
console.log("哈哈");
break;
case 5:
console.log("呵呵");
break;
case 10:
console.log("嘿嘿");
break;
default:
console.log("嘻嘻");
};
//---------------------
switch(a){
//当a等于1或者5的时候都执行者行代码,当变量在某几值之下要做相同的事情,不加break可以更好地实现效果,时代码更简洁。
case 1:
case 5:
console.log("呵呵");
break;
case 10:
console.log("嘿嘿");
break;
default:
console.log("嘻嘻");
};
//---------------------------------------------------
let a = "5";
switch(a){
case 1:
console.log("哈哈");
break;
case 5: // 此处"5" case 5 => FALSE =》 每一种case情况的比较,用的都是“===”,绝对相等,不转换,直接比较。
console.log("呵呵");
break;
default:
console.log("嘻嘻");
};
//=> "嘻嘻"
a = "5";
if(a == 0){
console.log("哈哈");
}else if(a == 5){
console.log("呵呵");
}else{
console.log("嘻嘻");
};
//=> "呵呵"
== VS ===
- ==:相等(如果两边的数据值类型不同,默认先转换为相同的类型,然后比较)“5” == 5 =>TRUE
- ===:绝对相等(如果数据类型不一样,肯定不相等)“5” === 5 => FALSE
- 所以在实际项目中为了保证业务的严谨性,推荐使用 ===。
do-while语句
- 后测试循环语句,循环体中代码执行后才会对退出条件进行求值,循环体中的代码至少执行一次
- 语法:do{ statement }while( expression )
while语句
- 先测试循环语句,先检测退出条件,再执行循环体内代码,循环体内代码可能一次都不执行
- 语法:while(expression ){}
for 语句
- 先测试循环语句,只不过增加了进入循环之前的初始化代码,和循环执行后要执行的表达式
- 语法:
for ([initialization]; [condition]; [final-expression]) statement
- initialization : 一个表达式 (包含赋值语句) 或者变量声明(循环的初始值)。
- condition :一个条件表达式被用于确定每一次循环是否能被执行(循环执行的条件)。
- statement :每次循环的最后都要执行的表达式(条件成立循环体中的内容)。
- final-expression :只要condition的结果为true就会被执行的语句(当前循环结束执行步长累计操作)。
- 初始化,条件表达式,循环后表达式都不是必须的, 无限循环:
for(;;){ statement }
for(var i = 0; i < 5; i++){
console.log(i); // 0,1,2,3,4
};
console.log(i); //5
for-in语句
- for-in语句是一种严格的迭代语句,用于枚举对象中的非符号键属性
- 语法:for(property in expression){statement}
- 不能保证返回对象属性的顺序
- 如果要迭代的变量是null或者undefined,则不执行循环体
for-of语句
- for-of语句是一种严格的迭代语句,用于遍历可迭代对象的元素
- 语法:for(property of expression){statement}
- 如果尝试迭代变量不支持迭代,for-of语句会抛出错误
标签语句
- 标签语句用于给语句添加标签
- 语法 label:statement
- 标签语句的经典应用场景是嵌套循环
start: for(let i = 0; i < count; i++){
console.log(i);
};
// start是一个标签,可以通过break和continue语句引用
break 和 continue语句
- break和continue语句为执行循环代码提供了更严格的控制手段
- break : 立即退出当前循环,强制执行循环后的下一条语句
- continue : 立即退出当次的循环,但会再次从循环顶部开始执行下一次循环
let num = 0;
for(let i = 1; i < 10; i++){
if(i%5 == 0) break;
num++;
};
console.log(num) //4
//------
let num = 0;
for(let i = 1; i < 10; i++){
if(i%5 == 0) continue;
num++;
};
console.log(num) //8