本週發起了一個100天前端進階計劃,天天一個知識點,搞明白背後的原理,這是第一週的總結,請注意查收。前端
以面試題的形式看本身本週掌握了多少。git
// base.js let count = 0; setTimeout(() => { console.log("base.count", ++count); }, 500) module.exports.count = count; // commonjs.js const { count } = require('./base'); setTimeout(() => { console.log("count is" + count + 'in commonjs'); }, 1000) // base1.js let count = 0; setTimeout(() => { console.log("base.count", ++count); }, 500) exports const count = count; // es6.js import { count } from './base1'; setTimeout(() => { console.log("count is" + count + 'in es6'); }, 1000)
詳細分析請看 《require和import的區別》
console.log((function() { console.log(1); setTimeout(function() { console.log(2) }, 1000) setTimeout(function() { console.log(3) }, 0); setTimeout(function() { console.log(4) }, 0); console.log(5) })());
詳細分析請看 《setTimeout和requestAnimationFrame》
console.log((typeof null )); console.log((typeof [])); console.log((typeof Symbol())); console.log((typeof 123n) ); function foo() { console.log(111); }; console.log((typeof foo));
function *foo(x) { const y = 2 * (yield (x + 1)); const z = yield (y / 3); return (x + y + z); } const a = foo(5); console.log(a.next()); console.log(a.next()); console.log(a.next()); const b = foo(5); console.log(b.next()); console.log(b.next(12)); console.log(b.next(13));
{ value: 6, done: false } { value: NaN, done: false } { value: NaN, done: true } { value: 6, done: false } { value: 8, done: false } { value: 42, done: true }
先看使用Generator函數生成的迭代器a
:es6
5 + 1 = 6
;undefined
, 致使y
的值等於2*undefined
即(NaN
),除以 3
之後仍是NaN
,所以返回對象的value
屬性也等於NaN
。return (x + y + z)
,此時x
的值爲 5
, y
的值爲 NaN
, 因爲next方法沒有帶參數,上一個yield表達式返回值爲undefined
,致使z爲 undefined,返回對象的 value屬性等於5 + NaN + undefined
,即 NaN再來看看使用Generator函數生成的迭代器b
:github
5 + 1 = 6
;12
,因此上一個yield表達式返回值爲12
, 所以y
的值等於2*12
即(24
),除以 3
是8
,所以返回對象的value
屬性爲8
。return (x + y + z)
,此時x
的值爲 5
, y
的值爲 24
, 因爲next方法沒有帶參數13
,所以z爲13
,返回對象的 value屬性等於5 + 24 + 13
,即 42
詳細分析請看 Generator函數詳解》
let z = 1; function *foo() { const x = yield 2; z++; const y = yield (x * z); console.log(x, y, z); } const a = foo(); const b = foo(); let val1 = a.next().value; console.log(val1); let val2 = b.next().value; console.log(val2); val1 = a.next(val2 * 10).value; console.log(val1); val2 = b.next(val1 * 5).value; console.log(val2); a.next(val2 / 2); b.next(val1 / 4);
*foo()
的兩個實例同時啓用,兩個next()
分別從yield 2
語句獲得2
val2 * 10
也就是2 * 10
,發送到第一個生成器實例 a
, 由於x獲得的值20
。z
從1
增長到2
,而後 20 * 2
經過 yield
發出,將val1
設置爲40
val1 * 5
也就是 40 * 5
,發送到第二個生成器實例 b
,所以x獲得的值200
。z
再從 2
遞增到3
,而後 200*3
經過 yield
發出,將val2
設置爲 600
val2 / 2
也就是 600 / 2
發動到第一個生成器實例 a
, 所以 y獲得值 300
, 而後打印出 x y z
的值分別爲 20, 300, 3
。val1 / 4
也就是 40 / 4
, 發送到第二個生成器實例 b
, 所以 y
獲得的值10
, 而後打印出 x y z
的值分別爲 200, 10, 3
。詳細分析請看 《Generator函數》
詳細分析請看 《require和import的區別》
JavaScript有八種內置類型面試
除對象外,其餘統稱爲「基本類型」。算法
注意新增的symbol
和BigInt
typeof
原理: 不一樣的對象在底層都表示爲二進制,在Javascript中二進制前(低)三位存儲其類型信息。數組
typeof null 爲"object", 緣由是由於 不一樣的對象在底層都表示爲二進制,在Javascript中二進制前(低)三位都爲0的話會被判斷爲Object類型,null的二進制表示全爲0,天然前三位也是0,因此執行typeof時會返回"object"。瀏覽器
關鍵詞:JavaScript數據類型的相關底層機制
instanceof
的語法:緩存
object instanceof constructor // 等同於 constructor.prototype.isPrototypeOf(object)
instanceof
原理: 檢測 constructor.prototype
是否存在於參數 object的 原型鏈上。instanceof
查找的過程當中會遍歷object
的原型鏈,直到找到 constructor
的 prototype
,若是查找失敗,則會返回false
,告訴咱們,object
並不是是 constructor
的實例。微信
對象的Symbol.hasInstance
屬性,指向一個內部方法。當其餘對象使用instanceof
運算符,判斷是否爲該對象的實例時,會調用這個方法。好比,foo instanceof Foo
在語言內部,實際調用的是FooSymbol.hasInstance。
class MyClass { [Symbol.hasInstance](foo) { return foo instanceof Array; } } [1, 2, 3] instanceof new MyClass() // true
關鍵詞:instanceof 用法,原型鏈,
Symbol.hasInstance
。詳細分析請查看
《 typeof和instanceof原理》
setTimeout(function fn(){ console.log('我被調用了'); setTimeout(fn, 100); },100);
詳細分析請看 《setTimeout和requestAnimationFrame》
setTimeout(()=> {}, 0)
執行該語句時,是當即把當前定時器代碼推入事件隊列,當定時器在事件列表中知足設置的時間值時將傳入的函數加入任務隊列,以後的執行就交給任務隊列負責。可是若是此時任務隊列不爲空,則需等待,因此執行定時器內代碼的時間可能會大於設置的時間。
HTML5標準規定了setTimeout()的第二個參數的最小值(最短間隔)不得低於4毫秒。 當指定的時間低於該時間時,瀏覽器會用最小容許的時間做爲setTimeout的時間間隔,也就是說即便咱們把setTimeout的延遲時間設置爲0,實際上可能爲 4毫秒後才事件推入任務隊列。
詳細分析請看 《setTimeout和requestAnimationFrame》
requestAnimationFrame
是瀏覽器用於定時循環操做的一個接口,相似於setTimeout,主要用途是按幀對網頁進行重繪。requestIdleCallback()
經常使用來切割長任務,利用空閒時間執行,避免主線程長時間阻塞。詳細分析請看 《setTimeout和requestAnimationFrame》
for...of 不僅是用來遍歷數組的,只要有iterator
接口的數據結構均可以用它來遍歷。一個數據結構只要部署了Symbol.iterator
屬性,就被視爲具備 iterator
接口。iterator
的實現思想來源於 單向鏈表
。
關鍵詞:iterator
,Symbol.iterator
, 單向鏈表。詳細分析請看 《for...of原理解析》
function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? { value: array[nextIndex++], done: false } : { value: undefined, done: true }; } }; } const it = makeIterator(['a', 'b']); it.next() // { value: "a", done: false } it.next() // { value: "b", done: false } it.next() // { value: undefined, done: true }
暫停執行(yield)
和恢復執行(next)
函數體內外的數據交換
(next
返回值的value
,是向外輸出
數據,next
方法的參數
,是向內輸入
數據)和錯誤處理機制
(Generator 函數內部還能夠部署錯誤處理代碼,捕獲函數體外拋出的錯誤)更多請查看 Generator函數詳解》
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。
若是你最多隻容許完成一筆交易(即買入和賣出一支股票),設計一個算法來計算你所能獲取的最大利潤。
注意你不能在買入股票前賣出股票。
示例 1:
輸入: [7,1,5,3,6,4] 輸出: 5 解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。 注意利潤不能是 7-1 = 6, 由於賣出價格須要大於買入價格。
示例 2:
輸入: [7,6,4,3,1] 輸出: 0 解釋: 在這種狀況下, 沒有交易完成, 因此最大利潤爲 0。
答案: 買賣股票的最佳時機
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。
設計一個算法來計算你所能獲取的最大利潤。你能夠儘量地完成更多的交易(屢次買賣一支股票)。
注意:你不能同時參與多筆交易(你必須在再次購買前出售掉以前的股票)。
示例 1:
輸入: [7,1,5,3,6,4] 輸出: 7 解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 3 天(股票價格 = 5)的時候賣出, 這筆交易所能得到利潤 = 5-1 = 4 。 隨後,在第 4 天(股票價格 = 3)的時候買入,在第 5 天(股票價格 = 6)的時候賣出, 這筆交易所能得到利潤 = 6-3 = 3 。
示例 2:
輸入: [1,2,3,4,5] 輸出: 4 解釋: 在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能得到利潤 = 5-1 = 4 。 注意你不能在第 1 天和第 2 天接連購買股票,以後再將它們賣出。 由於這樣屬於同時參與了多筆交易,你必須在再次購買前出售掉以前的股票。
示例 3:
輸入: [7,6,4,3,1] 輸出: 0 解釋: 在這種狀況下, 沒有交易完成, 因此最大利潤爲 0。
答案: 《買賣股票的最佳時機》
將兩個有序鏈表合併爲一個新的有序鏈表並返回。新鏈表是經過拼接給定的兩個鏈表的全部節點組成的。
示例:
輸入:1->2->4, 1->3->4 輸出:1->1->2->3->4->4
答案:合併兩個有序鏈表
給定一個整數數組 nums ,找到一個具備最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
示例:
輸入: [-2,1,-3,4,-1,2,1,-5,4], 輸出: 6 解釋: 連續子數組 [4,-1,2,1] 的和最大,爲 6。
答案:最大子序和
從撲克牌中隨機抽5張牌,判斷是否是一個順子,即這5張牌是否是連續的。2~10爲數字自己,A爲1,J爲11,Q爲12,K爲13,而大、小王爲 0 ,能夠當作任意數字。A 不能視爲 14。
示例 1: 輸入: [1,2,3,4,5] 輸出: True 示例 2: 輸入: [0,0,1,2,5] 輸出: True
限制:
1.數組長度爲 5
2.數組的數取值爲 [0, 13] .
答案:撲克牌中的順子
給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。
示例 1:
輸入: "abcabcbb" 輸出: 3 解釋: 由於無重複字符的最長子串是 "abc",因此其長度爲 3。
示例 2:
輸入: "bbbbb" 輸出: 1 解釋: 由於無重複字符的最長子串是 "b",因此其長度爲 1。
示例 3:
輸入: "pwwkew" 輸出: 3 解釋: 由於無重複字符的最長子串是 "wke",因此其長度爲 3。請注意,你的答案必須是 子串 的長度,"pwke" 是一個子序列,不是子串。
答案:無重複字符的最長子串
最新發起了一個100天前端進階計劃,致力於弄明白每一個知識點背後的原理。這是第一週的總結,原本想直接粘貼一下原先的標題並附上原文連接。後來想仍是找幾道關於本週內容的一些面試題(大部分爲原文中的例子),方便檢測一下本身的掌握程度。一共20道,看看本身能得幾分。算法題作多要在半個小時以內寫出最優解,上面提供的答案並必定是最好的,若是有問題或者更好的解法歡迎你們留言指出。或者你最新碰到的相似的面試題,也能夠提供給我進行補充。
最近發起了一個100天前端進階計劃,主要是深挖每一個知識點背後的原理,歡迎關注 微信公衆號「牧碼的星星」,咱們一塊兒學習,打卡100天。