過久沒有面試過了,第一次不免有點緊張,今天遇到的面試問題,大多數都遇到過,卻由於沒有充分準備,而沒有答好,之後必定好好準備才行。javascript
下面記錄一下今天的面試問題,加深印象:java
介紹一下JS的數據類型?面試
簡單類型:
String
、Number
、Boolean
、Null
、Undefined
複雜類型:Object
ES6新增類型:Symbol
(感謝TimeTraveler指出)
&
擴展:編程
- null與undefined有什麼區別
答:null
表示一個對象被定義了,值爲「空值」,而undefined
表示不存在這個值。
正由於這個緣由,因此使用typeof
判斷是,null
返回的是object
,而undefined
返回的是undefined
。(判斷二者時須要使用===
嚴格判斷)- Boolean類型在進行判斷的時候設置爲 0、-0、null、""、false、undefined 或 NaN,則該對象設置爲 false。不然設置爲 true(即便 value 參數是字符串 "false")
如何經過JS判斷一個數組?數組
- instanceof方法
instanceof
運算符是用來測試一個對象是否在其原型鏈原型構造函數的屬性。var arr = []; arr instanceof Array; // true複製代碼
- constructor方法
constructor
屬性返回對建立此對象的數組函數的引用,就是返回對象相對應的構造函數。var arr = []; arr.constructor == Array; //true複製代碼
- 特性判斷法
利用判斷數組獨有的length
和splice
方法,可是這是不靠譜的,由於對象也能添加方法和屬性。那怎麼辦了,有一個辦法,能夠利用數組的length屬性
無法枚舉來判斷。function isArray(object){ return object && typeof object==='object' && typeof object.length==='number' && typeof object.splice==='function' && //判斷length屬性是不是可枚舉的 對於數組 將獲得false !(object.propertyIsEnumerable('length')); }複製代碼
- 最簡單的方法
這種寫法,是 jQuery 正在使用的,淘寶的 kissy 也是使用這種方式。Object.prototype.toString.call(value) == '[object Array]' // 利用這個方法,能夠寫一個返回數據類型的方法 var isType = function (obj) { return Object.prototype.toString.call(obj).slice(8,-1); }複製代碼
- ES5新增方法isArray()
var a = new Array(123); var b = new Date(); console.log(Array.isArray(a)); //true console.log(Array.isArray(b)); //false複製代碼
&
擴展:
- 使用
instaceof
和construcor
,被判斷的array
必須是在當前頁面聲明的。好比,一個頁面(父頁面)有一個框架,框架中引用了一個頁面(子頁面),在子頁面中聲明瞭一個array
,並將其賦值給父頁面的一個變量,這時判斷該變量,Array == object.constructor;
會返回false
。- 最簡單的方法,在IE6下判斷
null
和undefined
,有一些bug,判斷undefined
和null
均爲Object
,(並非bug
,是在ES3的標準下返回的就爲Object
)
談一談let
與var
的區別?閉包
let爲ES6新添加申明變量的命令,它相似於
var
,可是有如下不一樣:app
let
命令不存在變量提高,若是在let
前使用,會致使報錯- 暫時性死區,若是塊區中存在
let
和const
命令,就會造成封閉做用域- 不容許重複聲明,所以,不能在函數內部從新聲明參數
map
與forEach
的區別?框架
由於平時基本只用
forEach
,因此這個很尷尬,索性就把新增的數組方法都刷一遍吧。異步
forEach
方法,是最基本的方法,就是遍歷與循環,默認有3個傳參:分別是遍歷的數組內容item
、數組索引index
、和當前遍歷數組Array
。另外,除去第一個必須的回調函數參數,還能夠接受一個上下文參數(改變回調函數的this指向);而且forEach
不會遍歷空元素。map
方法,基本用法與forEach一致,可是不一樣的,它會返回一個新的數組,因此在callback須要有return值,若是沒有,會返回undefined。(從字面理解,map就是映射的意思)filter
方法,用法和map很類似,從字面理解,就是過濾、篩選的意思。可是函數的callback須要返回布爾值true
或false
,而且返回值只須要爲弱等==
便可。some
方法,對數組中每一項運行指定函數,若是該函數對任一項返回true
,則返回true
。(一旦遇到true
,就會中斷循環,返回true
,相似於||判斷
)every
方法,對數組中的每一項運行給定函數,若是該函數對每一項返回true
,則返回true
。(一旦遇到false,就會中斷循環,返回false
,相似於&&判斷
)indexOf
方法,與字符串中的indexOf
相似,返回數組索引值,若是沒有匹配,則會返回-1
,第二個參數爲可選,表示從當前位置開始搜索。lastIndexOf
方法,與indexOf
類似,只是是從數組的末尾開始查找,而第二個參數的默認值是array.length - 1
。reduce
方法,字面意思應該是‘減小’,可是實際是‘遞歸’的意思。實際就是應用一個函數針對數組的兩個值(從左到右),以減至一個值。它的callback
接收4個參數:以前值(上一次循環返回的值)、當前值、索引值以及數組自己。initialValue
參數可選,表示初始值。reduceRight
方法,與reduce
方法相似,只是從數組的末尾開始實現。
談一談你理解的函數式編程?async
what?函數編程就是函數編程啊,還有什麼理解??
如今查了一下,才知道,原來沒有那麼簡單!!!
簡單說,"函數式編程"是一種"編程範式"(programming paradigm),也就是如何編寫程序的方法論。
它具備如下特性:閉包和高階函數、惰性計算、遞歸、函數是"第一等公民"、只用"表達式",不用"語句"(都會有返回值)、沒有"反作用"、不修改狀態、引用透明性。
具體的特性表明了什麼,我還要好好研究一下!!
談一談箭頭函數與普通函數的區別?
平時用的很爽,可是還真沒有考慮過這個問題!!
- 箭頭函數使得表達更加簡潔。(這個是廢話)
- 函數體內的
this
對象,就是定義時所在的對象,而不是使用時所在的對象。- 不能夠看成構造函數,也就是說,不可使用
new
命令,不然會拋出一個錯誤。- 不可使用
arguments
對象,該對象在函數體內不存在。若是要用,能夠用Rest參數
代替。- 不可使用
yield
命令,所以箭頭函數不能用做Generator
函數。
談一談函數中this的指向吧?
this的指向在函數定義的時候是肯定不了的,只有函數執行的時候才能肯定this到底指向誰,實際上this的最終指向的是那個調用它的對象。
《javascript語言精髓》中大概歸納了4種調用方式:
- 方法調用模式
- 函數調用模式
- 構造器調用模式
- apply/call調用模式
特別補充:
- 在構造器調用時,若是加入了
return
而且return
了一個對象,this
會指向這個return
的對象。- 爲何構造器時
this
會指向new
的對象?var p = new Emp(); // 過程模擬,new關鍵字會建立一個空的對象,而後會自動調用一個函數apply方法,將this指向這個空對象,這樣的話函數內部的this就會被這個空的對象替代。 var p = {}; Emp.apply(p); p.__proto__=Emp.prototype;複製代碼
談一談閉包吧?
「閉包」,是指那些可以訪問獨立(自由)變量的函數 (變量在本地使用,但定義在一個封閉的做用域中)。換句話說,這些函數能夠「記憶」它被建立時候的環境。特性:
- 函數嵌套函數
- 函數內部能夠引用外部的參數和變量
- 參數和變量不會被垃圾回收機制回收
異步編程的實現方式?
- 回調函數:
- 優勢:簡單、容易理解
- 缺點:不利於維護,代碼耦合高
- 事件監聽(採用時間驅動模式,取決於某個事件是否發生):
- 優勢:容易理解,能夠綁定多個事件,每一個事件能夠指定多個回調函數
- 缺點:事件驅動型,流程不夠清晰
- 發佈/訂閱(觀察者模式):
- 相似於事件監聽,可是能夠經過‘消息中心’,瞭解如今有多少發佈者,多少訂閱者。
- Promise對象
- 優勢:能夠利用then方法,進行鏈式寫法;能夠書寫錯誤時的回調函數;
- 缺點:編寫和理解,相對比較難
- Generator函數
- 優勢:函數體內外的數據交換、錯誤處理機制
- 缺點:流程管理不方便
- async函數
- 優勢:內置執行器、更好的語義、更廣的適用性、返回的是Promise、結構清晰。
- 缺點:錯誤處理機制