二、运算符
1、概述
运算符(Operators,也翻译为操作符),是发起运算的最简单形式。
数学运算符(Arithmetic operators)
比较运算符(Comparison operators)
逻辑运算符(Logical operators)
赋值运算符(Assignment operators)
按位运算符(Bitwise operators)
条件 (三元) 运算符(Conditional operator)
2、数学运算符
数学运算符: + - * / % ()
运算顺序:先算乘除取余,再算加减,有小括号先算小括号。
js里数学运算没有[]、{},全部用()代替。
正规:数字与数字之间进行数学运算。
非正规:数字与其他类型数据进行运算,其他类型数据之间进行数学运算。
①如果是数字与纯数字字符串字符串之间进行运算。
除了+号之外,其他的运算符,会自动将字符串转成数字。这个过程是私下进行,叫做隐式转换。不需要使用parseInt等方法。
//数字与纯数字字符串,纯数字字符串之间
console.log(12 + "2"); //122
//在纯数字字符串参与运算之前,被隐式转换成数字类型
console.log(12 - "2"); //10
console.log(12 * "2"); //24
console.log(12 / "2"); //6
console.log(12 % "2"); //0
console.log("12" % "2"); //0
②其他类型的数据参与数学运算。
其他类型的数据也会发生饮食转换。
转换为0:空字符串、null、false
转成1:true
转NaN:undefined、非空非纯数字字符串
//其他特殊数据类型参与运算
console.log(23 + true);
console.log(23 - true);
console.log(23 * true);
console.log(23 / true);
console.log(23 % true);
console.log(23 + false);
console.log(23 + null);
console.log(23 - "");
console.log(23 - undefined);
console.log(23 - "hello");
console.log(23 - "12hello");
“”→0 null→0 false→0 true→1 “12helle”→NaN undefined→NaN
③特殊数字参与运算。
特殊值NaN参与的运算都会返回NaN。
//所有NaN参与的运算都返回NaN
console.log(12 + NaN);
console.log(12 - NaN);
console.log(12 * NaN);
console.log(12 / NaN);
console.log(12 % NaN);
Infinity参与的运算,要单独看。
//Infinity参与运算
console.log(23 + Infinity);
console.log(23 - Infinity);
console.log(23 * Infinity);
console.log(23 / Infinity);
console.log(23 % Infinity);
console.log(Infinity % Infinity);
console.log(Infinity + Infinity);
console.log(Infinity - Infinity);
console.log(Infinity * Infinity);
console.log(Infinity / Infinity);
特殊值的数学运算,防止被大公司面试阴,要过一下脑子。不过数学运算的特殊值,真心没有任何实战价值,建议没必要刻意记忆,留着脑容量记更有用的。《高3》P47~P50
总结一下:纯数字字符串、字符串在参与数学运算时,除了加号之外,其他的运算都会隐式转换。
其他数据类型参与任何数学运算都会被隐式转换。
//数字与数字比较
console.log(7 > 8);
console.log(7 < 8);
console.log(7 >= 8);
console.log(7 <= 8);
console.log(7 == 8);
console.log(7 != 8);
console.log(8 === 8);
console.log(8 !== 8);
非常规:数字与其他类型数据进行比较,或者其他数据类型之间进行比较。
①如果数字进行其他比较,其他类型的数据会隐式转换为数字,然后再比较。
纯数字字符串转为对应的数字,空字符串、null、false转0,true转成1.
console.log(1 == "1");
console.log(1 == true);
console.log(1 == false);
console.log(0 == null);
console.log(0 >= null);
console.log(0 <= null);
console.log(0 == "");
相等于和全等于的区别:相等只判断值相等就够了,全等于还要判断数据类型。
//判断全等,除了判断值的大小,还要判断数据类型
console.log(1 === "1");
console.log(1 === true);
//不等于、不全等于,先看等于和全等于,取反
console.log(1 !== "1");
②字符串与字符串进行比较。
不会隐式转换为数字,比较的是Unicode字符编码顺序。
顺序在前面的小于顺序在后面。
字符编码顺序:数字0~9、大写字母A~Z、小写字母a~z。
比较方法:比较的不是字符串的长度,根据字符编码顺序,一个字符一个字符比较,直到比较出大小。
//字符串与字符串进行比较
console.log("12" < "2");
console.log("22" < "2");
console.log("abc" < "banana");
console.log("ball" < "banana");
console.log("ball" < "23");
console.log("ball" < "ABC");
③NaN参与的比较
除了不等于和不全等于,NaN参与的比较运算返回的都是false。
④Infinity自身的比较
特殊情况:
比较:3>2>1;
原因:代码从前往后执行,先计算3>2,得到的是true,再比较时true>1,返回false。
控制台快捷键:
清空控制台:ctrl+L
执行代码:enter
换行:shift+enter
重新输入上一次代码:Ctrl+↑
4、逻辑运算符
逻辑运算符常用于布尔类型值之间; 当操作数都是布尔值时,返回值也是布尔值。
&& 逻辑与运算符 且 交集
|| 逻辑或运算符 并集
! 逻辑非运算符
①逻辑与运算
规律:都真才真,有假就假。
//逻辑与运算
console.log(true && true);
console.log(true && false);
console.log(false && true);
console.log(false && false);
②逻辑或运算
规律:有真就真,都假为假。
//逻辑或运算
console.log(true || true);
console.log(true || false);
console.log(false || true);
console.log(false || false);
③逻辑非运算
规律:非真即假,非假即真。
// 逻辑非运算
console.log(!true);
console.log(!false);
console.log(!!!!!!!!!!!!false);
正常:用于布尔值之间的逻辑运算。
非正常:其他类型的数据参与逻辑运算。将其他的数据隐式转换成布尔类型的值,计算完之后,输出对应位置的数据。不一定是输出布尔值。
隐式转换成true:非0数字、非空字符串。
隐式转换为false:0、NaN、空字符串、undefined、null
//非布尔类型的数据
console.log(35 && null);
console.log(35 || null);
console.log(35 && "nihao");
console.log(35 || "nihao");
当它们用于非布尔值的时候,返回值就可能是非布尔值。其实这种运算非常简单,就两句话:
(逻辑与 && ) 如果a能被转换为false,那么返回a;否则,返回b。
(逻辑或 || ) 如果a能被转换为true,那么返回a;否则,返回b。
要能深层次的理解上面的话,达到不用刻意背,自行能推倒出来的“最高境界”。
花式写法:短路语法。
5、短路语法
将逻辑运算,模拟电路里面的短路。
①逻辑与
比喻成串联电路。
电流通过a到b;
如果a为真,电流可以流通到b,不论b为真还是假,直接抛出b。
如果a为假,电流通不过,停留在a,就直接抛出a。
//逻辑与运算
console.log(23 && "haha");
console.log(23 && null);
console.log(undefined && Infinity);
console.log(NaN && null);
②逻辑或
比喻成并联电路。
电流优先通过a。
如果a为真,电流可以直接通过a,不需要到b,直接抛出a。
如果a为假,电流不能通过a,换到b流过,不管b为真还是假,都抛出b。
//逻辑或运算
console.log(23 || "haha");
console.log(23 || null);
console.log(undefined || Infinity);
console.log(NaN || null);
逻辑运算有顺序:非、与、或。
案例:NaN && null || 23 && !true || !false
原式= NaN && null || 23 && !true || !false
= NaN && null || 23 && false || true
= NaN || false || true
= false || true
= true
答案:
6、赋值运算符
做了两步工作:先运算,后赋值。必须有变量参与运算。
= 等于
+= 加等于 将后面的值加到原来的变量值上,得到的值赋值给变量
-= 减等于
*=
/=
%=
++ 递加 在原来的基础上加1,再赋值
-- 递减 在原来基础上减一,在赋值
//带等号的赋值运算符
var a = 1;
//加等于
a += 2; // a = a + 2;
console.log(a); //3
//减等于
a -= 5; // a = a - 5
console.log(a);
//乘等于
a *= -5; // a = a *- 5
console.log(a); //10
//除等于
a /= 2; // a = a / 5
console.log(a); //5
//取余等于
a %= 6; // a = a / 6
console.log(a); //5
递加:
符号++,与前面的变量之间不能有空格。而且++符号可以写在变量的前面,也可以写在后面。着这两种情况使用时有一些区别。
++a:如果在一个算式里,第一次使用的值,是加完后的值,第二次使用也是加完后的新值。
a++:如果在一个算是里,参与运算时,第一次使用时原来的就值,第二次使用的时候就是新值。
//递加 var a = 2; console.log(a++); console.log(a); a = 2; console.log(++a); console.log(a);
特殊运算:
var a = 10,
b = 20,
c = 30;
var sum = ++a + b++ + a++ + ++c;
console.log(sum); //73
console.log(a);//12
console.log(b);//21
console.log(c);//31
7、综合运算顺序
贴身的 → 数学的 → 比较 → 逻辑的 → 赋值的。
综合案例: var a = 4; a *= 1 * (2 + 3) && ++a || 5 > 6 && 7 < 8 || !9;
|
原式 = a *= 1 * (2 + 3) && ++a || 5 > 6 && 7 < 8 || !9;
= a *= 1 * (2 + 3) && 5 || 5 > 6 && 7 < 8 || false;
= a *= 5 && 5 || 5 > 6 && 7 < 8 || false;
= a *= 5 && 5 || false && true || false
= a *= 5 || false || false
= a *= 5
a = 20
三、条件分支语句
是流程控制语句的一种。
JS代码如果没有特殊结构,从上往下依次执行。
流程可以被控制:想执行一些代码,直接跳过,选择性的执行。
条件分支语句:执行这个语句的时候,如果满足我们的特定条件,会执行特定的代码。其他的不执行。
1、if语句
if是如果的意思。else,否则。
语法: if(condition){ statement1 //结构体,多行代码,写在一对大括号内部
}
else{ statement2 }
结构体要执行就都执行,要不执行,就都不执行。
condition:条件表达式,强制给我们转成布尔值。
含义:如果条件condition为真,执行第一个结构体。如果为假,执行第二个结构体。
if(条件){
条件为真,执行的结构体;
}else{
条件为假,执行的结构体;
}
//请输入您的成绩
var a = parseFloat(prompt("请输入您成绩"));
//判断是否及格
//要么及格,要么不及格,输出语句有两个,进行选择
if(a >= 60) {
alert("恭喜,及格了");
}else {
alert("很遗憾,还没及格,继续努力");
}
if语句可以没有else,条件成立执行结构体,不成立直接退出程序
//不写else
if(a < 60) {
alert("抱歉没及格,努力吧");
}
如果执行的结构体只有单行语句,可以省略大括号
if(a >= 60)
alert("恭喜,及格了");
else
alert("很遗憾,还没及格,继续努力");
也能写在if语句的同一行,仅限单行结构体。
if(a >= 60) alert("恭喜,及格了");
else alert("很遗憾,没及格,继续努力");
这两种写法不会报错,但是为了避免出一些不必要的问题,尽量写大括号。
大括号后面不需要写分号,不会出错。
if语句殊途同归,不管执行哪个程序,退出后都继续执行后面的语句
//请输入您的成绩
var a = parseFloat(prompt("请输入您成绩"));
//判断是否及格
//要么及格,要么不及格,输出语句有两个,进行选择
if(a >= 60) {
alert("恭喜,及格了");
}else {
alert("很遗憾,还没及格,继续努力");
}
alert("好好准备下一次考试");
2、多条件分支语句
条件并不是只有一个,每一个条件对应一个结构体。
if……else if …… else if…… else if…… else …… 如果……否则如果……否则如果……否则……
if(条件1){
满足条件1执行的结构体
}else if(条件2){
条件1不满足,满足条件2时执行的结构体
}else if(条件3){
条件1/2都不满足,满足条件3时执行的结构体
}else if(条件4){
条件1/2/3都不满足,满足条件4时执行的结构体
}else{
以上条件都不满足,执行的结构体
}
跳楼现象:程序会选择一个分支执行(跳楼),如果执行了这个分支,表示前面分支的条件都没有满足。
案例:详细划分成绩评价,优秀,良好,及格,不及格。
if(a >= 90) {
alert("优秀");
}else if(a >= 70) { //如果走到这一步,隐含了a < 90
alert("良好"); //执行完之后,直接跳楼,不会执行后面的分支
}else if(a >= 60) {
alert("及格"); //如果走到这一步,隐含了a < 70
}else {
alert("不及格");
}
经典案例:一个大坑
var b = 1;
if(b <= 3) { //只会选择这个条件内部的结构体,执行后直接跳楼
b += 4;
}else if(b <= 5) {
b += 3
}else if(b <= 9) {
b += 4;
}else {
b += 10;
}
console.log(b);
3、if语句嵌套
制作一个结构的时候,有两个限制条件,可以使用if语句的嵌套。
if语句可以嵌套if语句使用,最终执行符合条件成立的结构体
//请输入您的性别和年龄
var sex = prompt("请输入您的性别","男");
var age = prompt("请输入您的年龄","22");
//判断是否能结婚了
if(sex == "男" && age >= 22) {
alert("可以领证了");
}else if(sex =="女" && age >= 20) {
alert("可以领证了");
}else {
alert("你还小,等等吧");
}
以上程序也可以达到效果:结构划分不清晰,条件比较复杂。
//if语句嵌套方法,每一层if语句只判断一个条件,内部再去进行另一个条件的判断
//第一层,只判断性别
if(sex == "男") {
//第二层,判断年龄
if(age >= 22) {
alert("可以领证了");
}else {
alert("你还小,等等吧");
}
}else {
if(age >= 20) {
alert("可以领证了");
}else {
alert("你还小,等等吧");
}
}
JS第2天作业
第1题:
用户输入一个数字,然后判断这个数字能否被5、6整除的情况,根据情况弹出下面4种警告框:
比如30
比如15
比如18
比如14
//能被5,6同时整除
//被5整除、不被6整除
//被6整除、不被5整除
//都不被5、6整除
//能被整除,说明取余的得0
//用户输入一个整数
var num = parseInt(prompt("请输入一个整数"));
// if(num % 5 == 0 && num % 6 == 0) {
// alert("被5,6同时整除")
// }else if(num % 5 == 0 && num % 6 != 0) {
// alert("能被5整除、不能被6整除");
// }else if(num % 5 != 0 && num % 6 == 0) {
// alert("被6整除,不被5整除");
// }else {
// alert("不能被5、6整除");
// }
if(num % 5 == 0) {
//都是能被5整除
if(num % 6 == 0) {
//能被6整除
alert("能被5、6整同时整除");
}else {
//不能被6整除
alert("能被5整除、不能被6整除");
}
}else {
//不能被5整除
if(num % 6 == 0) {
//能被6整除
alert("被6整除,不被5整除");
}else {
//不能被6整除
alert("不能被5、6整除");
}
}
第2题:
用户输入一个数字,然后再输入一个数字。然后弹出警告框:
比如用户输入3、147,都是奇数
比如用户输入6、171,不一样
注意,我们并不关心他们“都为奇数”、“都为偶数”,只是关心奇偶性一致的情况。
思路:判断奇偶性,看这个数字能否被2整除,余数是0。
判断依据:同为奇数,同为偶数,其他情况不同奇偶。
输出语句,判断是否相同,不用知道到底是奇数还是偶数。
//判断依据:同为奇数,同为偶数,其他情况不同奇偶。 var a = parseInt(prompt("请输入一个整数")); var b = parseInt(prompt("请再输入一个整数")); //要么同时为奇数、要么同时为偶数、其他都不是奇偶性 // if(a % 2 == 0 && b % 2 == 0 || a % 2 != 0 && b % 2 != 0) { // alert("奇偶性相同"); // }else { // alert("奇偶性不同"); // } //嵌套,判断同为奇数,或者同为偶数 if(a % 2 == 0) { if(b % 2 == 0) { alert("奇偶性相同"); }else { alert("奇偶性不同"); } }else { if(b % 2 == 0) { alert("奇偶性不同"); }else { alert("奇偶性相同"); } }
第二种情况:一个数取2的余数,只有0/1两种情况
//进一步简化,如果取余相等,表示同为1、或者同为0
if(a % 2 == b % 2) {
alert("奇偶性相同");
}else {
alert("奇偶性不同");
}
第三种情况:偶数与偶数相加为偶数,奇数与奇数相加也为偶数。一个奇数加一个偶数是奇数。
思路:判断两个数的和是否为偶数,如果是,奇偶性相同,不是奇偶性不同。
//判断两个数的和的奇偶性
if((a + b) % 2 == 0) {
alert("奇偶性相同");
}else {
alert("奇偶性不同");
}
第3题:
用户输入一个年份,判断这个年是否是闰年。
判断闰年条件:
① 非整百年数除以4,无余为闰,有余不闰;
② 整百年数除以400,无余为闰,有余不闰。
比如:
2000年,整百数年,就要用②公式,除以400,无余数,所以是闰年。
1900年,整百年数,就要用②公式,除以400,有余数,所以不是闰年。
2100不是
……
2016
2012
2008
2004
2000
……
……
1904
1900不是
自己把中文判断条件转为计算机语言。
第一种情况 if语句嵌套
// 判断是否闰年有两种情况,整百年份和非整百年份
var year = parseInt(prompt("请输入一个年份","2016"));
//用if语句嵌套
if(year % 100 == 0) {
//整百年份除以400
if(year % 400 == 0) {
alert("是闰年");
}else {
alert("不是闰年");
}
}else {
//非整百年份除以4
if(year % 4 == 0) {
alert("是闰年");
}else {
alert("不是闰年");
}
}
第二种情况:可以将所有是闰年的条件写在一起。
条件:要么整百年份被400整除,要么非整百年份被4整除。其他的都不是闰年。
//要么整百年份被400整除,要么非整百年份被4整除。其他的都不是闰年。
if(year % 400 == 0 || year % 100 != 0 && year % 4 == 0) {
alert("是闰年");
}else {
alert("不是闰年");
}
第4题:
某个公司要给员工发年终奖,为了奖励老员工,所以工作时间越长,发的越多,规则如下:
工作满0年 发月薪的1倍月薪年终奖,如果月薪大于8000,那么就是发1.2倍
工作满1年 发月薪的1.5倍月薪年终奖,如果月薪大于10000,那么就是发1.7倍
工作满2年,甚至更多 发月薪的3倍月薪年终奖,如果月薪大于12000,那么就是发3.2倍
用JS编写程序,让用户输入工作了几年,可以输入0,然后输入月薪。然后算年终奖。
思路:找到两个参数,年终奖 = 月工资*倍数。
倍数要根据工作年限和工资来定。
//输入工作年限、工资、输出年终奖
var year = parseInt(prompt("请输入你的工作年限,不满一年输入0"));
var salary = parseInt(prompt("请输入你的月工资"));
//工作满0年 发月薪的1倍月薪年终奖,如果月薪大于8000,那么就是发1.2倍
//工作满1年 发月薪的1.5倍月薪年终奖,如果月薪大于10000,那么就是发1.7倍
//工作满2年,甚至更多 发月薪的3倍月薪年终奖,如果月薪大于12000,那么就是发3.2倍
var bonus = 0; //里面要放数字类型
if(year == 0) {
//发月薪的1倍月薪年终奖,如果月薪大于8000,那么就是发1.2倍
if(salary > 8000) {
bonus = salary * 1.2;
}else {
bonus = salary * 1;
}
}else if(year == 1) {
if(salary > 10000) {
bonus = salary * 1.7;
}else {
bonus = salary * 1.5;
}
}else {
if(salary > 12000) {
bonus = salary * 3.2;
}else {
bonus = salary * 3;
}
}
alert("您的年终奖是"+bonus+"元");
第二种:奖倍数作为一个变量,分支都输出一个对应的倍数,输出之后,计算年终奖。再输出
var year = parseInt(prompt("请输入你的工作年限,不满一年输入0"));
var salary = parseInt(prompt("请输入你的月工资"));
var bonus = 0; //里面要放数字类型
var beishu;
if(year == 0) {
//发月薪的1倍月薪年终奖,如果月薪大于8000,那么就是发1.2倍
if(salary > 8000) {
beishu = 1.2
}else {
beishu = 1;
}
}else if(year == 1) {
if(salary > 10000) {
beishu = 1.7;
}else {
beishu = 1.5;
}
}else {
if(salary > 12000) {
beishu = 3.2;
}else {
beishu = 3;
}
}
bonus = salary * beishu;
alert("您的年终奖是"+bonus+"元");