唉,我仍是前端小渣渣一個。javascript
是一家雲服務產品公司,面試流程也比較簡單,前端負責人拿了一塊白板和記號筆,心想一會要手寫代碼了。。。。前端
不過這種面試方式仍是不錯的。java
去以前覺得本身準備的差很少,其實準備的遠遠不夠充足啊。react
一開始通常會讓你進行一個簡單的自我介紹,我就主要說了一下上家公司的工做經歷,描述了一下我負責過的項目,每一個項目的業務功能,主要詳細介紹每一個項目用到的技術。面試
雖然我說了不少,可是過後以爲我在表達的時候,語言的條理性、邏輯性、準確性都不是很好,表達能力的強弱也是面試官比較看中的一部分,畢竟有可能之後和他共事交流工做內容,探討技術等,因此,自我介紹這一塊,以爲也挺重要的,自我介紹表明了面試官對你的第一印象,即使你面試不少次了,也說過不少次了,這方面仍是應該好好梳理下本身的語言。redux
接下來考察js了,面試官慢慢的拿起了他的小白板,個人內心默默的有點小緊張。。。。數組
考察方式也比較中規中矩,按照js裏的大類挨個考察。bash
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}複製代碼
「咦?。。。,上一次的面試不是也碰到了這個?」閉包
而後我淡定的說出了答案:框架
「setTimeout
函數會延遲執行,那麼等到執行console.log()
的時候,i
已經變成5了,因此最後會一次性打印出5個5;」
問:「那我要輸出0~4呢?」
「怎麼也有這個問題?是否是要問我有幾種改法。。。」
我直接說var
改爲let
就能夠了
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}複製代碼
或者加個閉包:
for (var i = 0; i < 5; i++) {
(function(i) {
setTimeout(function() {
console.log(i);
}, 1000);
})(i)
}
複製代碼
或者這樣:
for(var i = 1;i < 5;i++){
var a = function(){
var j = i;
setTimeout(function(){
console.log(j);
},1000)
}
a();
}複製代碼
這也是用了閉包的方法,其實就至關於把var化成了let效果同樣,這樣i的值一開始不會被默認綁定,每執行一次循環的時候都會給i賦予新值。
問:「若是去掉function
裏的 i
呢?」
「這樣其實對內存沒有保持引用, i 最後仍是5。」
因爲相似的面試題頻繁遇到,整理了一些相關的面試題:
好比這個:
for (var i = 0; i < 5; i++) {
setTimeout((function(i) {
console.log(i);
})(i), i * 1000);
}複製代碼
延時函數的第一個參數變成了一個當即執行函數,在這裏應該是一個undefined
,等價於:
setTimeout( undefined, … )
;
當即函數會立馬執行,因此是立馬就輸出0~4;
Promise考察:
setTimeout(function() {
console.log(1)}, 0);
new Promise(function executor(resolve) {
console.log(2);
for( var i=0 ; i<10000 ; i++ ) {
i == 9999 && resolve();
}
console.log(3);
}).then(function() {
console.log(4);
});
console.log(5);複製代碼
考察運行機制,首先Promise
是異步的,Promise
只有三中狀態,pending、fulfilled(成功)、rejected(失敗)
,後二者統稱爲resolve
(已定型),一旦狀態定下句就沒法再改變。
第一個延時函數首先會設置一個定時,在定時結束後傳遞這個函數將它放到任務隊列中去,所以一開始不會輸出1;
Promise
裏的函數會按順序執行,輸出2 3 ,Promise
裏的then
就是會異步執行,放到當前Promise
任務隊列的最後執行,而console.log(5)
是按順序執行的,因此先輸出5,再輸出4。Promise.then()
裏面的回調屬於 microtask, 會在當前 Event Loop 的最後執行, 而 SetTimeout
內的回調屬於 macrotask, 會在下一個 Event Loop 中執行
最後,纔會輸出1。
最後輸出: 2 3 5 4 1
先來個最簡單的
var obj = {
a: "1"
};
var obj2 = obj;
obj2.a = "2";
console.log(obj.a);複製代碼
「確定是輸出 2 啊」
ojb2只是對obj實例的一個引用,到最後仍是修改的obj的值。
this指針
name = "name of window";
function show() {
var name = "name in function show()";
alert(this.name);
}
show();複製代碼
這裏定義了一個全局變量 name
,這個變量是屬於 window
的,在 show
函數裏也聲明瞭一個name
變量。
this
的定義是指向調用當前函數的那個對象, show()
函數是在全局被調用的,因此this
應該指向的是當前 window
對象。
再看下一個:
var myObj = {
name: " my Object",
show: function() {
var name = "my Object in function";
alert(this.name);
},
};
myObj.show();複製代碼
此次,調用 myObj.show()
的對象是 myObj
, 因此就會輸出 my Object
先來個排序吧:
var arr = [ 2, 4, 50, 20, 3 ];複製代碼
冒泡排序:
var arr = [ 2, 4, 50, 20, 3 ];
for(var i = 0 ; i < arr.length-1; i ++){
for(var j = 0; j < arr.length-i; j++ ){
var ls;
if(arr[j] > arr[j+1]){
ls = arr[j];
arr[j] = arr[j+1]
arr[j+1] = ls
}
}
}
console.log(arr);複製代碼
其實我要開始想到的是用sort()
,可是sort
排出來的不是很穩定,他默認排序是根據字符串Unicode碼點。
還問我sort有幾個參數,第二個參數是什麼?
我當時沒想起來,後續整理出來吧!
可選參數是一個比較函數, compareFunction
,用來指定按某種順序進行排列的函數。若是省略,元素按照轉換爲的字符串的各個字符的Unicode位點進行排序。
compareFunction(a, b)
小於 0 ,那麼 a 會被排列到 b 以前;compareFunction(a, b)
等於 0 , a 和 b 的相對位置不變;compareFunction(a, b)
大於 0 , b 會被排列到 a 以前。compareFunction(a, b)
必須老是對相同的輸入返回相同的比較結果,不然排序的結果將是不肯定的。要比較數字而非字符串,比較函數能夠簡單的以 a 減 b,以下的函數將會將數組升序排列
function compareNumbers(a, b) {
return a - b;
}複製代碼
因此上邊那個排序就能夠簡單的寫成:
var arr = [ 2, 4, 50, 20, 3 ];arr.sort(function (a, b) {
return a - b;
});
console.log(arr);複製代碼
或者更簡潔一點:
var arr = [ 2, 4, 50, 20, 3 ];
arr.sort((a, b) => a -b );
console.log(arr);複製代碼
又給我改了一下,說怎麼用sort 來排序一個對象?
var obj = [
{ name: 'a', value: 21 },
{ name: 'b', value: 37 },
{ name: 'c', value: 45 },
{ name: 'd', value: -12 },
{ name: 'e' }
];複製代碼
應該是這樣:
obj.sort(function (a, b) {
return (a.value - b.value);
});複製代碼
零零碎碎的問了很多,其餘的記不太清了,都是一些知識性的東西,不羅列了。
而後問了一些react、 redux相關的技術原理,生命週期、單向數據流、虛擬DOM等等。。。
這些我回答的還好,由於工做每天用這個,也比較熟悉,js基礎類的一些題回答的不太好,我也知道我js基礎不紮實,再者,面試題看少了,雖然這些基礎的知識點在工做中用的很少,有的記不清楚的就google了,也不會影響開發進度,可是,即使react 用的再熟練,重中之重的js基礎!纔是最重要的,框架都是js寫的。
反思一下,以前工做中碰到了一些不會的或者生疏不經常使用的技術,google出來答案後直接就用上了,也沒有仔細的去研究其中的原理,知其然不知其因此然!
過後也沒有總結出來,下次再碰到這個技術點,可能又要google了。。。
不說廢話了!
alert(a);
a();
var a=3;
function a(){
alert(10)
}
alert(a);
a=6;
a();
複製代碼
果不其然,我本身看一遍的時候就分析錯了。
關鍵的一點就是:var 聲明的變量 和function生命的函數都會提早,只是提早到做用域開始的位置,但不會進行賦值操做;
function a(){alert(10)}
,就會看到這個函數。
a()
,執行函數,就是出現
alert(10)
var a=3;
因此
alert(a)
就是顯示
3
a
不是一個函數了,因此往下在執行到
a()
的時候, 報錯。
再來看:
alert(a);
a();
var a=3;
var a=function(){
alert(10)
}
alert(a);
a=6;
a();
複製代碼
區別是,函數此次用var聲明瞭,根據原理,他只是聲明被提早,但a 沒有被賦值爲一個函數,
因此,一開始alert(a) 是undefined
;
a() 報錯;
相似的題目:
var a=0;
function aa(){
alert(a);
var a=3;
}
aa();複製代碼
在aa函數裏面,有var a=3,那麼在aa做用域裏面,就是把a這個變量聲明提早,可是不會賦值,因此是undefined
;
var a=0;
function aa(a){
alert(a);
var a=3;
};
aa(5);
alert(a);
//5,0 複製代碼
在函數體內,參數a的優先級高於變量a ;
var a=0;
function aa(a){
alert(a);
a=3;
alert(a);
}
aa();
alert(a);
複製代碼
首先沒有傳參數進去,aa()
是 undefined
;
a=3,實際上修改的是形參a的值,並非全局變量a,往下alert(a)
也是形參a;
最後的alert(a)
; 是全局的a;
不說了!。。。
我要去刷面試題,繼續啃個人JavaScript 語言精粹了。