语法基础(二)
# 操作符
# 一元操作符
# 递增与递减
++ 和 -- 放在变量前面时符合直接,返回值为对应运算后的结果,放在变量后面时,会先返回运算前的结果,再进行对应的运算。
let num1 = 2
let num2 = 20
let num3 = num1++ + num2
let num4 = num1 + num2
console.log(num3) // 22
console.log(num4) // 23
2
3
4
5
6
- 规则
- 对于字符串,如果是有效的数值形式,则转换为数值再应用改变。变量类型从字符串变成数值。
- 对于字符串,如果不是有效的数值形式,则将变量的值设置为 NaN 。变量类型从字符串变成 数值。
- 对于布尔值,如果是false,则转换为0 再应用改变。变量类型从布尔值变成数值。
- 对于布尔值,如果是true,则转换为1 再应用改变。变量类型从布尔值变成数值。
- 对于浮点值,加1 或减1。
- 如果是对象,则调用其valueOf()方法取得可以操作的值。对得到的值应用上述规则。如果是NaN,则调用toString()并再次应用其他规则。变量类型从对象变成数值。
# 一元 加减
主要用于基本的算术,也可以进行数据类型转换
# 位操作符
js中的位运算
笔记
ECMAScript中的所有数值都以 IEEE 754 64 位格式存储,但位操作并不直接应用到 64 位表示,而是先把值转换为32 位整数,再进行位操作,之后再把结果转换为64 位。对开发者而言,就好像只有32 位整数一样,因为64 位整数存储格式是不可见的。既然知道了这些,就只需要考虑32 位整数即可。
有符号整数使用32 位的前31 位表示整数值。第32 位表示数值的符号,如0 表示正,1 表示负。这一位称为符号位(sign bit),它的值决定了数值其余部分的格式。
负数使用补码进行存储,方便直接和正数进行加法计算。
补码计算方式,原码取反加一
注意
在对ECMAScript 中的数值应用位操作符时,后台会发生转换:64 位数值会转换为32 位数值,然后执行位操作,最后再把结果从32 位转换为64 位存储起来。整个过程就像处理32 位数值一样,这让二进制操作变得与其他语言中类似。但这个转换也导致了一个奇特的副作用,即特殊值NaN 和Infinity在位操作中都会被当成0 处理。
# 按位非(NOT)
按位非操作符由一个波浪线(~)表示,执行操作数的二进制表示的按位非。简单说,就是将操作数的二进制表示中的所有位都取反。
let num1 = 25
let num2 = ~num1
console.log(num2) // -26
2
3
# 按位与(AND)
按位与操作符由和号(&)表示,它将两个数的二进制形式对齐,然后进行逐位比较。如果两个相应的位都为1,则该位的结果为1,否则为0。
let num1 = 25
let num2 = 3
let num3 = num1 & num2
console.log(num3) // 1
2
3
4
# 按位或(OR)
按位或操作符由符号(|)表示,它将两个数的二进制形式对齐,然后进行逐位比较。如果两个相应的位都为0,则该位的结果为0,否则为1。
let num1 = 25
let num2 = 3
let num3 = num1 | num2
console.log(num3) // 27
2
3
4
# 按位异或(XOR)
按位异或操作符由符号(^)表示,它将两个数的二进制形式对齐,然后进行逐位比较。如果两个相应的位不同,则该位的结果为1,否则为0。
let num1 = 25
let num2 = 3
let num3 = num1 ^ num2
console.log(num3) // 26
2
3
4
# 左移(Shift Left)
左移操作符由两个小于号(<<)表示,它将数值的所有位向左移动指定的位数。左移时,右侧空出的位用0 填充。
let num1 = 2
let num2 = num1 << 5
console.log(num2) // 64
2
3
# 有符号右移(Shift Right)
有符号右移操作符由两个大于号(>>)表示,它将数值的所有位向右移动指定的位数。使用有符号右移时,会保留符号位(最左侧位)。如果该位为0,表示负数;如果该位为1,表示正数。
let num1 = 64
let num2 = num1 >> 5
console.log(num2) // 2
2
3
# 无符号右移(Shift Right Unsigned)
无符号右移操作符由三个大于号(>>>)表示,它将数值的所有位向右移动指定的位数。使用无符号右移时,会将符号位也一起移动,因此符号位的值变为0,结果总是非负的。
let num1 = -64
let num2 = num1 >>> 5
console.log(num2) // 134217726
2
3
# 布尔操作符
# 逻辑非(NOT)
逻辑非操作符由一个叹号(!)表示,它将操作数转换为布尔值,然后取反。
let num = 25
console.log(!num) // false
2
# 逻辑与(AND)
逻辑与操作符由两个和号(&&)表示,它将两个操作数都转换为布尔值,然后返回第一个操作数的值(如果该值为假)或第二个操作数的值(如果该值为真)。
let num1 = 25
let num2 = 3
let num3 = num1 && num2
console.log(num3) // 3
2
3
4
# 逻辑或(OR)
逻辑或操作符由两个竖线(||)表示,它将两个操作数都转换为布尔值,然后返回第一个操作数的值(如果该值为真)或第二个操作数的值(如果该值为假)。
let num1 = 25
let num2 = 3
let num3 = num1 || num2
console.log(num3) // 25
2
3
4
# 乘性操作符
# 乘法(Multiplication)
乘法操作符由一个星号(*)表示,用于计算两个数值的乘积。
let num1 = 25
let num2 = 3
let num3 = num1 * num2
console.log(num3) // 75
2
3
4
# 除法(Division)
除法操作符由一个斜线(/)表示,用于计算两个数值的商。
let num1 = 25
let num2 = 3
let num3 = num1 / num2
console.log(num3) // 8.333333333333334
2
3
4
5
# 求模(Modulus)
求模操作符由一个百分号(%)表示,用于计算两个数值的余数。
let num1 = 25
let num2 = 3
let num3 = num1 % num2
console.log(num3) // 2
2
3
4
# 指数操作符
# 指数(Exponentiation)
指数操作符由两个星号(**)表示,用于计算一个数的指数值。
let num1 = 2
let num2 = num1 ** 5
console.log(num2) // 32
2
3
ES7新增 ** 操作符,代替Math.pow()
# 语句
# do-while 语句
do-while 语句是一种后测试循环语句,即循环体中的代码执行后才会对退出条件进行求值。换句话说,循环体内的代码至少执行一次。do-while 的语法如下:
do {
statement
} while (expression);
2
3
提示
do-while循环是后测试循环,while和for循环是先测试循环
# for-in 语句
for-in 语句是一种精准的迭代语句,用于枚举对象中的非符号键属性,语法如下:
for (property in expression) statement
提示
for-in循环用于遍历对象的可枚举属性,包括对象自身的属性和继承的属性。如果需要遍历对象自身的属性,可以使用hasOwnProperty()方法进行过滤。
# for-of 语句
for-of 语句是一种迭代语句,用于遍历可迭代对象(如数组、字符串、Map、Set等)中的元素,语法如下:
for (variable of iterable) statement
提示
for-of循环用于遍历可迭代对象中的元素,包括数组、字符串、Map、Set等。如果需要遍历对象的可枚举属性,可以使用Object.keys()、Object.values()、Object.entries()等方法获取对象的可枚举属性,然后使用for-of循环进行遍历。
# for-await-of 语句
for-await-of 语句是一种迭代语句,用于遍历异步可迭代对象(如异步迭代器、Promise等)中的元素,语法如下:
for await (variable of iterable) statement
提示
for-await-of循环用于遍历异步可迭代对象中的元素,包括异步迭代器、Promise等。如果需要遍历异步可迭代对象的可枚举属性,可以使用Object.keys()、Object.values()、Object.entries()等方法获取异步可迭代对象的可枚举属性,然后使用for-await-of循环进行遍历。
# 标签语句
标签语句用于给语句加标签,语法如下:
label: statement 下面是一个例子:
start: for (let i = 0; i < count; i++) {
console.log(i);
}
2
3
在这个例子中,start 是一个标签,可以在后面通过break 或continue 语句引用。标签语句的典型应用场景是嵌套循环。
let num = 0;
outermost:
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
if (i == 5 && j == 5) {
break outermost;
}
num++;
}
}
console.log(num); // 55
2
3
4
5
6
7
8
9
10
11
let num = 0;
outermost: for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
if (i == 5 && j == 5) {
continue outermost;
}
num++;
}
}
console.log(num); // 95
2
3
4
5
6
7
8
9
10
11
# with 语句
with 语句的用途是将代码作用域设置为特定的对象,其语法是:
with (expression) statement;
使用with 语句的主要场景是针对一个对象反复操作,这时候将代码作用域设置为该对象能提供便利,如下面的例子所示:
let qs = location.search.substring(1);
let hostName = location.hostname;
let url = location.href;
2
3
上面代码中的每一行都用到了location 对象。如果使用with 语句,就可以少写一些代码:
with(location) {
let qs = search.substring(1);
let hostName = hostname;
let url = href;
}
2
3
4
5
这里,with 语句用于连接location 对象。这意味着在这个语句内部,每个变量首先会被认为是一个局部变量。如果没有找到该局部变量,则会搜索location 对象,看它是否有一个同名的属性。如果有,则该变量会被求值为location 对象的属性。
严格模式不允许使用with 语句,否则会抛出错误。
提示
由于with 语句影响性能且难于调试其中的代码,通常不推荐在产品代码中使用with语句。
# switch 语句
能够在条件判断中使用表达式,就可以在判断中加入更多逻辑:
let num = 25;
switch (true) {
case num < 0:
console.log("Less than 0.");
break;
case num >= 0 && num <= 10:
console.log("Between 0 and 10.");
break;
case num > 10 && num <= 20:
console.log("Between 10 and 20.");
break;
default:
console.log("More than 20.");
}
2
3
4
5
6
7
8
9
10
11
12
13
14
提示
switch 语句在比较每个条件的值时会使用全等操作符,因此不会强制转换数据类 型(比如,字符串"10"不等于数值10)