咱們在長期的面試過程當中,經歷了種種苦不堪言,不訴苦感受不過癮(我儘可能控制),而後主要聊聊常見JavaScript
面試題的解法,以及面試注意事項javascript
面試第一苦,面試官的土 - 有些面試官本身就很是不專業,詞不達意、不知所云,這類面試經常表現爲網上搜題,面試時照本宣科,只會比較候選人的答案最終的結果,自動忽略候選人對題目的看法以及解題思路。碰到這種面試官,你只有是個題霸,再加上眼緣夠才能順利入圍。苦!html
面試第二苦,候選人的虎 - 有些候選人的表現好像菜市場的大媽,表述永遠走「樸實無華」路線,譬如:說個iife
,他必定要說「就是那個小括號包裹,裏面寫一個函數,最後再來一對括號,函數裏面寫一堆閉包的寫法」, 注意,這裏面必定會說「裏面寫閉包」這句話,以彰顯專業性,卻不知從一開始就露怯了。苦!java
面試第三苦,雙方都在賭 - 面試官自說自話,候選人答非所問,場面一片歡愉,結果不言而喻!git
面試,是一個很是須要認真思考的事情,不管面試官仍是候選人,選什麼人、怎麼選;面什麼公司、什麼崗位、題目不會該如何做答?不思考胡說一通,那不苦纔有鬼!程序員
一般面試都是聊天、筆試,機試環節經常短缺。但捫心自問,咱們真的須要程序員熟背全部Javascript
API麼?咱們真的須要程序員熟背全部Web
API麼?咱們真的須要程序員瞬間給出「某某網站慢的徹底優化方案」麼?github
我在想,前兩問徹底能夠
缺乏上機測試會有什麼問題?(其實沒什麼大差錯),不過可能會損失一些「嘴笨」的實踐派幹活能手,他們信奉「能動手就別BB」,這類人一般在與面試官face 2 face
的「聊天」中不能討得面試官歡心,但他們真心能寫的一手好碼,惋惜沒機會展現,也是苦!算法
因而我以爲你們應該互相給對方一個機會,談談我本身用的一套機試題目fe-interview,以及做爲面試官但願瞭解的候選人關於Javascript
方面的能力的見解。segmentfault
如下是該機試題目的開始界面(retro風格),經過鍵盤光標上/下鍵選擇題目,按回車鍵確認選中數組
雖然寫了「算法考覈」,但其實沒什麼算法題,這也算是標題黨吧^^
確認選中後,會出現以下選擇器,候選人能夠再次上/下鍵選擇"查看題目描述"、「查看測試用例」、「檢驗答題結果」
"查看測試用例"的目的是幫助候選人,經過查看測試用例的代碼來改進本身的題目解答。
該測試工具須要本地安裝,詳情請看:安裝/使用手冊
簡單瞭解測試工具以後,咱們就能夠開始愉快的答題了
最後再來回顧一下機試目標:機試的目的不是爲了讓候選人在指定時間內完成一個完美無瑕的功能,那是高考!咱們期待的是經過不一樣的題目,考察候選人的基本功、編碼能力、思考方法。。。,經過這些綜合指標,判斷該候選人是否一個你指望的JavaScript
工程師
下面讓咱們一塊兒走上答題之路
題目很是簡單,完成一個能夠刪除數組指定下標對應元素的函數
答案:
var removeArray = function(arr, index) { arr.splice(index, 1); }; module.exports = removeArray;
真心沒什麼花哨的地方,這個題目不涉及任何高深的知識。旨在考察候選人對基礎API的熟練程度,關於
splice
你可能想知道更多
答案:
var isString = function(value) { return Object.prototype.toString.call(value) === '[object String]'; }; module.exports = isString;
這裏考察的重點是
new String('hello')
究竟是個什麼東西?至於我給的答案用了Object.prototype.toString
方法,我能夠負責任的告訴你,這個作法是有風險的,由於該方法的實現由平臺提供,意思是:不一樣的JavaScript
執行引擎實現可能不一樣,因此結果並不能保證。仍是那句話,結果不是最重要的,解題思路,看清本質最爲關鍵,也是最重要的能力。固然關於Object.prototype.toString
,你也可能想知道更多
這題可能對一些同窗來說有點過了,但相信我,個人測試用例並不變態,你徹底沒必要寫出一個「完美」的柯里化。只要按照我題目的思路,甚至打出來測試用例看看,就能實現這個題目了。
首先爲了普法,仍是先簡單介紹下什麼是「柯里化」,說白了柯里化也是一個函數。假設咱們有函數A
通過柯里化函數處理事後,A
就被賦予了一種可以被部分執行的能力!這話說的聽不懂了是吧?咱們來看個例子:
//假設咱們有個add函數,她接受兩個參數a和b;並返回兩者之和 var add = function(a, b){ return a + b; };
簡單吧?那麼問題來了,若是我如今只給了你一個參數a,另外一個參數我想過會兒再給你,怎麼辦?傳統思惟是那就過一會再調用
add
唄!這固然沒錯!可是憑藉柯里化,咱們有另一種思路使得如下成爲可能:
var add3 = add(3);//執行了一半 setTimeout(function(){ console.log(add3(5));//這裏拿到了另外一半參數5,再計算最終結果 }, 5000);
我這裏不會大篇幅講柯里化有多牛逼的好處,固然若是你有興趣,能夠看Why Curry Helps
答案:
var currying = function(func) { var len = func.length;//獲取一個函數形參的個數 var getCurry = function(params) { return function() { //參數拼接 var next = params.concat(Array.prototype.slice.call(arguments)); //持續接收的參數已經知足當初原始函數的形參個數,執行原始函數,返回結果 if (len - next.length <= 0) { return func.apply(this, next); } //不知足個數,將已經獲取的參數繼續遞歸 return getCurry(next); }; }; return getCurry([]); }; module.exports = currying;
如此簡單的題目,我想考察的依舊是
Array
的內置API,不記得沒關係,我是容許上網查的(誰沒有個記不住的時候)。但你要是玩出花來,譬若有人寫了幾十行的方法,這個我就有點懵了。
答案:
var duplicate = function(array) { return array.concat(array); }; module.exports = duplicate;
其實
concat
足矣。關於concat
,更多詳情
「淺拷貝」,顧名思義,對於引用類型的數據,只拷貝其引用,也就是題目中
copied[0].name = 'world';
以後,原先的value
也被改了。
答案:
var shallowCopy = function(value) { return Object.assign(new (Object.getPrototypeOf(value).constructor)(), value); }; module.exports = shallowCopy;
根據@Tommy Troy Lin的PR,對答案作出修正。緣由是我在題目裏提到了對
Object
的支持,而個人答案以及題目考覈的最初想法都沒有考慮Object
的狀況(記憶錯亂了)。再次感謝指正關於
Object.assign
,不明白的同窗看這裏assign;對於Object.getPrototypeOf
不清楚的同窗,看getPrototypeOf
如何「拍平」一個多維數組,這是好玩意兒
答案:
var flatten = function(array) { return array.reduce(function(previous, i) { if (Object.prototype.toString.call(i) !== '[object Array]') { return (previous.push(i), previous); } return (Array.prototype.push.apply(previous, flatten(i)), previous); }, []); }; module.exports = flatten;
本題在「遞歸」這個問題上,作了一些考慮。我想考查的主要是面對多維數組,候選人將如何處理!
個人答案用了
reduce
方法,若是你還沒用過,你須要看reduce。另外可能有人對於逗號的使用有疑惑,能夠看Comma_Operator。另:個人答案毫不敢稱最佳,隨時歡迎優化/修正。
考查
ES5
時代基於prototype
的類繼承實現,若是你心繫ES6
,這個能夠忽略。但瞭解總歸是好的。
答案:
Parent
var Parent = function(name) { this.name = name; }; Parent.prototype.getName = function() { return this.name; }; module.exports = Parent;
Son
var Parent = require('./Parent'); var Son = function(parentName, name) { Parent.call(this, parentName); this.childName = name; }; Son.prototype = Object.create(Parent.prototype); Son.prototype.constructor = Son; Son.prototype.getChildName = function() { return this.childName; }; module.exports = Son;
以上算是基本繼承概念,若是不清楚的,看看這篇教程OOP in JS, Part 2 : Inheritance。你也可能對與
Object.create
的使用感到疑惑,那麼請看create接受@我仍舊在這裏 建議,把
new Parent()
換成了Object.create(Parent.prototype)
經過長期觀察咱們發現一個現象,就是在
ES2015
甚至ES2016
大行其道的今天,仍然有人打着「我要兼容IE8」的旗號拒絕進步。自ES5
開始就有的Array
新方法map
,forEach
、reduce
經常有人搞不懂,也不會用,更不知道幹嗎用的。每每一言不和就吐一堆for
循環出來噁心人!本題主要就是甄別候選人是否本身口中所說的那樣「積極、愛學習」,若是連ES5
就有的常見方法都不會,仍是「積極、愛學習」,那我只能呵呵了!
答案:
var map = function(arr, func, ctx) { var array = []; arr.forEach(function(i, index) { array.push(func.call(ctx, i, index, arr)); }); return array; }; module.exports = map;
這裏解法也是多種多樣,無所謂用哪種,關鍵在因而否真正理解了什麼是
map
?文檔看:map
最爲
ES5
裏Array
的幾個好兄弟,reduce
的用法/原理我想仍是應該掌握的。
答案:
var reduce = function(arr, func, initialValue) { var base = typeof initialValue === 'undefined' ? arr[0] : initialValue; var stepForward = typeof initialValue === 'undefined' ? 1 : 0; var startPoint = stepForward; arr .slice(startPoint) .forEach(function(val, index) { base = func(base, val, index + stepForward, arr); }); return base; }; module.exports = reduce;
仍然不理解
reduce
工做原理的,看Understanding Eloquent Javascript's Reduce function
永遠獲取傳入參數的最終執行結果,若是是函數的,就執行、執行、再執行,直到拿到了最終的非函數結果。
答案:
var value = function(anything) { if (Object.prototype.toString.call(anything) !== '[object Function]') { return anything; } return value(anything()); }; module.exports = value;
今天實在寫不動了,先來10題試試反響,若是你們以爲還有用,我再繼續補後面的題目。固然也歡迎直接Github
給我PR,star
那天然是最好的啦^^
欲知後事,請看下集