你不知道的JavaScript
hawx1993 opened this issue · 0 comments
hawx1993 commented
摘录自己平时遇到的比较重要的js相关的知识点,文章会随时不断更新。
按位非(~)以及双非(~~)的使用
// 双非遇到false的值都将转为0
~~false; // 0
~~null; // 0
~~0; // 0
~~''; // 0
~~NaN; // 0
~~[]; // 0
~~{}; // 0
// 双重按位非(~~)对于数字的运算相当于Math.floor()
~~0.9 === 0;//true
// 对任一数值 x 进行按位非操作的结果为 -(x + 1),并向下取整
~3.9; //-4
~0; //-1
字符串数字大小的比较
'9' > '10';// true
字符串的比较是按字母排列顺序进行的比较,'1'字符排在字符'9'的前面,所以'9'大于'1'
计算精度问题
- 为什么0.1 + 0.2不等于0.3?
因为计算机是二进制来表示浮点数的,无法准确表示一个浮点数,只能逼近。首先我们要了解浮点数二进制表示, 有以下两个原则:
1.整数部分对 2 取余然后逆序排列
2.小数部分乘 2 取整数部分, 然后顺序排列
这就引出了一个问题, 你永远不能存下 0.1 的二进制, 即使你把全世界的硬盘都放在一起, 也存不下 0.1 的二进制小数.
要判断两个浮点数是否相等,还是建议用逼近的比较.比如ES6新增了一个Math.EPSILON
0.1+0.2 - 0.3 < Number.EPSILON;// true
setTimeout 间隔输出
改写如下,使之间隔输出:
for (var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log(i);
}, i*1000 );
}
setTimeout定时器执行时,会返回唯一的一个id,通常为数字。
1.借助循环闭包的特性,每次循环时,将i值保存在一个闭包中,当setTimeout中定义的操作执行时,则访问对应闭包保存的i值即可。
for (var i=1; i<=5; i++) {
(function(i) {
setTimeout( function timer() {
console.log(i);
}, i*1000 );
})(i)
}
2.利用let
for (let i=1; i<=5; i++) {
setTimeout( function timer() {
console.log(i);
}, i*1000 );
}
使用var,你拥有一个函数作用域,对于所有循环迭代只有一个共享绑定,即每个setTimeout回调中的i表示在循环迭代结束后最终等于5
for (var i = 1; i <= 3; i++) {
function timer() {
console.log(i);
}
setTimeout( timer, i * 1000 );
}
然后我们将循环展开,三次执行过程的变化如下:
// 第一步: i = 1;
setTimeout( timer, 1 * 1000 );
// 第二步:i = 2;
setTimeout( timer, 2 * 1000 );
// 第三步 i = 3;
setTimeout( timer, 3 * 1000 );
由于setTimeout是异步的,在循环过程中, timer() 函数并未变化,也没有执行( 计时器还未开始 )。
使用let,你拥有一个块级作用域,当在for循环中使用时,你可以为每个迭代获得一个新的绑定。 即每个setTimeout回调中的i表示一个不同的变量,每个变量都有一个不同的值