又到年尾了,各位小夥伴的心可能又蠢蠢欲動了。。。 得不到的永遠在騷動,被偏愛的都有恃無恐。。。
作為一個前端菜鳥的我,面試經驗和工作經驗並不豐富,但大大小小也面試過不少網際網路聖地,今天就講講筆者今年初面試鵝廠的經驗,希望對大家有所幫助!後面的答案為自行整理,如有疏漏,歡迎指正!
先說整體情況
適用範圍: 一到兩年的菜鳥前端開發工程師
筆者情況: 筆者一共面試了好幾輪技術面,最終結果技術面通過。
筆者感言: 可能是鵝廠大佬感覺我的經驗不豐富的原因,感覺面試的大部分問題都是以基礎為主。個人感覺大廠還是非常重視基礎的,特別是對工作經驗尚淺或者是校招生而言。所以
重視基礎和原理
重視基礎和原理
重視基礎和原理
正文走起來
以下,筆者會結合面試官問的問題一一道來...
一面——那是一個電話
騰訊面試官(小騰):你好,我是騰訊面試官,巴拉巴拉......先自我介紹一下(聲音特別溫柔?)!
筆者:我...
小騰:那我們就簡單的聊一下一些基礎的前端知識!
。。。。。。
這通面試電話,面試官主要問了我4個前端相關問題。
1.知道什麼是事件委託嗎?
2.對Promise瞭解嗎?
3.window的onload事件和domcontentloaded誰先誰後?
4.你之前遇到過跨域問題嗎?是怎麼解決的。
眾人皆知,不以結婚為目的的戀愛都是耍流氓,額,不,跑題了?。。。不給答案的面試題都是來騙點選量的?!!!由於這些問題實在過於簡單,但是涉及面又挺廣的,還請大家自行百度(千萬不要因為這個不給我贊,你的贊是寶寶持續分享的動力QAQ)。
二面——QQ遠端面
啊呀,羅裡吧嗦的,老太婆的裹腳布...,我寫到這裡,被主管劈頭蓋臉就是一頓!現在的年輕人時間寶貴,喜歡乾貨,不喜歡你這磨磨唧唧的!如此,只能乾貨先行了(大家如果喜歡我的行文風格,就點個贊,或者評論一下唄,筆者特別想懟一下那個主管)!
乾貨如下,答案為自己整理,如果有誤,歡迎指出!
一.有一個類如下:
function Person(name) {
this.name = name
}
let p = new Person('Tom');
複製程式碼
1. p.__proto__
等於什麼?
答案: Person.prototype
2. Person.__proto__
等於什麼?
答案: Function.prototype
解析:
1,2兩問其實問的是同一個問題,都是考察原型鏈相關的知識,我們只需要記住一句話就可以迎刃而解。例項的__proto__屬性(原型)等於其建構函式的prototype屬性。例項p的建構函式為Person,而Person的建構函式為Function,結果就一目瞭然了。
觸類旁通
var foo = {},
F = function(){};
Object.prototype.a = 'value a';
Function.prototype.b = 'value b';
console.log(foo.a)
console.log(foo.b)
console.log(F.a)
console.log(F.b)
複製程式碼
這裡就不給答案了,大家自己分析一下,然後再去控制檯執行一下吧!冬天到了,動動手,暖一暖,有木有覺得筆者還是相當的貼心的!!!
3. 若將題幹改為
function Person(name) {
this.name = name
return name;
}
let p = new Person('Tom');
複製程式碼
例項化Person過程中,Person返回什麼(或者p等於什麼)?
答案:
{name: 'Tom'}
複製程式碼
4. 若將題幹改為
function Person(name) {
this.name = name
return {}
}
let p = new Person('Tom');
複製程式碼
例項化Person過程中,Person返回什麼(或者p等於什麼)?
答案:
{}
複製程式碼
解析
建構函式不需要顯示的返回值。使用new來建立物件(呼叫建構函式)時,如果return的是非物件(數字、字串、布林型別等)會忽而略返回值;如果return的是物件,則返回該物件(注:若return null也會忽略返回值)。
5. typeof和instanceof的區別
答案:
在 JavaScript 中,判斷一個變數的型別嚐嚐會用 typeof 運算子,在使用 typeof 運算子時採用引用型別儲存值會出現一個問題,無論引用的是什麼型別的物件,它都返回 “object”。
instanceof 運算子用來測試一個物件在其原型鏈中是否存在一個建構函式的 prototype 屬性。 語法:object instanceof constructor 引數:object(要檢測的物件.)constructor(某個建構函式) 描述:instanceof 運算子用來檢測 constructor.prototype 是否存在於引數 object 的原型鏈上。
答案是我整理後的,可能覺得我回答的並不準確,面試官又舉了一個例子給我。
6. 如果Student inherit from Person(Student類繼承Person,需是基於原型的繼承),let s = new Student('Lily'),那麼s instanceof Person返回什麼?
function Person (name) {
this.name = name;
}
function Student () {
}
Student.prototype = Person.prototype;
Student.prototype.constructor = Student;
let s = new Student('Tom');
console.log(s instanceof Person); // 返回 true
複製程式碼
答案: true
7. new和instanceof的內部機制
答案
- 建立一個新物件,同時繼承物件類的原型,即Person.prototype;
- 執行物件類的建構函式,同時該例項的屬性和方法被this所引用,即this指向新構造的例項;
- 如果建構函式return了一個新的“物件”,那麼這個物件就會取代整個new出來的結果。如果建構函式沒有return物件,那麼就會返回步驟1所建立的物件,即隱式返回this。(一般情況下建構函式不會返回任何值,不過在一些特殊情況下,如果使用者想覆蓋這個值,可以選擇返回一個普通的物件來覆蓋。)
用程式碼來闡述
// let p = new Person()
let p = (function () {
let obj = {};
obj.__proto__ = Person.prototype;
// 其他賦值語句...
return obj;
})();
複製程式碼
下面通過程式碼闡述instanceof的內部機制,假設現在有 x instanceof y 一條語句,則其內部實際做了如下判斷:
while(x.__proto__!==null) {
if(x.__proto__===y.prototype) {
return true;
}
x.__proto__ = x.__proto__.proto__;
}
if(x.__proto__==null) {return false;}
複製程式碼
x會一直沿著隱式原型鏈__proto__向上查詢直到x.__proto__.__proto__......===y.prototype
為止,如果找到則返回true,也就是x為y的一個例項。否則返回false,x不是y的例項。
觸類旁通
function F() {}
function O() {}
O.prototype = new F();
var obj = new O();
console.log(obj instanceof O); // true
console.log(obj instanceof F); // true
console.log(obj.__proto__ === O.prototype); // true
console.log(obj.__proto__.__proto__ === F.prototype); // true
複製程式碼
根據new 的內部機制改寫上面程式碼
function F() {}
function O() {}
var obj = (function () {
var obj1 = {};
obj1.__proto__ = F.prototype; // new F();
O.prototype = obj1; // O.prototype = new F();
obj.__proto__ = O.prototype; // new O();
obj.__proto__ = obj1;
return obj;
})();
複製程式碼
結合instanceof內部機制很容易得出正確答案。
如果稍微調整一下程式碼順序,結果將迥然不同
function F() {}
function O() {}
var obj = new O();
O.prototype = new F();
console.log(obj instanceof O); // false
console.log(obj instanceof F); // false
console.log(obj.__proto__ === O.prototype); // false
console.log(obj.__proto__.__proto__ === F.prototype); // false
複製程式碼
具體原因,請讀者自行分析,如果還是有疑問,可以在評論區提出!
其實上面很多問題都是考察原型鏈相關的知識,這裡給出一張必須理解的原型鏈圖,原諒我盜了一張圖。
問到這裡我的腦袋已經有點漿糊了,原諒我太菜了!!
8.下面程式碼輸出什麼?
for(var i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i)
}, 0)
}
複製程式碼
答案: 10個10
若要輸出從0到9,怎麼辦?
答案: 將var改為let,或者使用閉包。
// 使用閉包
for(var i = 0; i < 10; i++) {
(function (i) {
setTimeout(() => {
console.log(i)
}, 0);
})(i);
}
複製程式碼
9. 剛剛我們用到了箭頭函式,說一下箭頭函式This指向問題?
答案: 預設指向在定義它時,它所處的物件,而不是執行時的物件,定義它的時候,可能環境是window(即繼承父級的this)。
如果對This還有不清楚的地方,可以參考我的另一篇文章徹底理解JavaScript中的this。
10. for...in迭代和for...of有什麼區別?
11.說一下你對generator的瞭解?
答案: 建議大家檢視阮一峰老師的generator相關章節
12.使用過flex佈局嗎?flex-grow和flex-shrink屬性有什麼用?
答案: flex-grow:專案的放大比例,預設為0,即如果存在剩餘空間,也不放大。flex-shrink:專案的縮小比例,預設為1,即如果空間不足,該專案將縮小。
想徹底理解flex,可以檢視阮一峰老師的Flex佈局教程:語法篇
13. 說一下macrotask 和 microtask?並說出下面程式碼的執行結果。
console.log('a');
setTimeout(() => {
console.log('b');
}, 0);
console.log('c');
Promise.resolve().then(() => {
console.log('d');
})
.then(() => {
console.log('e');
});
console.log('f');
複製程式碼
答案: 輸出結果為 acfdeb,而關於macrotask和microtask可以繼續留意筆者後篇文章,亦可自行搜尋。不過可以看一下盜的一張圖。
14. Http請求中的keep-alive有了解嗎。
答案:
在http早期,每個http請求都要求開啟一個tpc socket連線,並且使用一次之後就斷開這個tcp連線。 使用keep-alive可以改善這種狀態,即在一次TCP連線中可以持續傳送多份資料而不會斷開連線。通過使用keep-alive機制,可以減少tcp連線建立次數,也意味著可以減少TIME_WAIT狀態連線,以此提高效能和提高httpd伺服器的吞吐率(更少的tcp連線意味著更少的系統核心呼叫,socket的accept()和close()呼叫)。 但是,keep-alive並不是免費的午餐,長時間的tcp連線容易導致系統資源無效佔用。配置不當的keep-alive,有時比重複利用連線帶來的損失還更大。所以,正確地設定keep-alive timeout時間非常重要。
15. React中的controlled component 和 uncontrolled component區別(受控元件和不受控元件)。
16. 瞭解過react-router內部實現機制嗎?
**答案:**請看這篇文章react-router的實現原理
17.陣列扁平化處理:實現一個flatten方法,使得輸入一個陣列,該陣列裡面的元素也可以是陣列,該方法會輸出一個扁平化的陣列。
// Example
let givenArr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];
let outputArr = [1,2,2,3,4,5,5,6,7,8,9,11,12,12,13,14,10]
// 實現flatten方法使得
flatten(givenArr)——>outputArr
複製程式碼
年輕的我是用遞迴實現的QAQ,我的答案
function flatten(arr){
var res = [];
for(var i=0;i<arr.length;i++){
if(Array.isArray(arr[i])){
res = res.concat(flatten(arr[i]));
}else{
res.push(arr[i]);
}
}
return res;
}
複製程式碼
其實你還可以這樣
function flatten(arr){
return arr.reduce(function(prev,item){
return prev.concat(Array.isArray(item)?flatten(item):item);
},[]);
}
複製程式碼
還可以使用ES6擴充運算子
function flatten(arr){
while(arr.some(item=>Array.isArray(item)){
arr = [].concat(...arr);
}
return arr;
}
複製程式碼
18.如果在17問的前提下,要做去重和排序處理又該怎麼做(不用給出具體程式碼)。
**答案:**最好封裝一個陣列方法的類,該類包含flatten(扁平化)、sort(排序)和unique(去重)等方法。
二面就這樣過去了,懷著忐忑的心情等待結果中,文章有點長了,欲知後面的面試題,請聽下回分解!!!
@Author: Even