嗯,小白的進擊之路,繼續來補充了... 又看了一些坑,本身第一次疏忽作錯的,仍是用筆記下來,共同進步html
恩,面試系列和排坑會在github更新哦,一塊兒準備秋招的小夥伴路過能夠star下,一塊兒進步O(∩_∩)O~: 傳送門git
請問如下輸出是什麼github
var arr1 = "john".split('');
var arr2 = arr1.reverse();
var arr3 = "jones".split('');
arr2.push(arr3);
console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1));
console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));
複製代碼
答案:面試
"array 1: length=5 last=j,o,n,e,s"
"array 2: length=5 last=j,o,n,e,s"
複製代碼
是的,發現兩個輸出同樣,先說這道題的核心,再好好想一想吧編程
var arr1 = arr2
賦值時,只是淺拷貝,拿到了arr2
的引用,這樣帶來的問題就是,修改arr1
的時候arr2
也會收到影響。arr1.push(arr2)
,這就是爲何有一個函數叫concat
,push
會直接把整個數組push進去,而不會分開搞 搞清楚以上兩點,這個題基本上就解開了。如下程序輸出是什麼?數組
console.log(1 + "2" + "2");
console.log(1 + +"2" + "2");
console.log(1 + -"1" + "2");
console.log(+"1" + "1" + "2");
console.log( "A" - "B" + "2");
console.log( "A" - "B" + 2);
複製代碼
答案:bash
"122"
"32"
"02"
"112"
"NaN2"
NaN
複製代碼
嗯,核心是如下幾點,本身再細細思考閉包
-
+
會隱式轉換爲Number
類型+
做爲運算符出如今String
類型前時,會認爲須要字符串拼接,所以會隱式轉換爲String
Number
包含一個特殊的類型NaN,當對非數字進行Number轉換時,會變爲這個。第一題: 第二條,認爲須要字符串拼接 1被轉換爲1
,答案122
第二題: 注意到第二個2
前面的+
號,是符合第一條的,所以第二個2
被轉換爲Number類型,答案爲32
第三題: 同理,答案02
第五題: 運用(1)(3),顯然是NaN2
,第六題同理異步
下面的代碼將會形成棧溢出,請問如何優化,不改變原有邏輯函數
var list = readHugeList();
var nextListItem = function() {
var item = list.pop();
if (item) {
// process the list item...
nextListItem();
}
};
複製代碼
答案:
var nextListItem = function() {
var item = list.pop();
if (item) {
// process the list item...
setTimeout(nextListItem,0}
};
複製代碼
首先必須搞清楚,堆棧溢出的緣由。
在JS中,不當心的操做或者編程習慣,很容易形成堆棧溢出,特別是進行回調或者循環的時候。 引用如下來講明溢出的緣由:
緣由是每次執行代碼時,都會分配必定尺寸的棧空間(Windows系統中爲1M),每次方法調用時都會在棧裏儲存必定信息(如參數、局部變量、返回值等等),這些信息再少也會佔用必定空間,成千上萬個此類空間累積起來,天然就超過線程的棧空間了。那麼如何解決此類問題?
這裏介紹兩個思路解決此問題:
顯然,這裏就是使用的第一種方法,閉包。爲何使用setTimeout就能夠解決問題?咱們看下與沒用以前的差異。若是沒有使用setTimeout,那麼函數將在大數據前不斷的回調,直到最後走到重點,最初的函數才運行結束,釋放內存。 可是若是使用了setTimeout
,咱們知道它是異步的,即便設置了時間爲0,它也容許先執行下面的內容,能夠釋放堆棧,從而避免堆棧溢出的問題。 換言之,加了setTimeout
,nextListItem函數被壓入事件隊列,函數能夠退出,所以每次會清空調用堆棧。
閉包 也是同樣的道理,由於這道題要求不修改原有邏輯,第一種是最合適的答案,固然用閉包避免的方法就是返回出來一個函數
var nextListItem = function() {
var item = list.pop();
if (item) {
// process the list item...
return nextListItem()
}
};
複製代碼
固然,這樣作會改變函數的調用方式,咱們就須要不斷的調用 nextListItem()()()
爲了處理這個辦法,能夠對其進行進一步的封裝
var nextListItem = function() {
var item = list.pop();
if (item) {
// process the list item...
return function() {
return nextListItem()
}
}
};
function autoRun(fun) {
var value = nextListItem();
while(typeof value === 'function') {
value = nextListItem()
}
return
}
複製代碼
這樣,就解決堆棧溢出的問題。 這裏閉包的思路來源與堆棧溢出解決方案
下面函數的輸出是什麼?
var a={},
b={key:'b'},
c={key:'c'};
a[b]=123;
a[c]=456;
console.log(a[b]);
複製代碼
答案: 輸出是這樣的456
,不是123
,至少我有有點之外...
緣由是什麼呢? 這裏瞭解ES6新的數據類型map的應該就會意識到了,沒錯,對象的key值是隻容許String
類型的,這也是爲何引入了map數據類型了。 好了,那若是把一個對象做爲key值,就會調用toString
方法了。
Object.prototype.toString(obj)
會獲得什麼呢?沒錯`[object Object]。 那因此
a[b] ==> a["[object Object"] = 123;
a[b] ==> a["[object Object"] = 456;
複製代碼
答案,顯而易見
請作一個迴文判斷的函數,判斷是不是迴文
答案: 這是一個很簡單、很常規的方法。鏈表是最好的判斷迴文的方法,固然得益於JS數組的靈活方法,能夠更容易實現。
這裏主要考慮了一個健壯性的問題,多了一個正則來檢測:
function check(str) {
str = str.replace(/\W/g,'').toLowerCase();
return str === str.split('').reverse().join()
}
複製代碼