摘要:綁定為這個數組五綁定如果使用來創建對象,因為后面跟著的是構造函數,所以稱它為構造器調用。為傳進來的構造函數你這要看懂這步就行。
記得剛開始,我理解 this 的時候 也是云里霧里的,哈哈,希望通過這篇文章,對你有幫助吧。
關于 this 最多的說法,就是:誰調用它,this就指向誰。這話呢,不能說它錯了,只能說它講的不嚴謹,為什么呢?我們先來了解下 this 的幾種綁定規則。
一、默認綁定默認綁定 發生在全局環境 。
全局環境中,this 默認綁定到 window。(嚴格模式下一樣)
</>復制代碼
console.log(this === window);
//true
"use strict"; //使用嚴格模式執行代碼
var a = 666;
console.log(this.a)
//666
隱式綁定 發生在 方法調用(執行)。
什么是方法呢?通常把 對象的屬性值 是函數的,稱為方法。
</>復制代碼
var obj = {
fun: function(){}
}
//這里obj 對象里 的fun 屬性值是個函數, 就把 這個fun 屬性稱為方法了。
通常,方法調用時,this 隱式綁定到其 所屬的對象 上。
</>復制代碼
var a = "window";
var obj = {
a: "obj",
fun: function(){
console.log(this.a);
}
}
obj.fun();
//"obj"
來個難一點的:
</>復制代碼
var obj1 = {
a: "obj1",
obj2: {
a: "obj2",
fun: function(){
console.log(this.a);
}
}
}
obj1.obj2.fun();
//"obj2"
這里的答案 跟你想的一樣嗎? 出現這個答案的關鍵 就是于,fun 函數 在作為對象方法執行時, this 綁定的是它的 所屬對象,也就是 obj2 。 而非外層 的 obj1。
三、隱式綁定丟失在判斷是否是隱式綁定的時候,最容易出問題的地方就是發生在 隱式綁定丟失。
隱式丟失是指被隱式綁定的函數丟失綁定對象,從而綁定到window。這種情況容易出錯卻又常見。(嚴格模式下,綁定到undefined)
隱式綁定丟失 一般 發生在 函數獨立調用時。
啥是獨立調用呢?就是一個簡單的函數執行. 函數名的前面沒有任何引導內容。
</>復制代碼
function ff(){};
ff(); //獨立調用
當函數獨立調用(執行)時,this 就會隱式綁定丟失,而綁定到 window 對象上。(非嚴格模式下)
</>復制代碼
function fun(){
console.log(this === window);
}
fun();
//true
那么嚴格模式下呢?是指向 undefined 的。
</>復制代碼
function fun(){
"use strict"; //使用嚴格模式執行代碼
console.log(this);
}
fun();
//undefined
考考你:
</>復制代碼
var a = "window";
var obj = {
a: "obj",
fun1: function(){
console.log(this.a);
}
}
var fun2 = obj.fun;
fun2();
//"window"
判斷是否隱式綁定丟失的關鍵就在于, 判斷函數 是否是哪種調用。
上面的例子,關鍵點就在 最后兩行代碼。
先看其中的第一行:
</>復制代碼
var fun2 = obj.fun;
這里把 obj 的fun 方法 賦值給了 一個變量 fun2,這里的 fun 并沒有作為對象的方法來執行,因為,fun 方法這里沒有執行。
其后:
</>復制代碼
fun2();
再執行 fun2,它保存著 fun1 方法,這時候執行 fun2(等于fun1) ,但是,它是獨立調用。因為,沒有作為對象的方法來調用。所以 this 就被指向 window了。
那么怎么解決隱式丟失問題呢?
</>復制代碼
var a = "window";
var obj = {
a: "obj",
fun: function(){
return function(){
console.log(this.a);
}
}
}
obj.fun()();
//"window"
//這里我們想要的是 obj里 a 的值,可是,隱式綁定丟失導致獲取到了 window 里 a 的值。
可以基礎好的已經知道答案了:
</>復制代碼
var a = "window";
var obj = {
a: "obj",
fun: function(){
var that = this;
return function(){
console.log(that.a);
}
}
}
obj.fun()();
//"obj"
因為 fun 是作為方法調用的,所以 this 綁定到 obj 對象上,因此,我們就可以先用一個變量 that 來保存 this,然后 在內部的 匿名函數中 使用 that 就可以了。它保存著 上面 this 的綁定對象。
忽然靈機一動,想出個題目,看人家都玩出題,我也試試,哈哈:
</>復制代碼
var a = "window";
function fun(){
var a = "fun";
return (function(){
return this.a;
})()
}
fun()
//“你猜”
這道題中 有立即執行函數、this問題,哈哈,乍一看挺惡心,其實看完上面的,應該可以看出來的。
四、顯示綁定通過call()、apply()、bind()方法把 this 綁定到對象上,叫做顯式綁定。對于被調用的函數來說,叫做間接調用。
</>復制代碼
var a = "window"
var obj = {
a:"obj",
}
function fun(){
console.log(this.a);
}
fun.call(obj);
//"obj";
這里使用了 call 方法,把fun 中的 this 綁定到 obj 對象上。
javascript內置的一些函數,具有顯式綁定的功能,如數組的5個迭代方法:map()、forEach()、filter()、some()、every(),以及創建對象的 Object.create() 函數(后面原型鏈中會細說),都可以手動綁定this。
大家可以去看下API文檔,數組的這幾個函數的最后一個參數,就是指定函數內 this 的綁定,如果不指定,則是window,嚴格模式下是undefined。
</>復制代碼
var a = [1,2,3];
a.forEach(function(){
console.log(this)
},a);
//綁定 this 為 a 這個數組
//(3) [1, 2, 3]
//(3) [1, 2, 3]
//(3) [1, 2, 3]
五、new 綁定
如果 使用 new 來創建對象,因為 后面跟著的是構造函數,所以稱它為構造器調用。對于this綁定來說,稱為new綁定。
想知道 構造器調用 中 this 的綁定,就要知道 new 到底做了啥了。
先來個 new 的實現。看不懂不要緊,在后面原型鏈那篇,還會說的。
</>復制代碼
function New(proto){ //proto 為傳進來的構造函數
var obj = {};
obj.__proto__ = proto.prototype;
proto.apply(obj, Array.prototype.slice.call(argument,1));
//你這要看懂這步就行。這里把構造函數里的 this 綁定到了 新的obj 對象上,最后 返回了該新對象,作為實例對象。
return obj;
}
所以在使用 new 來創建實例對象時,new 內部把 構造函數的 this 綁定到 返回的新對象 上了。
</>復制代碼
function Person(name){
this.name = name;
}
var c = new Person("zdx");
c.name;
總結: this的四種綁定規則:隱式綁定、隱式綁定丟失、顯式綁定和new綁定,分別對應函數的四種調用方式:方法調用、獨立調用、間接調用和構造器調用。
1、關于this綁定 的優先級問題。
簡單提一下吧:
new 綁定 > 顯示綁定 > 隱式綁定 > 默認綁定 。
2、ES6 中,箭頭函數的 this 綁定。
箭頭函數內的 this 綁定的 是所屬的環境(函數或者對象), 它是固定不變的。
先看下上面的這個例子
</>復制代碼
var a = "window";
var obj = {
a: "obj",
fun: function(){
return function(){
console.log(this.a);
}
}
}
obj.fun()();
//"window"
上面我們使用 一個變量來保存 this 的綁定,下面我們來用 箭頭函數解決問題
</>復制代碼
var a = "window";
var obj = {
a: "obj",
fun: function(){
return () => {
console.log(this.a);
}
}
}
obj.fun()();
//"obj"
實際上,箭頭函數內部是沒有this 的,所以,它不能使用 new 構造器調用,call 等顯示綁定。所以它內部就是使用了一個變量來保存 箭頭函數 所屬環境的(函數或者對象) this。
就相當于:
</>復制代碼
var a = "window";
var obj = {
a: "obj",
fun: function(){
that = this;
return function(){
console.log(that.a);
}
}
}
obj.fun()();
//"obj"
考考你:
</>復制代碼
var a = "window";
var obj = {
a: "obj",
fun1: function(){
return () => {
console.log(this.a);
}
}
}
var fun2 = obj.fun1;
fun2()();
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/96444.html
摘要:情況沒有明確作用對象的情況下,通常為全局對象例如函數的回調函數,它的就是全局對象。正因如此,機器可以作為這類對象的標志,即面向對象語言中類的概念。所以機器又被稱為構造函數。原型鏈也就是繼承鏈。 JS面向對象二:this/原型鏈/new原理 阮一峰JavaScript教程:面向對象編程 阮一峰JavaScript教程:實例對象與 new 命令 阮一峰JavaScript教程:this 關...
摘要:此時產生了閉包。導致,函數的活動對象沒有被銷毀。是不是跟你想的不一樣其實,這個例子重點就在函數上,這個函數的第一個參數接受一個函數作為回調函數,這個回調函數并不會立即執行,它會在當前代碼執行完,并在給定的時間后執行。 上一節說了執行上下文,這節咱們就乘勝追擊來搞搞閉包!頭疼的東西讓你不再頭疼! 一、函數也是引用類型的。 function f(){ console.log(not cha...
摘要:每一個由構造函數創建的對象都會默認的連接到該神秘對象上。在構造方法中也具有類似的功能,因此也稱其為類實例與對象實例一般是指某一個構造函數創建出來的對象,我們稱為構造函數的實例實例就是對象。表示該原型是與什么構造函數聯系起來的。 本文您將看到以下內容: 傳統構造函數的問題 一些相關概念 認識原型 構造、原型、實例三角結構圖 對象的原型鏈 函數的構造函數Function 一句話說明什么...
摘要:有關函數柯里化的詳解,請回閱前端進擊的巨人五學會函數柯里化。構造函數中的通過操作符可以實現對函數的構造調用。在了解構造函數中的前,有必要先了解下實例化對象的過程。 showImg(https://segmentfault.com/img/bVburMp?w=800&h=600); 常見this的誤解 指向函數自身(源于this英文意思的誤解) 指向函數的詞法作用域(部分情況) th...
摘要:匿名函數是不能單獨寫的,所以就提不上立即執行了。六立即執行函數在閉包中的應用立即執行函數能配合閉包保存狀態。來看下上節內容中閉包的例子現在,我們來利用立即執行函數來簡化它第一個匿名函數執行完畢后,返回了第二個匿名函數。 前面的閉包中,提到與閉包相似的立即執行函數,感覺兩者還是比較容易弄混吧,嚴格來說(因為犀牛書和高程對閉包的定義不同),立即執行函數并不屬于閉包,它不滿足閉包的三個條件。...
閱讀 3152·2023-04-26 02:33
閱讀 3106·2023-04-25 21:33
閱讀 913·2021-09-02 09:56
閱讀 2932·2019-08-30 15:44
閱讀 2464·2019-08-30 13:15
閱讀 1038·2019-08-30 13:04
閱讀 1639·2019-08-29 15:09
閱讀 3969·2019-08-26 18:26