本书属于基础类书籍,会有比较多的基础知识,因此这里仅记录日常不怎么容易注意到的知识点,不会全记,供你们和本身翻阅;html
上中下三本的读书笔记:前端
43.toFixed(3) // 报错: Invalid or unexpected token 43..toFixed(3) // "43.000"
这是由于42.toFixed(3)
这里由于.
被视为常量42
的一部分,因此没有.
属性访问运算符来调用toFixed
方法。而42..toFixed
则没有问题。segmentfault
JSON.stringify
在对象中遇到undefined
、function
、symbol
时会自动将其忽略,在数组中则会返回null
,好比:数组
JSON.stringify([1, 23, 4, null, undefined, function(){ return 123 }]) // "[1,23,4,null,null,null]"
JS中的假值 undefined
、null
、false
、+0
、-0
、NaN
、""
浏览器
关于真假值的判断:微信
new Boolean(false) // true new Number(0) // true new String("") // true Boolean("false") // true Boolean("0") // true Boolean("''") // true Boolean([]) // true Boolean({}) // true Boolean(function() {}) // true
语句都有个结果值:并发
b = a
的结果值是a
的值var
的结果值是 undefined
{ ... }
的结果值是其最后一个语句表达式的结果标签语句异步
{ foo: bar() }
这里的 foo
是标签语句,带标签的循环跳转可使用 continue\break
来实现执行标签所在循环的下一轮循环或跳出标签所在循环;函数
foo: for (var i = 0; i < 4; i++){ for (var j = 0; j < 4 ; j++){ if ((i * j) === 3){ console.log('stoping', i, j) break foo; } console.log(i, j) } } // 0 0 // 0 1 // 0 2 // 0 3 // 1 0 // 1 1 // 1 2 // stoping 1 3
这里的 break foo
不是指跳转到标签 foo
所在位置继续执行,而是跳出标签 foo
所在的循环/代码块,继续执行后面的代码。所以这里的标签语句并不是传统意义上的 goto
;性能
关联
运算符有优先级,那么若是多个相同优先级的运算符同时出现,执行的顺序就和关联顺序有关了,JS默认的执行顺序是从左到右,可是有时候不是,好比:
? :
三元运算符是右关联,好比? : ? :
,实际上是? : (? :)
这样的顺序= =
连等是右关联,好比 a=b=c=2
,实际上是 (a=(b=(c=2)))
像函数传递参数时,arguments
数组中对应单元会和命名参数创建关联(linkage)以获得相同的值;相反,不传递参数就不会创建关联:
function foo(a){ a=42 console.log(arguments[0]) } foo(2) // 42 foo() // undefined
注意:严格模式没有创建关联一说;
finally
中的代码老是会在 try
以后执行,即便 try
中已经 return 了,若是有 catch
的话则在 catch
以后执行;
function foo(){ try{ return('returned') } finally { console.log('finally') } } console.log(foo()) // finally // returned
finally
中抛出异常,函数会终值,若是以前 try
中已经 return 了返回值,则返回值会被丢弃;finally
中的 return 会覆盖 try
和 catch
中 return 的返回值;finally
中若是没有 return,则会返回前面 return 的返回值;switch
中的 case
执行的匹配是 ===
严格相等的,也就是说若是不是 true,是真值也是不经过的:
switch(true) { case ('hello' || 10): console.log('world') // 不会执行 break; default: console.log('emmm') } // emmm
因此这里的字符串即便是真值,也是不被匹配,因此能够经过强制表达式返回 Boolean 值,好比 !!('hell0' || 10)
default
是可选的,无需放在最后一个,且并不是必不可少:
switch(10){ case 1: case 2: default: console.log('hello') case 3: console.log(3) break; case 4: console.log(4) } // hello // 3
上面这个例子的逻辑是:首先找匹配的 case,没找到则运行 default
,由于其中没有 break,因此继续执行 case 3
中的代码,而后 break;
因为浏览器历史遗留问题,在建立带有 id
属性的 DOM 元素的时候也会建立同名的全局变量:
<div id='foo'><div> <scripts> console.log(foo) // 打印出DOM元素 </scripts>
因此说 HTML 中尽可能少用 id 属性...
某些浏览器的 console.log
并不会把传入的内容当即输出,缘由是在许多程序(不仅是JS)中,I/O 是很是低速的阻塞部分,因此,从页面UI的角度来讲,浏览器在后台异步处理控制台 I/O 可以提升性能,这时用户可能根本意识不到其发生。
var a = { b: 1 } console.log(a) a.b++
这时候控制台看到的是 a 对象的快照 {b:1}
,然而点开看详情的话是 {b:2}
;这段代码在运行的时候,浏览器可能会认为须要把控制台 I/O 延迟到后台,这种状况下,等到浏览器控制台输出对象内容时,a.b++
可能已经运行,所以会在点开的时候显示 {b:2}
,这是 I/O 的异步化形成的。
若是遇到这种状况:
JSON.stringify
;若是 Promise 状态一直未改变,怎么获得通知呢,这里可使用 Promise.race
竞态,若是在设置时间内还未返回,那么 Promise 将会被 reject
;
function timeoutPromise(delay) { return new Promise((resolve, reject) => { setTimeout(() => { reject('Timeout!') }, delay) }) } Promise.race([foo(), timeoutPromise(3000)]) .then(() => console.log('Promise 及时完成')) .catch(() => console.log('Promise 超时了'))
function* foo(x) { return x * (yield 'hello') } const it = foo(6) let res = it.next() res.value // hello res = it.next(7) res.value // 42
能够看到第一个 next
并无传参,由于只有暂停的 yield
才能接受这样一个经过 next
传递的参,而在生成器刚生成尚未 next()
这时候尚未暂停的 yield
来接受这样一个值,因此会默默丢弃传递给第一个 next
的任何参数。
function* foo() { const r1 = yield request('http://some.url.1') const r2 = yield request('http://some.url.2') }
这种方式的两个请求是串行的,yield
只是代码中一个单独的暂停点,不能同时在两个点上暂停,若是但愿并行的发送,那么考虑:
function* foo() { const p1 = request('http://some.url.1') const p2 = request('http://some.url.2') const r1 = yield p1 const r2 = yield p2 }
PS:欢迎你们关注个人公众号【前端下午茶】,一块儿加油吧~
另外能够加入「前端下午茶交流群」微信群,长按识别下面二维码便可加我好友,备注加群,我拉你入群~