运算符
数学运算符的正统,number和number的数学运算,结果是number。出于面试的考虑,有一些奇奇怪怪的数学运算:
数学运算中:只有纯字符串、布尔值、null能够进行隐式转换。
//隐式转换:就是没有写parseInt()、parseFloat()也能自动帮你转换类型
console.log(2 + "4"); //24
console.log(26 - "2"); //24
console.log(3 * "8"); //24
console.log("3" * "8"); //24
console.log("48" / "2"); //24
console.log("24" % 25); //24
console.log(3 * null); // 0 隐式转换时null被转换为0
console.log(3 * false); // 0 隐式转换时false被转换为0
console.log(3 * true); // 3 隐式转换时true被转换为1
console.log(3 + true); // 4 隐式转换时true被转换为1
console.log(3 + false); // 3 隐式转换时false被转换为0
console.log(3 + null); // 3 隐式转换时null被转换为0
console.log(3 - false); // 3 隐式转换时false被转换为0
console.log(3 - null); // 3 隐式转换时null被转换为0
console.log(3 - ""); // 3 隐式转换时""被转换为0
不纯的字符串和undefined是不能进行隐式转换,结构都是NaN:
console.log(3 * "8天"); //NaN 数学中,不纯的字符串没法隐式转换
console.log(3 * undefined); //NaN 数学中,undefined没法隐式转换
console.log(3 + undefined); //NaN 数学中,undefined没法隐式转换
console.log(3 - undefined); //NaN 数学中,undefined没法隐式转换
console.log(3 / undefined); //NaN 数学中,undefined没法隐式转换
加法比较特殊,因为“+”号同时是加法和拼接字符串的符号,所以加法在面对字符串的时候没有隐式转换。
console.log(2 + "4"); //24 |
总结:
无论哪种运算,只要出现了undefined参与运算,结果都是NaN。
然后字符串"8"、false、true、null都能进行隐式转换。
加号比较特殊,面对字符串"8"没有隐式转换的
特殊值数值的计算:NaN、Infinity参与的运算。
Infinity参与的运算:
console.log(Infinity + 1000); //Infinity
console.log(Infinity - 1000); //Infinity
console.log(Infinity * 1000); //Infinity
console.log(Infinity / 1000); //Infinity
console.log(Infinity + Infinity); //Infinity
console.log(Infinity * Infinity); //Infinity
console.log(Infinity - Infinity); //NaN
console.log(Infinity / Infinity); //NaN
console.log(9 / 0); //Infinity
console.log(0 / 0); //NaN
NaN参与运算:得到结果都是NaN
console.log(NaN + 2);//NaN
console.log(NaN - 2);//NaN
console.log(NaN * 2);//NaN
console.log(NaN / 2);//NaN
console.log(NaN % 2);//NaN
特殊值的数学运算,防止被大公司面试阴,要过一下脑。不过数学运算的特殊值,没有任何的实战价值,建议没必要刻意记忆,留着脑容量记更有用。
一.比较运算符
比较运算符介绍:
比较运算符(关系运算符)的正统,number和number的数学运算,比较它的操作数会返回一个Boolean布尔类型的值。要么是true(真),要么是false(假)
> 大于 < 小于 >= 大于或等于 <= 小于或等于 == 相等,判断值相等,不会判断数据类型 ====全等于,除了判断数值是否相等,还要判断数据类型是否相等 != 不等于,取反,永远和相等判断相反 !== 不全等,取反,永远与全等于判断相反 |
1.1正常情况下:数学和数字进行比较
console.log(5 > 6); //false console.log(5 < 6); //true console.log(5 <= 6); //true console.log(5 >= 6); //false console.log(5 == 5); //true console.log(5 === 5);//true console.log(5 != 5); //false console.log(5 !== 5);//false |
==叫做"相等判断",不会判断数据类型,它会进行隐式转换,尽可能得到true的答案:
console.log(5 == "5"); //true |
===叫做"全等于",会比较数值是否相等,还会判断数据类型是否相等:
console.log(5 === "5"); //false |
!=是==的反面,如果==运算是true,那么!=是false
!==是===的反面,如果===运算是true,那么!==是false
console.log(5 != "5"); //false,脑子要反着想,5 == "5"结果是true,取反后是false console.log(5 !== "5"); //true,脑子要反着想,5 === "5"结果是false,取反后是true |
正统的讲完了,number和number进行比较运算,结果都是Boolean。
1.2不正统的比较运算:
1、string和string也能进行比较运算,比较的是字符编码顺序(Unicode)。
字符编码顺序:0~9、A~Z、a~z,顺序越往后越大。
比较多个字符串:从左往右,一个一个的比较,直到比较出大小,就终止比较。
console.log("a" < "b"); //true
console.log("A" < "B"); //true
console.log("A" < "a"); //true 大写字母在字符集中是在小写字母前面
console.log("1" < "A"); //true 数字在字母的前面
console.log("blank" < "blue"); //true 一位一位比较,直到比出大小,就结束比较,后面的忽略。
console.log("23" < "3"); //true,因为String和String比的不是数字,而是字符编码顺序
2、与数字进行比较运算时,纯数字字符串会被转为数字,null转换0,false转换0,true转换1
null不能进行和0相等判断。
console.log(null < 0.0001); //true
console.log(null > -0.0001); //true
console.log(null >= 0); //null转化为number,为0>=0,所以结果为true
console.log(null <= 0); //null转化为number,为0<=0,所以结果为true
console.log(null > 0); //null转化为number,为0,所以0>0结果为false。
console.log(null == 0);//null在==判断时,不进行转型,所以null和0为不同类型,结果为false。
console.log(false == 0); //true
console.log(true == 1); //true
3、String和number比,string会被隐式转换为number
非正常情况:数字与其他数据比较,其他数据之间进行转换(忽略字符串与字符串比较)
"123" → 123 、true → 1 、 false → 0 、undefined → NaN 、"hello" → NaN、"" → 0 |
举例:
console.log(1 < ""); //false
console.log(0 == ""); //true
console.log(0 == "hello"); //false
console.log(0 == undefined); //false
console.log(1 < "2"); //true
console.log(0 === ""); //false
console.log(1 == true); //true
console.log(0 == false); //true
console.log(0 == false); //true
4、特殊值参与比较:NaN、Infinity
NaN参与:NaN不等于自己,也不全等于自己。
console.log(NaN == NaN); //false
console.log(NaN === NaN); //false
console.log(NaN != NaN); //true
console.log(NaN !== NaN); //true
console.log(NaN < 0); //false
console.log(NaN >= 0); //false
console.log(NaN != 0); //true
Infinity :
console.log(Infinity > 100); //true
console.log(Infinity >= 100); //true
console.log(Infinity < 100); //false
console.log(Infinity <= 100); //false
console.log(Infinity == 100); //false
console.log(Infinity != 100); //true
Infinity与自身比较:
console.log(Infinity > Infinity); //false
console.log(Infinity >= Infinity); //true
console.log(Infinity < Infinity); //false
console.log(Infinity <= Infinity); //true
console.log(Infinity == Infinity); //true
console.log(Infinity === Infinity);//true
console.log(Infinity != Infinity); //false
console.log(Infinity !== Infinity);//false
需要注意的是,我们已经了解一些不正统的运算,所以不要出洋相,不能连续使用比较运算符。
比如像验证3大于2,2大于1
3 > 2 > 1; //false |
解:原式 (3>2)= true > 1 = false。(因为true被转为1来与1进行比较)
也就是说,不能连续使用比较运算符,一旦使用了连续的,实际上是从左到右计算,所以就有上一步的布尔类型值参与下一步的运算。
二.逻辑运算符
逻辑运算符常用于布尔类型值之间,当操作数都是布尔值的时候,返回值也是布尔值。
&& 逻辑“与”运算符,交集,两个条件都成立才为真 || 逻辑“或”运算符,并集,只要其中一个成立就为真 ! 逻辑“非”运算符 |
2.1逻辑“与”&& 运算符
正统来说,参与逻辑运算的都是Boolean和Boolean类型,得到的结果也是Boolean类型值。
按照真值表来定: &&逻辑与(且)
a && b |
||
a |
b |
结果 |
真 |
真 |
真 |
真 |
假 |
假 |
假 |
真 |
假 |
假 |
假 |
假 |
结论:“都真才真”,“有假就假”。
命题1:“地球是圆的” 真的 命题2:“习大大是男的” 真的 命题1 && 命题2 = 真 |
命题1:“1+1=2” 真的 命题2:“地球是方的” 假的 命题1 && 命题2 = 假 |
逻辑运算符“与”
console.log(true && true); //true
console.log(true && false); //false
console.log(false && true); //false
console.log(false && false); //false
2.2逻辑“或”|| 运算符
按照真值表来定: ||逻辑“或”
a || b |
||
a |
b |
结果 |
真 |
真 |
真 |
真 |
假 |
真 |
假 |
真 |
真 |
假 |
假 |
假 |
结论:“有真就真”,“都假就假”。
命题1:“地球是圆的” 真的 命题2:“习大大是男的” 真的 命题1 || 命题2 = 真 |
命题1:“1+1=2” 真的 命题2:“地球是方的” 假的 命题1 || 命题2 = 真 |
2.3逻辑“非”!
!就是逻辑“非”,相反的,非真即假,非假即真。
console.log(!true); //false console.log(!false); //true console.log(!!!!!false); //true |
2.4 逻辑运算符-短路语法
短路语法就是将“逻辑与”、“逻辑或”模拟成电路短路的效果。
非正常情况:布尔类型的值或其他类型的值进行混合逻辑运算,运算过程中其他的数据类型会隐式转换为布尔类型的值,运算完之后返回值不一定是布尔值,而是对应的位置的某个具体值。
隐式转换为false有:null、0、NaN、空字符串("")、undefined
隐式转换为true有:除了以上5种,全是真。
2.4.1逻辑“&&”的短路语法
电流先通过a:
如果a为真,能走到b,不论b为真还是假,直接输出b的结果。
如果a为假,电流不通,直接留在a,不管b是什么,直接把a作为结果输出。
也就是说,本质上计算机进行a && b运算时,不是在进行逻辑分析,要么输出a,要么输出b。如果a是假的,直接输出a;如果a是真的,直接输出b。
-----短路语法,要么被a短路,要么被b短路。
console.log(false && 8); //false,且运算a已经是false,直接输出false
console.log(true && 8); //8,且运算a已经是true,电流通了,可以走到b,将b作为结果输出
console.log(null && 8); //null 且运算a已经是false,直接输出a的结果
console.log(12 && 13); //13 且运算a已经是true,电流通了,可以走到b,将b作为结果输出
console.log(true && NaN); //NaN
console.log(undefined && 哈哈); //undefined
console.log("哈哈" && undefined); //undefined
console.log("" && undefined); // ""
//console.log(哈哈 && undefined); //报错
2.4.2逻辑“||”的短路语法
总结:
如果a为真,直接得到a结果
如果a为假,直接得到b结果(换线路走b,不论b真假)
console.log(false || null); //null
console.log(true || null); //true
console.log(123 || "哈哈"); //123
console.log(0 || 18); //18
console.log(18|| 0); //18
console.log(undefined || NaN);//NaN
运算顺序:非(!)、与(&&)、或(||)
true || false && !true || false |
原式:= true || false && !true || false
= true || false && false || false
= true || false || false
= true || false
= true
88 || 99 && 66 || 55 |
原式:= 88 || 99 && 66 || 55
= 88 || 66 || 55
= 88 || 55
= 88
undefined && ("3" != 3) || NaN && null |
原式:= undefined && false || NaN && null
= undefined || NaN && null
= undefined || NaN
= NaN
综合运算顺序题目:非(!)、与(&&)、或(||)
null && true || undefined && 123 || !"hello" && fasle |
原式:= null && true || undefined && 123 || !"hello" && fasle
= null && true || undefined && 123 || false && fasle
= null || undefined && 123 || false && fasle
= null || undefined || false && fasle
= null || undefined || false
= undefined || false
= false
//短路语法案例:以后经常会遇见这种套路
var age = parseInt(prompt("请输入年龄"));
(age >= 18) && alert("已经成年,可以考驾照");
(age < 18) && alert("未成年,可以做违法的事情");
总结短路语法:
当它们用于非布尔值的时候,返回值可能是非布尔值,其实这种运算很简单,就两句话:
a && b 如果a为真,执行b a || b 如果a为真,执行a |
不推荐背诵规律:自己去推导过程(短路语法)。
三.赋值运算符
赋值运算符必须有变量参与。
= 简单的赋值,不需要运算 += 加等于 -= 减等于 /= 除等于 *= 乘等于 %= 取余等于 ++ 每次在原基础上加1 -- 每次在原基础上减1 |
var a = 1;
a += 2; //这行语句等价于a = a + 2;
console.log(a); var b = 6;
b /= 3; //这行语句等价于b = b / 3;
console.log(b); //2 var c = 1;
c *= 2; //这行语句等价于c = c * 2;
console.log(c); //2 var d = 100;
d -= 50; //这行语句等价于d = d - 50;
console.log(d); //50 var e = 100;
e %= 10; //这行语句等价于e = e % 10;
console.log(e); //0 var f = "大";
f += "家"; //这行语句等价于f = f + "家";
f += "好";
console.log(f);
++运算符:
++可以与输出语句写在一起,++写在变量前和变量后不是一个意思。
a++ : 先用a的原值,然后a再加1 ++a :先给a加1,然后再给a赋新值 |
var g = 10; console.log(g++); //10 先引用原值,再加1 console.log(g); //11,用了g++后的值 |
等价于:
var f = 10; console.log(f); //先输出f f++; //然后f加1 |
var h = 10; console.log(++h);//11,这是自加1,再输出 |
++有花式玩法,仅面试有用:
var z = 8; console.log(4 + z++); //12,先用原来的z值,4 + 8,输出12然后再加1 |
var y = 9; console.log(++y % 5); //0,先把y加1,然后使用i,10 % 5 = 0 |
综合案例:
var a = 10;
var b = 20;
var c = 30;
var sum = a++ + ++b + c++ + ++a + ++c;
// 10 + 21 + 30 + 12 + 32 = 105
console.log(a)
console.log(b)
console.log(c)
console.log(sum)
综合运算顺序
运算符的计算顺序:
贴身(! ++ --) → 数学运算符 → 比较运算符 → 逻辑运算符 → 赋值运算符 |
var a = 3 < 6 && 7 < 14; |
原式 = true && true
= true
var b = 1 + 2 < 3 + 3 && 3 + 4 < 2 * 7 |
原式:= 1 + 2 < 3 + 3 && 3 + 4 < 2 * 7
= 3 < 6 && 7 < 14
= true && true
= true
var c = false + true && 13; |
原式: = 0 + 1 && 13
= 1 && 13
= 13
var a = 15; false + a++ + true > 8 && 13 || 6 |
原式 = false + 15 + true > 8 && 13 || 6
= 16 > 8 && 13 || 6
= true && 13 || 6
= 13 || 6
= 13
四.if条件分支语句
流程控制语句:可以利用一些结构打断程序,或者挑选分支执行,或者循环执行某一段语句。
包含:条件分支语句、循环语句
条件分支语句:if语句、switch语句、三元运算符
4.1 if语句
if(条件表达式){ 条件表达式成立执行 } |
if(条件表达式){ 条件表达式成立执行 }else{ 条件表达式不成立执行 } |
if 如果
else 否则
条件表达式,可以是任意内容,表达式会强制得到一个布尔值,只要表达式在参与程序之前都会计算出一个结果。根据布尔类型结果的真假,选取分支。
if语句只会选一个分支进行执行,另一个不执行:
var num = 80;
if(num >= 60){
alert("及格");
}else{
alert("不及格");
}
if(8 > 10){
alert("条件成立");
}else{
alert("条件不成立");
}
//用户输入密码
var pwd = parseInt(prompt("请输入您的密码"));
//返回用户信息,是否正确
if(pwd == 123456){
alert("密码正确");
}else{
alert("密码错误");
}
如果结构体中只有单行语句,可以省略大括号:
var pwd = parseInt(prompt("请输入您的密码"));
//返回用户信息,是否正确
if(pwd == 123456)
alert("密码正确");
else
alert("密码错误");
alert("请再次输入"); //超出else的控制范围,所以会执行
4.2多条件if语句
根据多个条件可以选择不同的支进行执行。
语法:if...else if...else if
如果...否则如果...否则如果..否则
if(条件表达式1){
条件表达式1成立,执行的结构体1
}else if(条件表达式2){
条件1为假,条件2为真,执行的结构体2
}else if(条件表达式3){
条件1、2为假,条件3为真,执行的结构体3
}else{
以上的条件都为假,执行这里的结构体
}
【注意】:
1、多条件if语句可以有多个else if,但是只能有一个else。else也可以省略。前面的条件有满足的直接选择分支,如果都不满足,就直接跳出if语句执行后面其他的代码。
var s = parseInt(prompt("请输入成绩"));
if(s >= 90){
alert("优秀!棒棒哒");
}else if(s >= 80){
alert("良好!继续保持");
}else if(s >= 70){
alert("中等!继续努力");
}else if(s >= 60){
alert("及格");
}
2、跳楼现象:if语句选中了某个复合条件的分支,执行完结构体后,不管执行结果如何,都会直接跳出if语句。不再往下继续判断。
var a = 3;
if(a < 5){
a += 5; //满足第一个条件,执行完后,不会再继续往下判断,直接跳楼
}else if(a == 8){
a + 3;
}else if(a % 3 == 2){
a += 5;
}else{
a += 12;
}
console.log(a); //8
if语句不管是普通的还是多分支的,都只会选一个分支,然后跳楼,殊途同归执行if后面的语句。
4.3 if语句嵌套
if语句的结构体可以再嵌套if语句
如果想执行内部的if语句的某个分支,除了要满足自身条件之外,还要满足外层条件。
var sex = prompt("请输入性别");
var age = parseInt(prompt("请输入年龄"));
if(sex == "男" && age >= 22){
alert("可以结婚了");
}else if(sex == "男" && age < 22){
alert("你还小,先去网吧转转!");
}else if(sex == "女" && age >= 20){
alert("菇凉,可以嫁人了");
}else if(sex == "女" && age < 20){
alert("不能结婚,不要着急");
}else{
alert("你是人妖吗?")
}
if(sex == "男"){
//只要进来执行,性别肯定是男的
//判断年龄是否大于或等于22
if(age >= 22){
alert("恭喜,小鲜肉可以结婚了");
}else{
alert("不能结婚,再坚持一会!")
}
}else if(sex == "女"){
if(age >= 20){
alert("恭喜,小姐姐可以结婚了");
}else{
alert("小萝莉不能结婚,再坚持一会!")
}
}else{
//进入这个条件分支语句,说明不是男也不是女,是人妖
alert("人妖走开!");
}