這段時間,金三銀四,不少人面試,不少人分享面試題。在前段時間,我也臨時擔任面試官,爲了大概瞭解面試者的水平,我也寫了一份題目,面試了幾個前端開發者。在這段時間裏面,我在學,在寫設計模式的一些知識,想不到的設計模式的這些知識,就是面試題裏面,頻繁讓人掉坑的考點。因此,今天就總結一下,那些讓人掉坑的考點。javascript
關於面向對象和麪向過程,我的以爲這二者不是絕對獨立的,而是相互相成的關係。至於何時用面向對象,何時用面向過程,具體狀況,具體分析。html
針對於面向對象編程的。知乎上有一個高贊回答:前端
面向對象: 狗.吃(屎)
面向過程: 吃.(狗,屎)java
可是這個例子以爲不太優雅,我改一下了,舉一個優雅些的小例子說明一下面向對象和麪向過程的區別。面試
需求:定義‘守候吃火鍋’編程
面向對象的思想是:守候.動做(吃火鍋)設計模式
面向過程的思想是:動做(守候,吃火鍋)數組
代碼實現方面:微信
//面向對象
//定義人(姓名)
let People=function(name){
this.name=name;
}
//動做
People.prototype={
eat:function(someThing){
console.log(`${this.name}吃${someThing}`);
}
}
//守候是我的,因此要建立一我的(new一次People)
let shouhou=new People('守候','男',24);
shouhou.eat('火鍋');
//面向過程
let eat=function(who,someThing){
console.log(`${who}吃${someThing}`);
}
eat('守候','火鍋');複製代碼
結果都同樣,都是輸出‘守候吃火鍋’。可是萬一我如今吃飽了,準備寫代碼了。這下怎麼實現呢?看代碼閉包
//面向對象
shouhou.coding=function(){
console.log(this.name+'寫代碼');
}
shouhou.coding();
//面向過程
let coding=function(who){
console.log(who+'寫代碼');
}
coding('守候');複製代碼
結果也同樣:‘守候寫代碼’
可是不難發現面向對象更加的靈活,複用性和擴展性更加。由於面向對象就是針對對象(例子中的:‘守候’)來進行執行某些動做。這些動做能夠自定義擴展。
而面向過程是定義不少的動做,來指定誰來執行這個動做。
好了,面向對象的簡單說明就到這裏了,至於面向對象的三大特性:繼承,封裝,多態這個自行上網查找資料。
使用 JavaScript 開發的時候,不少開發者多多少少會被 this
的指向搞蒙圈,可是實際上,關於 this
的指向,記住最核心的一句話:哪一個對象調用函數,函數裏面的this指向哪一個對象。
下面分幾種狀況談論下
這個狀況沒特殊意外,就是指向全局對象-window。
let username='守候'
function fn(){
alert(this.username);//undefined
}
fn();複製代碼
可能你們會困惑,爲何不是輸出守候
,可是在細看一看,我聲明的方式是let
,不會是window
對象
若是輸出守候,要這樣寫
var username='守候'
function fn(){
alert(this.username);//守候
}
fu();
//---------------
window.username='守候'
function fn(){
alert(this.username);//守候
}
fn();
//能夠理解爲
//window.fn();複製代碼
這個相信不難理解,就是那個函數調用,this指向哪裏
window.b=2222
let obj={
a:111,
fn:function(){
alert(this.a);//111
alert(this.b);//undefined
}
}
obj.fn();複製代碼
很明顯,第一次就是輸出obj.a
,就是111。而第二次,obj
沒有b
這個屬性,因此輸出undefined,由於this
指向obj
。
可是下面這個狀況得注意
let obj1={
a:222
};
let obj2={
a:111,
fn:function(){ alert(this.a);
}
}
obj1.fn=obj2.fn;
obj1.fn();//222複製代碼
這個相信也不難理解,雖然obj1.fn
是從obj2.fn
賦值而來,可是調用函數的是obj1
,因此this
指向obj1
。
let TestClass=function(){
this.name='111';
}
let subClass=new TestClass();
subClass.name='守候';
console.log(subClass.name);//守候
let subClass1=new TestClass();
console.log(subClass1.name)//111複製代碼
這個也是不難理解,回憶下(new的四個步驟)就差很少了!
可是有一個坑,雖然通常不會出現,可是有必要提一下。
在構造函數裏面返回一個對象,會直接返回這個對象,而不是執行構造函數後建立的對象
apply和call簡單來講就是會改變傳入函數的this。
let obj1={
a:222
};
let obj2={
a:111,
fn:function(){ alert(this.a);
}
}
obj2.fn.call(obj1);複製代碼
此時雖然是 obj2
調用方法,可是使用 了call
,動態的把 this
指向到 obj1
。至關於這個 obj2.fn
這個執行環境是 obj1
。apply
和 call
詳細內容在下面說起。
首先不得不說,ES6 提供了箭頭函數,增長了咱們的開發效率,可是在箭頭函數裏面,沒有 this
,箭頭函數裏面的 this
是繼承外面的環境。
一個例子
let obj={
a:222,
fn:function(){
setTimeout(function(){console.log(this.a)})
}
};
obj.fn();//undefined複製代碼
不難發現,雖然 fn() 裏面的 this 是指向 obj ,可是,傳給 setTimeout 的是普通函數, this 指向是 window , window 下面沒有 a ,因此這裏輸出 undefined。
換成箭頭函數
let obj={
a:222,
fn:function(){
setTimeout(()=>{console.log(this.a)});
}
};
obj.fn();//222複製代碼
此次輸出 222 是由於,傳給 setTimeout 的是箭頭函數,而後箭頭函數裏面沒有 this ,因此要向上層做用域查找,在這個例子上, setTimeout 的上層做用域是 fn。而 fn 裏面的 this 指向 obj ,因此 setTimeout 裏面的箭頭函數的 this ,指向 obj 。因此輸出 222 。
call
和 apply
的做用,徹底同樣,惟一的區別就是在參數上面。call
接收的參數不固定,第一個參數是函數體內 this
的指向,第二個參數如下是依次傳入的參數。
apply接收兩個參數,第一個參數也是函數體內 this
的指向。第二個參數是一個集合對象(數組或者類數組)
let fn=function(a,b,c){
console.log(a,b,c);
}
let arr=[1,2,3];複製代碼
如上面這個例子
let obj1={
a:222
};
let obj2={
a:111,
fn:function(){ alert(this.a);
}
}
obj2.fn.call(obj1);複製代碼
call
和 apply
兩個主要用途就是
1.改變 this
的指向(把 this
從 obj2
指向到 obj1
)
2.方法借用( obj1
沒有 fn
,只是借用 obj2
方法)
閉包這個可能你們是迷糊,可是必需要征服的概念!下面用一個例子簡單說下
let add=(function(){
let now=0;
return {
doAdd:function(){
now++;
console.log(now);
}
}
})()複製代碼
而後執行幾回!
上圖結果看到,now
這個變量,並無隨着函數的執行完畢而被回收,而是繼續保存在內存裏面。
具體緣由說下:剛開始進來,由於是自動執行函數,一開始進來會自動執行,這一塊
而後把這個對象賦值給 add
。因爲 add
裏面有函數是依賴於 now
這個變量。因此 now
不會被銷燬,回收。這就是閉包的用途之一(延續變量週期)。因爲 now
在外面訪問不到,這就是閉包的另外一個用途(建立局部變量,保護局部變量不會被訪問和修改)。
可能有人會有疑問,閉包會形成內存泄漏。可是你們想下,上面的例子,若是不用閉包,就要用全局變量。把變量放在閉包裏面和放在全局變量裏面,影響是一致的。使用閉包又能夠減小全局變量,因此上面的例子閉包更好!
在學設計模式的時候,遇到的知識點就是這一些了,這些知識點,也是我在羣聊,社區裏面,讓人掉坑比較多的考點。這些知識,能夠說是開發經常使用,面試常考的知識,仍是建議你們深刻些學習。上面那裏也是簡單的過一下而已。不算深刻。若是你們對文章有什麼建議,歡迎指點。
-------------------------華麗的分割線--------------------
想了解更多,關注關注個人微信公衆號:守候書閣