作者:倔強(qiáng)的石頭
https://juejin.im/post/5c19c1b6e51d451d1e06c163(點(diǎn)擊閱讀原文查看)
引言
又到年尾了,各位小伙伴的心可能又蠢蠢欲動(dòng)了峭弟。附鸽。脱拼。
得不到的永遠(yuǎn)在騷動(dòng)瞒瘸,被偏愛的都有恃無恐。熄浓。情臭。
作為一個(gè)前端菜鳥的我,面試經(jīng)驗(yàn)和工作經(jīng)驗(yàn)并不豐富赌蔑,但大大小小也面試過不少互聯(lián)網(wǎng)圣地俯在,今天就講講筆者今年初面試鵝廠的經(jīng)驗(yàn),希望對(duì)大家有所幫助娃惯!后面的答案為自行整理跷乐,如有疏漏,歡迎指正趾浅!
先說整體情況
適用范圍: 一到兩年的菜鳥前端開發(fā)工程師
筆者情況: 筆者一共面試了好幾輪技術(shù)面愕提,最終結(jié)果技術(shù)面通過。
筆者感言: 可能是鵝廠大佬感覺我的經(jīng)驗(yàn)不豐富的原因皿哨,感覺面試的大部分問題都是以基礎(chǔ)為主浅侨。個(gè)人感覺大廠還是非常重視基礎(chǔ)的,特別是對(duì)工作經(jīng)驗(yàn)尚淺或者是校招生而言证膨。所以
重視基礎(chǔ)和原理
重視基礎(chǔ)和原理
重視基礎(chǔ)和原理
正文走起來
以下如输,筆者會(huì)結(jié)合面試官問的問題一一道來…
一面——那是一個(gè)電話
騰訊面試官(小騰):你好,我是騰訊面試官,巴拉巴拉……先自我介紹一下(聲音特別溫柔??)不见!
筆者:我…
小騰:那我們就簡(jiǎn)單的聊一下一些基礎(chǔ)的前端知識(shí)澳化!
。稳吮。肆捕。。盖高。慎陵。
這通面試電話,面試官主要問了我4個(gè)前端相關(guān)問題喻奥。
1.知道什么是事件委托嗎席纽?
2.對(duì)Promise了解嗎?
3.window的onload事件和domcontentloaded誰先誰后撞蚕?
4.你之前遇到過跨域問題嗎润梯?是怎么解決的。
眾人皆知甥厦,不以結(jié)婚為目的的戀愛都是耍流氓纺铭,額,不刀疙,跑題了??舶赔。。谦秧。不給答案的面試題都是來騙點(diǎn)擊量的??>鼓伞!疚鲤!由于這些問題實(shí)在過于簡(jiǎn)單锥累,但是涉及面又挺廣的,還請(qǐng)大家自行百度(千萬不要因?yàn)檫@個(gè)不給我贊集歇,你的贊是寶寶持續(xù)分享的動(dòng)力QAQ)桶略。
二面——QQ遠(yuǎn)程面
啊呀,羅里吧嗦的诲宇,老太婆的裹腳布…际歼,我寫到這里,被主管劈頭蓋臉就是一頓焕窝!現(xiàn)在的年輕人時(shí)間寶貴蹬挺,喜歡干貨,不喜歡你這磨磨唧唧的它掂!如此巴帮,只能干貨先行了(大家如果喜歡我的行文風(fēng)格溯泣,就點(diǎn)個(gè)贊,或者評(píng)論一下唄榕茧,筆者特別想懟一下那個(gè)主管)垃沦!
干貨如下,答案為自己整理用押,如果有誤肢簿,歡迎指出!
一.有一個(gè)類如下:
function Person(name) {
this.name = name
}
let p = new Person('Tom');
1. p.__proto__
等于什么蜻拨?
答案:
Person.prototype
-
Person.__proto__
等于什么池充?
答案:
Function.prototype
解析:
1,2兩問其實(shí)問的是同一個(gè)問題缎讼,都是考察原型鏈相關(guān)的知識(shí)收夸,我們只需要記住一句話就可以迎刃而解湾碎。實(shí)例的proto屬性(原型)等于其構(gòu)造函數(shù)的prototype屬性辕羽。實(shí)例p的構(gòu)造函數(shù)為Person畔塔,而Person的構(gòu)造函數(shù)為Function摄职,結(jié)果就一目了然了。
觸類旁通
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)
這里就不給答案了拄显,大家自己分析一下召烂,然后再去控制臺(tái)運(yùn)行一下吧贸街!冬天到了舰讹,動(dòng)動(dòng)手茅姜,暖一暖,有木有覺得筆者還是相當(dāng)?shù)馁N心的6宓印P僬觥!
3. 若將題干改為
function Person(name) {
this.name = name return name;
}
let p = new Person('Tom');
實(shí)例化Person過程中桶错,Person返回什么(或者p等于什么)?
答案:
{name: 'Tom'}
4. 若將題干改為
function Person(name) {
this.name = name return {}
}
let p = new Person('Tom');
實(shí)例化Person過程中胀蛮,Person返回什么(或者p等于什么)院刁?
答案:
{}
解析
構(gòu)造函數(shù)不需要顯示的返回值。使用new來創(chuàng)建對(duì)象(調(diào)用構(gòu)造函數(shù))時(shí)粪狼,如果return的是非對(duì)象(數(shù)字退腥、字符串、布爾類型等)會(huì)忽而略返回值;如果return的是對(duì)象再榄,則返回該對(duì)象(注:若return null也會(huì)忽略返回值)狡刘。
5. typeof和instanceof的區(qū)別
答案:
在 JavaScript 中,判斷一個(gè)變量的類型嘗嘗會(huì)用 typeof 運(yùn)算符困鸥,在使用 typeof 運(yùn)算符時(shí)采用引用類型存儲(chǔ)值會(huì)出現(xiàn)一個(gè)問題嗅蔬,無論引用的是什么類型的對(duì)象剑按,它都返回 “object”。
instanceof 運(yùn)算符用來測(cè)試一個(gè)對(duì)象在其原型鏈中是否存在一個(gè)構(gòu)造函數(shù)的 prototype 屬性澜术。
語法:object instanceof constructor
參數(shù):object(要檢測(cè)的對(duì)象.)constructor(某個(gè)構(gòu)造函數(shù))
描述:instanceof 運(yùn)算符用來檢測(cè) constructor.prototype 是否存在于參數(shù) object 的原型鏈上艺蝴。
答案是我整理后的,可能覺得我回答的并不準(zhǔn)確鸟废,面試官又舉了一個(gè)例子給我猜敢。
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的內(nèi)部機(jī)制
答案
- 創(chuàng)建一個(gè)新對(duì)象添寺,同時(shí)繼承對(duì)象類的原型撇叁,即Person.prototype;
- 執(zhí)行對(duì)象類的構(gòu)造函數(shù)畦贸,同時(shí)該實(shí)例的屬性和方法被this所引用陨闹,即this指向新構(gòu)造的實(shí)例;
- 如果構(gòu)造函數(shù)return了一個(gè)新的“對(duì)象”薄坏,那么這個(gè)對(duì)象就會(huì)取代整個(gè)new出來的結(jié)果趋厉。如果構(gòu)造函數(shù)沒有return對(duì)象,那么就會(huì)返回步驟1所創(chuàng)建的對(duì)象胶坠,即隱式返回this君账。(一般情況下構(gòu)造函數(shù)不會(huì)返回任何值,不過在一些特殊情況下沈善,如果用戶想覆蓋這個(gè)值乡数,可以選擇返回一個(gè)普通的對(duì)象來覆蓋。)
用代碼來闡述
// let p = new Person();
let p = (function () {
let obj = {};
obj.__proto__ = Person.prototype;
// 其他賦值語句...
return obj;
})();
下面通過代碼闡述instanceof的內(nèi)部機(jī)制闻牡,假設(shè)現(xiàn)在有 x instanceof y 一條語句净赴,則其內(nèi)部實(shí)際做了如下判斷:
while(x.__proto__!==null) {
if(x.__proto__===y.prototype) {
return true;
break;
}
x.__proto__ = x.__proto__.proto__;
}
if(x.__proto__==null) {
return false;
}
x會(huì)一直沿著隱式原型鏈proto向上查找直到x.__proto__.__proto__......===y.prototype
為止,如果找到則返回true罩润,也就是x為y的一個(gè)實(shí)例玖翅。否則返回false,x不是y的實(shí)例割以。
觸類旁通
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
根據(jù)new 的內(nèi)部機(jī)制改寫上面代碼
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;
})
結(jié)合instanceof內(nèi)部機(jī)制很容易得出正確答案金度。
如果稍微調(diào)整一下代碼順序,結(jié)果將迥然不同
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
具體原因严沥,請(qǐng)讀者自行分析猜极,如果還是有疑問,可以在評(píng)論區(qū)提出消玄!
其實(shí)上面很多問題都是考察原型鏈相關(guān)的知識(shí)跟伏,這里給出一張必須理解的原型鏈圖丢胚,原諒我盜了一張圖。
問到這里我的腦袋已經(jīng)有點(diǎn)漿糊了酬姆,原諒我太菜了J茸馈!
8.下面代碼輸出什么辞色?
for(var i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i)
}, 0)
}
答案: 10個(gè)10
若要輸出從0到9骨宠,怎么辦?
答案:
將var改為let相满,或者使用閉包层亿。
// 使用閉包
for(var i = 0; i < 10; i++) {
(function (i) {
setTimeout(() => {
console.log(i)
}, 0);
})(i);
}
9. 剛剛我們用到了箭頭函數(shù),說一下箭頭函數(shù)This指向問題立美?
答案:
默認(rèn)指向在定義它時(shí),它所處的對(duì)象,而不是執(zhí)行時(shí)的對(duì)象,定義它的時(shí)候,可能環(huán)境是window(即繼承父級(jí)的this)匿又。
如果對(duì)This還有不清楚的地方,可以參考我的另一篇文章徹底理解JavaScript中的this建蹄。
10. for…in迭代和for…of有什么區(qū)別碌更?
答案:for…in和for…of的區(qū)別
11.說一下你對(duì)generator的了解?
答案: 建議大家查看阮一峰老師的generator相關(guān)章節(jié)
12.使用過flex布局嗎洞慎?flex-grow和flex-shrink屬性有什么用痛单?
答案: flex-grow:項(xiàng)目的放大比例,默認(rèn)為0劲腿,即如果存在剩余空間旭绒,也不放大。flex-shrink:項(xiàng)目的縮小比例焦人,默認(rèn)為1挥吵,即如果空間不足,該項(xiàng)目將縮小花椭。
想徹底理解flex忽匈,可以查看阮一峰老師的Flex布局教程:語法篇
13. 說一下macrotask 和 microtask?并說出下面代碼的運(yùn)行結(jié)果个从。
console.log('a');
setTimeout(() => {
console.log('b');
}, 0);
console.log('c');
Promise.resolve().then(() => {
console.log('d');
}).then(() => {
console.log('e');
});
console.log('f');
答案: 輸出結(jié)果為 acfdeb脉幢,而關(guān)于macrotask和microtask可以繼續(xù)留意筆者后篇文章,亦可自行搜索嗦锐。不過可以看一下盜的一張圖。
14. Http請(qǐng)求中的keep-alive有了解嗎沪曙。
答案:
在http早期奕污,每個(gè)http請(qǐng)求都要求打開一個(gè)tpc socket連接,并且使用一次之后就斷開這個(gè)tcp連接液走。
使用keep-alive可以改善這種狀態(tài)碳默,即在一次TCP連接中可以持續(xù)發(fā)送多份數(shù)據(jù)而不會(huì)斷開連接贾陷。通過使用keep-alive機(jī)制,可以減少tcp連接建立次數(shù)嘱根,也意味著可以減少TIME_WAIT狀態(tài)連接髓废,以此提高性能和提高h(yuǎn)ttpd服務(wù)器的吞吐率(更少的tcp連接意味著更少的系統(tǒng)內(nèi)核調(diào)用,socket的accept()和close()調(diào)用)。
但是该抒,keep-alive并不是免費(fèi)的午餐,長(zhǎng)時(shí)間的tcp連接容易導(dǎo)致系統(tǒng)資源無效占用慌洪。配置不當(dāng)?shù)膋eep-alive,有時(shí)比重復(fù)利用連接帶來的損失還更大凑保。所以冈爹,正確地設(shè)置keep-alive timeout時(shí)間非常重要。
15. React中的controlled component 和 uncontrolled component區(qū)別(受控組件和不受控組件)欧引。
答案: : 請(qǐng)查閱React官網(wǎng)受控組件频伤,非受控組件
16. 了解過react-router內(nèi)部實(shí)現(xiàn)機(jī)制嗎?
答案:請(qǐng)看這篇文章react-router的實(shí)現(xiàn)原理
17.數(shù)組扁平化處理:實(shí)現(xiàn)一個(gè)flatten方法芝此,使得輸入一個(gè)數(shù)組憋肖,該數(shù)組里面的元素也可以是數(shù)組,該方法會(huì)輸出一個(gè)扁平化的數(shù)組婚苹。
// 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]
// 實(shí)現(xiàn)flatten方法使得flatten(givenArr)——>outputArr
年輕的我是用遞歸實(shí)現(xiàn)的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;
}
其實(shí)你還可以這樣
function flatten(arr){
return arr.reduce(function(prev,item){
return prev.concat(Array.isArray(item)?flatten(item):item);
},[]);
}
還可以使用ES6拓展運(yùn)算符
function flatten(arr){
while(arr.some(item=>Array.isArray(item)){
arr = [].concat(...arr);
}
return arr;
}
18.如果在17問的前提下,要做去重和排序處理又該怎么做(不用給出具體代碼)租副。
答案:最好封裝一個(gè)數(shù)組方法的類坐慰,該類包含flatten(扁平化)、sort(排序)和unique(去重)等方法用僧。