摘要:在嚴格模式下,對象的函數中的指向調用函數的對象實例顯式綁定,,通過可以把的綁定到上。間接引用最容易在賦值時發生返回目標函數的引用詞法之前介紹的種綁定規則可以包含所有正常的函數,但是中介紹了一種無法使用這些規則的特殊函數類型箭頭函數。
this到底指向什么?
this關鍵詞是javaScript中最復雜的機制之一,一般有兩個誤區:
1.this指向函數自身;
2.this指向函數的作用域;
this是指向調用位置,調用位置就是函數在代碼中被調用的位置(而不是聲明的位置),this的綁定規則主要有4條,我們在使用時能判斷它屬于哪種規則即可;
1.默認綁定首先介紹最常用的函數調用類型:獨立函數調用,可以理解為這是一條在無法應用其他規則的默認規則,非嚴格模式下,this指向全局對象,即window
var a = 2; function foo(){ var a = 1; console.log(this.a) } foo(); // 2
很明顯這里的this指向window對象,但嚴格模式下呢?
var a = 1; function foo(){ "use strict" console.log(this.a) } foo(); // TypeError:this is undefined
嚴格模式下函數中的this指向undefined
"use strict"; console.log(this === window); // false? // true? this.a = 9804; console.log(window.a); // undefined? // 9804? // true // 9804
但全局中的this指向window
2.隱式綁定先看一段代碼
function foo(){ console.log(this.a) } var a = 1; var obj = { a:2, foo:foo } obj.foo(); // ? // 2
當函數引用有上下文對象時,隱式綁定規則會把函數調用中的this綁定到這個上下文對象,可以記住一點:誰調用綁到誰身上。
再看一段代碼:
function foo(){ console.log(this.a) } var obj2 = { a:42, foo:foo } var obj1 = { a:2, obj2:obj2 } obj1.obj2.foo(); // ? // 42
對象屬性引用鏈中只有上一層或者最后一層才起作用。
"use strict"; var o = new Object(); o.a = "obj.a"; o.f5 = function(){ return this.a; } console.log(o.f5());// ? // obj.a
在嚴格模式下,對象的函數中的this指向調用函數的對象實例
3.顯式綁定apply,call,bind
function foo(){ console.log(this.a) } var a = 1; var obj = { a:2 } foo.call(obj);// ? // 2
通過foo.call()可以把foo的this綁定到obj上。
var obj1 = { a: 1, b: 2, caculate: function(c,d){ return this.a + this.b + c + d; } }; var obj2 = { a: 10, b: 20, }; console.log( obj1.caculate(3,4) ); // ? console.log( obj1.caculate.call( obj2, 3, 4 ) ); // ? console.log( obj1.caculate.apply( obj2, [30, 40] ) ); // ? // 10 // 37 // 100
call 和 apply 的用法唯一的不同就是傳參的方式不同,參見上面兩種調用方式
(1)硬綁定
看下面代碼:
var a = 1; function foo(){ console.log(this.a) } var obj = { a:2 } var bar = function(){ foo.call(obj) } bar();// ? setTimeout(bar,100);// ? //硬綁定的bar不可能再修改它的this bar.call(window); // ? // 2 // 2 // 2
無論何時調用bar函數,都會手動obj上調用foo,這種就是一種顯示的強制綁定,即硬綁定。硬綁定的典型場景就是創建一個包裹函數
由于硬綁定是一種常用的模式,所以ES5提供的內置的方法Function.prototype.bind,它的用法如下:
function foo(something){ console.log(this.a ,something); return this.a + something } var obj = { a:2 } var bar = foo.bind(obj); var b = bar(3); console.log(b); // 2 3 // 5
bind(..)會返回一個硬編碼的新函數,它會把你指定的參數設置為this的上下文并調用原始函數,但是Ta是永久綁定,一旦綁定不會在改變:4.new綁定
當用 new 運算符調用函數時,該函數總會返回一個對象,通常情況下,如果構造器不顯式地返回任何數據,或者是返回一個非對象類型的數據,構造器里的 this 就指向返回的這個對象,
var MyClass = function(){ this.name = "sven"; return "anne"; // 返回 string 類型 }; var obj = new MyClass(); console.log(obj) // ? console.log(obj.name); // ? // {name: "sven"} // 輸出: sven
var MyClass = function(){ this.name = "sven"; return { // 顯式地返回一個對象 name: "anne" } }; var obj = new MyClass(); console.log( obj); // ? // 輸出: {name: "anne"}
"use strict"; console.log("嚴格模式"); console.log("構造函數中的this"); function constru(){ this.a = "constru-a"; this.f2 = function(){ console.log(this.b); return this.a; } } var o2 = new constru(); // ? o2.b = "o2-b"; console.log(o2.f2()); // ? // o2-b // constru-a
在嚴格模式下,構造函數中的this指向構造函數創建的對象實例四種綁定規則的優先級
new綁定>顯式綁定>隱式綁定>默認綁定被忽略的this
如果你把null或者undefined作為this的綁定對象傳入call、apply或者bind,這些值在調用時會被忽略,實際應用的是默認綁定規則:
function foo(){ console.log(this.a) } var a = 2; foo.call(null); // ? // 2間接引用
另一個需要注意的是,你有可能無意的創建一個函數的“間接引用”,這種情況下,調用函數會應用默認規則。間接引用最容易在賦值時發生:
function foo() { console.log(this.a); } var a = 2; var o = { a: 3, foo: foo}; var p = { a: 4 }; o.foo(); (p.foo = o.foo)(); // 返回目標函數的引用 //3 //2this詞法
之前介紹的4種綁定規則可以包含所有正常的函數,但是ES6中介紹了一種無法使用這些規則的特殊函數類型:箭頭函數。
箭頭函數this的定義:箭頭函數中的this是在定義函數的時候綁定,而不是在執行函數的時候綁定。
function foo(){ //返回一個箭頭函數 return (a) => { //this繼承自foo() console.log(this.a) } } var obj1 = { a:2 } var obj2 = { a:3 } var bar = foo.call(obj1); bar.call(obj2); // ? // 2, 不是3
foo()內部創建的箭頭函數會捕獲調用時foo()的this,由于foo()的this綁定到obj1,bar(引用箭頭函數)的this也會綁定到obj1,箭頭函數的綁定無法被修改小結
1.由new調用?綁定到新創建的對象。
2.由call或者apply(或者bind)調用?綁定到指定的對象。
3.由上下文對象調用?綁定到那個上下文對象。
4.默認:在嚴格模式下綁定到undefined,否則綁定到全局對象。
ES6中的箭頭函數并不會用這4種綁定規則,而是根據詞法作用域來決定this,具體來說,箭頭函數會繼承外層函數調用的this綁定。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/105700.html
摘要:當我們不想再對象內部間接包含引用函數,而像在某個對象上強制調用函數。我們可以用中內置的和的方法來實現,這兩個方法的第一個參數是一個對象,是給準備的,接著再調用函數時將其綁定到。 this是什么 在javascript中,每個執行上下文可以抽象成一組對象showImg(https://segmentfault.com/img/bVuKR7); 而this是與執行上下文相關的特殊對象,任何...
摘要:關于的全棉解析上的文章地址判斷函數是否在中調用綁定如果是的話綁定的是新創建的對象。顯而易見,這種方式可能會導致許多難以分析和追蹤的。默認在嚴格模式下綁定到,否則綁定到全局對象。 關于this的全棉解析(上)的文章地址 判斷this 函數是否在new中調用(new綁定)?如果是的話this綁定的是新創建的對象。 bar = new foo() 函數是否通過call、apply(顯式綁定...
摘要:關于的全面解析下頁面鏈接的調用位置調用位置就是函數在代碼中被調用的位置而不是聲明的位置,尋找調用位置就是尋找函數被調用的位置,最重要的是分析調用棧就是為了到達當前執行位置所調用的所有函數。因此,調用函數時被綁定到這個對象上,所以和是一樣的。 關于this的全面解析(下)頁面鏈接 this的調用位置 調用位置就是函數在代碼中被調用的位置(而不是聲明的位置),尋找調用位置就是尋找函數被調用...
摘要:在嚴格模式下調用函數則不影響默認綁定。回調函數丟失綁定是非常常見的。因為直接指定的綁定對象,稱之為顯示綁定。調用時強制把的綁定到上顯示綁定無法解決丟失綁定問題。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第三期,本周的主題是this全面解析,今天是第9天。 本計劃一共28期,每期重點攻克一個面試重...
摘要:在傳統的面向類的語言中,構造函數是類中的一些特殊方法,使用初始化類是會調用類中的構造函數。 在上一節中我們詳細介紹了this的兩種綁定方式,默認綁定和隱式綁定,在這一節我們繼續介紹this的另外兩種綁定方式顯示綁定和new綁定。那么,我們要解決的問題當然就是上一節中我們提到的:this丟失! 顯式綁定 在隱式綁定中,我們必須在一個對象的內部包含一個指向函數的屬性,并通過這個屬性間接引用...
摘要:調用棧就是為了到達當前執行位置所調用的所有函數。由于無法控制回調函數的執行方式,因此就沒有辦法控制調用位置得到期望的綁定,下一節我們會介紹如何通過固定來修復這個問題。 在《你不知道的this》中我們排除了對于this的錯誤理解,并且明白了每個函數的this是在調用時綁定的,完全取決于函數的調用位置。在本節中我們主要介紹一下幾個主要內容: 什么是調用位置 綁定規則 this詞法 調用...
閱讀 2720·2021-10-12 10:12
閱讀 2345·2021-09-02 15:41
閱讀 2577·2019-08-30 15:55
閱讀 1409·2019-08-30 13:05
閱讀 2446·2019-08-29 11:21
閱讀 3542·2019-08-28 17:53
閱讀 3037·2019-08-26 13:39
閱讀 808·2019-08-26 11:50