今天突发奇想,想要垂直精学一段时间的javascript,用我的第一次「连载」来记录总结一些知识点吧。
知识点
原始类型的类型转换
类型转换
- alert 会自动将任何值都转换为字符串以进行显示。算术运算符会将值转换为数字
- 常用的类型转换:转换为 string 类型、转换为 number 类型和转换为 boolean 类型
- 字符串转换 —— 转换发生在输出内容的时候,也可以通过 String(value) 进行显式转换。原始类型值的 string 类型转换通常是很明显的
- 数字型转换 —— 转换发生在进行算术操作时,也可以通过 Number(value) 进行显式转换。
Number类型转换
值 | 变成…… |
---|---|
undefined | NaN |
null | 0 |
true / false | 1/0 |
string | 去掉首尾空白字符(空格、换行符 \n、制表符 \t 等)后的纯数字字符串中含有的数字。如果剩余字符串为空,则转换结果为 0。否则,将会从剩余字符串中“读取”数字。当类型转换出现 error 时返回 NaN。 |
布尔型转换
值 | 变成…… |
---|---|
0, null, undefined, NaN, “” | false |
其他值 | true |
对 “0” 和只有空格的字符串(比如:" ")进行布尔型转换时,输出结果为 true
用二元运算符 + 连接字符串
只要任意一个运算元是字符串,那么另一个运算元也将被转化为字符串。
alert( '1' + 2 ); // "12"
alert(2 + 2 + '1' ); // "41"
alert('1' + 2 + 2); // "122"
二元 + 是唯一一个以这种方式支持字符串的运算符。其他算术运算符只对数字起作用,并且总是将其运算元转换为数字
alert( 6 - '2' ); // 4
alert( '6' / '2' ); // 3
数字转化,一元运算符 +
一元运算符加号,或者说,加号 + 应用于单个值,对数字没有任何作用。但是如果运算元不是数字,加号 + 则会将其转化为数字
let x = 1; alert( +x ); // 1
let y = -2; alert( +y ); // -2
alert( +true ); // 1
alert( +"" ); // 0
效果和 Number(…) 相同,但是更加简短(推荐以下做法)
let apples = "2";
let oranges = "3";
// 在二元运算符加号起作用之前,所有的值都被转化为了数字
alert( +apples + +oranges ); // 5
运算符优先级
优先级 | 名称 | 符号 |
---|---|---|
… | … | … |
15 | 一元加号 | + |
15 | 一元负号 | - |
14 | 求幂 | ** |
13 | 乘号 | * |
13 | 除号 | / |
12 | 加号 | + |
12 | 减号 | - |
… | … | … |
2 | 赋值符 | = |
… | … | … |
我们可以看到,“一元加号运算符”的优先级是 15,高于“二元加号运算符”的优先级 12。这也是为什么表达式 “+apples + +oranges” 中的一元加号先生效,然后才是二元加法。
赋值运算符 =也是运算符
链式赋值(Chaining assignments)
let a, b, c;
a = b = c = 2 + 2;
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
let n = 2;
n *= 3 + 5;
alert( n ); // 16
自增/自减
如果我们想要对变量进行自增操作,并且 需要立刻使用自增后的值,那么我们需要使用前置形式:
let counter = 0; alert( ++counter ); // 1
如果我们想要将一个数加一,但是我们想使用其自增之前的值,那么我们需要使用后置形式:
let counter = 0; alert( counter++ ); // 0
自增/自减和其它运算符的对比
++/-- 运算符同样可以在表达式内部使用。它们的优先级比绝大部分>的算数运算符要高。
举个例子:
let counter = 1;
alert( 2 * ++counter ); // 4
与下方例子对比:
let counter = 1;
alert( 2 * counter++ ); // 2,因为 counter++ 返回的是“旧值”
尽管从技术层面上来说可行,但是这样的写法会降低代码的可阅读性。在一行上做多个操作 —— 这样并不好。
当阅读代码时,快速的视觉“纵向”扫描会很容易漏掉 counter++,这样的自增操作并不明显。
我们建议用“一行一个行为”的模式:
let counter = 1;
alert( 2 * counter );
counter++;
位运算符
按位与 ( & )
按位或 ( | )
按位异或 ( ^ )
按位非 ( ~ )
左移 ( << )
右移 ( >> )
无符号右移 ( >>> )
这些运算符很少被使用,一般是我们需要在最低级别(位)上操作数字时才使用。我们不会很快用到这些运算符,因为在 Web 开发中很少使用它们,但在某些特殊领域中,例如密码学,它们很有用。
逗号运算符(tips)
逗号运算符的优先级非常低
请注意逗号运算符的优先级非常低,比 = 还要低,因此上面你的例子中圆括号非常重要。
如果没有圆括号:a = 1 + 2, 3 + 4 会先执行 +,将数值相加得到 a = 3, 7,然后赋值运算符 = 执行 a = 3,然后逗号之后的数值 7 不会再执行,它被忽略掉了。相当于 (a = 1 + 2), 3 + 4。
为什么需要这样一个运算符,它只返回最后一个值呢?
有时候,人们会使用它把几个行为放在一行上来进行复杂的运算。
举个例子:
// 一行上有三个运算符
for (a = 1, b = 3, c = a * b; a < 10; a++) {
…
}
这样的技巧在许多 JavaScript 框架中都有使用,这也是为什么我们提到它。但是通常它并不能提升代码的可读性,使用它之前,我们要想清楚。
节后小测题
第一题
let a = 1, b = 1;
let c = ++a; // ?
let d = b++; // ?
第一题
let a = 2;
let x = 1 + (a *= 2);
第一题
"" + 1 + 0
"" - 1 + 0
true + false
6 / "3"
"2" * "3"
4 + 5 + "px"
"$" + 4 + 5
"4" - 2
"4px" - 2
" -9 " + 5
" -9 " - 5
null + 1
undefined + 1
" \t \n" - 2
第一题
a = 2
b = 2
c = 2
d = 1
第一题
a = 4(乘以 2)
x = 5(相当于计算 1 + 4)
第三题
- ‘10’
- 1
- 1
- 2
- 6
- ‘9px’
- ‘$45’
- 2
- NaN
-4" -9 5"(第二次说:只要任意一个运算元是字符串,那么另一个运算元也将被转化为字符串)NaN-14(第二次说:二元 + 是唯一一个以这种方式支持字符串的运算符。其他算术运算符只对数字起作用,并且总是将其运算元转换为数字)- 1
- NaN
- -2
此处,可以幻想用柯南的语气解析答案:字符串的加法 “” + 1,首先会将数字 1 转换为一个字符串:“” + 1 = “1”,然后我们得到 “1” + 0,再次应用同样的规则得到最终的结果。
减法 -(像大多数数学运算一样)只能用于数字,它会使空字符串 “” 转换为 0。
带字符串的加法会将数字 5 加到字符串之后。
减法始终将字符串转换为数字,因此它会使 " -9 " 转换为数字 -9(忽略了字符串首尾的空格)。
null 经过数字转换之后会变为 0。
undefined 经过数字转换之后会变为 NaN。
字符串转换为数字时,会忽略字符串的首尾处的空格字符。在这里,整个字符串由空格字符组成,包括 \t、\n 以及它们之间的“常规”空格。因此,类似于空字符串,所以会变为 0。
第四题-修正加法
let a = prompt("First number?", 1); let b = prompt("Second number?", 2); alert(a + b); // 12
现在,想想为什么弹窗出12?然后修正它。使弹窗结果为 3。
解决思路为:
|
|
|
|
|
在 + 之前将字符串转换为数字。例如,使用 Number() 或在 prompt 前加 +
方案1:
let a = +prompt("First number?", 1);
let b = +prompt("Second number?", 2);
alert(a + b); // 3
方案2:
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);
alert(+a + +b); // 3
最新的代码中,同时使用一元和二元的 +。看起来确实很有趣,不是吗?