本書屬於基礎類書籍,會有比較多的基礎知識,因此這裏僅記錄日常不怎麼容易注意到的知識點,不會全記,供你們和本身翻閱;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:歡迎你們關注個人公衆號【前端下午茶】,一塊兒加油吧~
另外能夠加入「前端下午茶交流羣」微信羣,長按識別下面二維碼便可加我好友,備註加羣,我拉你入羣~