JavaScript基础提升【二】
目录
算术运算符
加法运算符
减法运算符
乘法运算符
除法运算符
使用JS运算符与对象
余数运算符
使用余数运算符的特殊值
利用余数运算符构建模运算符
赋值运算符
链接JS赋值运算符
逗号运算符
一元运算符
比较运算符
比较数字与其他类型的数值
比较对象与非对象
比较布尔值与其他值
比较null和undefined
比较NaN与其他值
严格等于===和不严格等于==
逻辑运算符
逻辑非运算符
逻辑与运算符
逻辑或运算符
逻辑运算符优先级
逻辑赋值运算符
逻辑或赋值运算符
逻辑与赋值运算符
空值合并赋值运算符
空值合并运算符
为什么使用空值合并运算符
短路效应
幂运算符
其他
算术运算符
加法运算符
加法运算符计算的两个值,如果一个值为字符串,则加法运算符将使用以下规则:
- 如果两个值都是字符串,则将第二个字符串连接到第一个字符串
- 如果一个值是字符串,则将隐式地将数值转换为字符串,并将两个字符串连接起来
另一个数值转换为字符串遵循以下规则:
- 对象转换为字符串:“[object Object]”(默认toString()方法)
- 数字转换为字符串:在数字两边加引号
- 布尔转换为字符串:在布尔值两边加引号
- 数组转换为字符串:去掉数组两边方括号,只保留数组元素(包括逗号)
- null转换为字符串:null两边加引号
- undefined转换为字符串:undefined两边加引号
- 函数转换为字符串:函数表达式两边加引号
console.log({} + "");
console.log(1.2 + "");
console.log(true + "");
console.log([1, 2] + "");
console.log([1, {}] + "");
console.log(null + "");
console.log(undefined + "");
console.log(function () {} + "");
特殊数字相加得到结果如下表所示:
第一个值 | 第二个值 | 结果 |
---|---|---|
NaN | 任意值 | NaN |
Infinity | Infinity | Infinity |
-Infinity | -Infinity | -Infinity |
Infinity | -Infinity | NaN |
+0 | +0 | +0 |
-0 | +0 | +0 |
-0 | -0 | -0 |
减法运算符
减法运算符操作的两个数值,如果有一个数值是:“字符串”、“布尔值”、“null”、“undefined”,则先使用Number()尝试将该值转换为数字,再执行减法:
使用Number()转换数字遵循以下规则:
- 数字字符串(整数、小数):对应数字
- 复杂字符串(包括数字、特殊符号、英语字符):NaN
- 布尔值:true = 1,false = 0
- null:0
- undefined:NaN
特殊数字相减得到结果如下表所示:
第一个值 | 第二个值 | 结果 |
---|---|---|
NaN | 任意值 | NaN |
Infinity | Infinity | NaN |
-Infinity | -Infinity | NaN |
Infinity | -infinity | Infinity |
+0 | +0 | +0 |
+0 | -0 | +0 |
-0 | -0 | +0 |
乘法运算符
与减法运算符一样,乘法两侧如果有数值不是数字,将尝试使用Number()转换
特殊数字相乘得到结果如下表所示:
第一个值 | 第二个值 | 结果 |
---|---|---|
NaN | 任意值 | NaN |
Infinity | 0 | NaN |
-Infinity | 0 | NaN |
Infinity | 整数 | Infinity |
Infinity | 负数 | -Infinity |
Infinity | Infinity | Infinity |
-Inifinity | Infinity | -Infinity |
除法运算符
与减法运算符和乘法运算符一样,除法两侧如果有数值不是数字,将尝试使用Number()转换
特殊数字相除得到结果如下表所示:
第一个值 | 第二个值 | 结果 |
---|---|---|
NaN | 任意值 | NaN |
数字 | 0 | Inifinity |
Infinity | Infinity | NaN |
0 | 0 | NaN |
Infinity | 正数 | Infinity |
Infinity | 负数 | -Infinity |
-Infinity | 正数 | -Infinity |
-Infinity | 负数 | Infinity |
使用JS运算符与对象
使用JS运算符时,如果一个值为对象,JS引擎则先调用对象的valueOf()方法获取“用于计算的值”,如果对象没有valueOf()方法,但有“toString()”方法,则调用toString()获取“用于计算的值”
const a = {valueOf() {return NaN;},toString() {return "obj";}
}
const b = {toString() {return "123";}
}
const c = {valueOf() {return "123";}
}
const d = {}
// 有valueOf,则调用valueOf,忽略toString
console.log(a + 1);
// 没有valueOf,则调用toString
console.log(b + 1);
// 使用Number()调用valueOf,没有则调用toString
console.log(Number(a), Number(b));
// 使用String()只调用toString
console.log(String(a), String(b), String(c));
// 空对象没有valueOf,但是原型链上有toString()
console.log(String(d));
// 尝试删除空对象原型链上的toString()方法
delete d.__proto__.toString;
console.log(String(d));
余数运算符
JS使用“%”表示余数运算符
PS:“余数的符号与被除数的符号相同”
console.log(5 % 3); // 2
console.log(5 % -3); // 2
console.log(-5 % 3); // -2
console.log(-5 % -3); // -2
使用余数运算符的特殊值
- 被除数是Infinity且除数是有限数,则余数为NaN
console.log(Infinity % 2); // NaN
- 被除数是有限数且除数为0,则余数为NaN
console.log(10 % 0); // NaN
- 被除数和除数都是Infinity,则余数为NaN
console.log(Infinity % Infinity); // NaN
- 被除数是有限数且除数是Infinity,余数为被除数
console.log(111 % Infinity); // 111
- 被除数是0,除数非0,余数为0
console.log(0 % 11); // 0
- 被除数或除数不是数字,使用Number()转换为数字后再相除
console.log("11" % 1); // 0
console.log("asd" % 1); // NaN
利用余数运算符构建模运算符
可以利用数学公式:
modulo = ((dividend % divisor)+ divisor)% divisor
function mod (dividend, divisor) {return (dividend % divisor + divisor) % divisor;
}
console.log(mod(-1, 5)); // 4
console.log(mod(5, 3)); // 2
赋值运算符
链接JS赋值运算符
在一次变量定义中,可以使用逗号“,”分隔,一次定义多个变量:
const a = 1, b = 2, c = 3;
console.log(a, b, c); // 1 2 3
如果想将单个值一次赋给多个变量,可以使用“链接赋值运算符”,它的执行顺序是“从右到左”
let a = 1, b = 2, c = 3;
a = b = c;
console.log(a, b, c); // 3 3 3
// 上面的 a = b = c,相当于下面的语句
b = c;
a = b;
逗号运算符
逗号运算符会从左到右依次执行每个表达式:
const a = (1, 2, 3);
console.log(a); // 3
- 先执行1,无意义,仅执行
- 再执行2,无意义,仅执行
- 最后执行a = 3
一元运算符
一元运算符有:
- +x:一元加号,将值变为数字
- -x:一元减号,将值变为数字并取反
- ++x:一元自增,前缀,执行完语句再自增
- --x:一元自减,前缀,执行完语句再自减
- x++:一元自增,后缀,自增完再执行语句
- x--:一元自减,后缀,自减完再执行语句
一元加号和一元减号将值变为数字,本质上就是使用Number()转变
比较运算符
比较数字与其他类型的数值
如果一个值是数字,另一个值不是,则比较运算符将非数字值转换为数字,再进行数值比较:
console.log(1 < "2"); // true
比较对象与非对象
如果一个值为对象,则调用该对象的valueOf(),如果没有valueOf()则调用toString(),都没有返回NaN,最后比较
let apple = {valueOf: function () {return 10;},
};let orange = {toString: function () {return '20';},
};
console.log(apple > 10); // false
console.log(orange == 20); // true
但也有特殊情况:
console.log({} > "1"); // true
console.log({} > 1); // false
- 尝试获取{}原始值,得到[object Object],“[” 大于 “1”,所以返回true
- 尝试获取{}原始值,得到[object Object],Number后得到NaN,所以返回false
比较布尔值与其他值
如果一个值为布尔值,JS将其转换为数字,再进行比较:
console.log(true > 0); // true
console.log(false < 1); // true
console.log(true > false); // true
console.log(false > true); // false
console.log(true >= true); // true
console.log(true <= true); // true
console.log(false <= false); // true
console.log(false >= false); // true
比较null和undefined
null等于undefined
console.log(null == undefined); // true
console.log(null === undefined); // false
比较NaN与其他值
NaN与任何值进行大于、小于、等于比较,只会返回false
NaN与任何值进行不等于比较,会返回true
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
console.log(NaN > 0); // false
console.log(NaN == 0); // false
console.log(NaN < 0); // false
console.log(NaN != NaN); // true
console.log(NaN !== NaN); // true
严格等于===和不严格等于==
===与==最大的区别就是:
- ==会将左右两侧数据进行类型转换,直到类型相同后再比较
- ===不会进行类型转换,如果两侧数据类型不同,直接返回false
console.log(1 == "1"); // true
console.log(1 === "1"); // false
逻辑运算符
逻辑非运算符
逻辑!运算符根据以下规则工作:
- !undefined:true
- !null:true
- !非0数字:false
- !0:true
- !NaN:true
- !对象:false
- !"":true
- !非空字符串:false
双重否定(!!):连续使用两次逻辑非运算符将值替换为真实布尔值,相当于使用Boolean()
let counter = 10;
console.log(Boolean(counter)) // true
console.log(!!counter); // true
逻辑与运算符
&&运算符链:
以下表达式使用多个&&运算符
const res = 1 && 2 && 3;
特点:
- 从左到右计算值
- 对于每个值,将其转换为布尔值,如果结果为false,则停止并返回第一个值
- 如果所有值都是真值,则返回最后一个值
const res = 1 && 2 && 3;
console.log(res); // 3
const res1 = 1 && 0 && 3;
console.log(res1); // 0
逻辑或运算符
||运算符链:
以下表达式使用多个||运算符
const res1 = 1 || 2 || 3;
特点:
- 从左到右计算值
- 对于每个值,将其转换为布尔值,如果结果为true,则停止并返回当前值
- 如果所有值都是false,则返回最后一个值
const res1 = 1 || 2 || 3;
console.log(res1); // 1
const res2 = 0 || 1 || 2;
console.log(res2); // 1
const res3 = 0 || "" || null;
console.log(res3); // null
逻辑运算符优先级
- 逻辑非(!)
- 逻辑与(&&)
- 逻辑或(||)
逻辑赋值运算符
逻辑赋值运算符是ES2021引入的:
- 逻辑或赋值运算符:||=
- 逻辑与赋值运算符:&&=
- 空值合并赋值运算符:??=
逻辑赋值运算符其实可以等效成逻辑运算符:
逻辑赋值运算符 | 逻辑运算符 |
---|---|
x ||= y | x || (x = y) |
x &&= y | x && (x = y) |
x ??= y | x ?? (x = y) |
逻辑或赋值运算符
逻辑或赋值运算符(||=)接受两个操作数,如果左操作数为假值,则将右操作数赋值给左操作数
let a;
a ||= 1;
console.log(a); // 1
a || (a = 2);
console.log(a); // 1
逻辑与赋值运算符
逻辑与赋值运算符仅在x为真值时才将y赋值给x
x &&= y
let a;
a &&= 1;
console.log(a); // undefined
a = 2;
a &&= 1;
console.log(a); // 1
空值合并赋值运算符
空值合并赋值运算符仅在x为null或undefined时才将y赋值给x
x ??= y
let a;
a ??= 1;
console.log(a); // 1
a ??= 2;
console.log(a); // 1
空值合并运算符
ES2020引入了空值合并运算符,用双问号(??)表示,它接受两个值:
value1 ?? value2
如果第一个值value1为“null”或“undefined”,则空值合并运算符返回第二个值value2,空值合并运算符等效于下面的代码块:
const value1 = undefined, value2 = "test";
const res = undefined;
if (res == null || res == undefined) {res = value2;
}
console.log(res); // "test"
为什么使用空值合并运算符
在变量指定默认值时,通常使用逻辑或运算符:
const count;
const res = count || 1; // 1
这个时候使用||是没有问题的,但是如果count的值为0,显然就不合适了,因此我们需要使用空值合并运算符:
const count = 0;
const res = count || 1; // 0
短路效应
如果第一个值(value1)不是null或undefined,那么??会直接结束,此时返回第一个值:
const res = 1 ?? 2;
console.log(res); // 1
幂运算符
幂运算符是:“**”,语法:
x ** 2 // 相当于Math.pow(x, 2);
其他
更多JavaScript知识可以参考我的专栏:
JavaScript_是洋洋a的博客-CSDN博客