JS 中的 this 總結
阿新 • • 發佈:2018-09-20
post hellip body ret object show color log apply (可理解為:var girl=new Object(); girl.name="amy"; girl.testThis=this;(指向window)
函數上下文:在函數內部,this的取值取決於函數被調用的方式
1、簡單調用:
function f1(){
return this;
}
f1() === window; //在瀏覽器中,全局對象是window
非嚴格模式下,且this的值不是由該調用設置時(具體說就是不由該調用通過 call、apply、bind 這些方法來設置),this的值默認指向全局對象 嚴格模式下,this將保持它進入執行上下文時的值 所以默認為undefined
2、如果要想把 this 的值從一個上下文傳到另一個,就要用 call 或者apply 方法
3、bind方法:
ECMAScript 5 引入了 Function.prototype.bind。調用f.bind(someObject)會創建一個與f具有相同函數體和作用域的函數,但是在這個新函數中,this將永久地被綁定到了bind的第一個參數,無論這個函數是如何被調用的
4、箭頭函數:this與封閉詞法上下文的this保持一致(即this被設置為它創建時的上下文)。如果將this的值傳給call、bind、apply,它將被忽略,不過仍然可以為為調用添加參數,不過第一個參數應設置為null
5、作為對象的方法:當作為對象的方法被調用時,它們的this是調用該函數的對象,並且此時this的綁定只受最靠近的成員引用的影響
6、原型鏈中的this:this指向的是調用該方法的對象,就像該方法在對象上一樣
7、getter(與setter)中的this:用作getter(或setter)的函數會把this綁定到獲取(或設置)屬性的對象上
8、作為構造函數:this被綁定到正在構造的新對象(雖然構造器返回的默認值是this所指的那個對象,但它仍可以手動返回其他的對象)
9、作為一個DOM事件處理函數:this指向觸發事件的元素
10、作為一個內聯事件處理函數:this指向監聽器所在的DOM元素
如:
1、<button onclick="alert(this.tagName.toLowerCase());"> Show this </button> this指向button(註意只有外層代碼中的this是這樣設置的)
2、<button onclick="alert((function(){return this})());"> Show inner this </button> 這種情況下,沒有設置內部函數的this,相當於函數簡單調用的情況,所以它指向global/window對象
JavaScript 中的 this:
this指向是在運行函數時確定的,而不是定義函數時候確定的
匿名函數的執行環境具有全局性,因此其this 對象通常指向window(在通過call()或apply()改變函數執行環境的情況下,this 就會指向其他對象)
全局上下文:無論是否在嚴格模式下,在全局執行上下文中(在任何函數體外)this都指代全局對象
如:
1、console.log(this === window); // true
2、var girl={name:"amy",testThis:this}; console.log(girl.testThis); // window
函數上下文:在函數內部,this的取值取決於函數被調用的方式
1、簡單調用:
function f1(){
return this;
}
f1() === window; //在瀏覽器中,全局對象是window
非嚴格模式下,且this的值不是由該調用設置時(具體說就是不由該調用通過 call、apply、bind 這些方法來設置),this的值默認指向全局對象 嚴格模式下,this將保持它進入執行上下文時的值 所以默認為undefined
2、如果要想把 this 的值從一個上下文傳到另一個,就要用 call 或者apply 方法
3、bind方法:
ECMAScript 5 引入了 Function.prototype.bind。調用f.bind(someObject)會創建一個與f具有相同函數體和作用域的函數,但是在這個新函數中,this將永久地被綁定到了bind的第一個參數,無論這個函數是如何被調用的
4、箭頭函數:this與封閉詞法上下文的this保持一致(即this被設置為它創建時的上下文)。如果將this的值傳給call、bind、apply,它將被忽略,不過仍然可以為為調用添加參數,不過第一個參數應設置為null
5、作為對象的方法:當作為對象的方法被調用時,它們的this是調用該函數的對象,並且此時this的綁定只受最靠近的成員引用的影響
6、原型鏈中的this:this指向的是調用該方法的對象,就像該方法在對象上一樣
7、getter(與setter)中的this:用作getter(或setter)的函數會把this綁定到獲取(或設置)屬性的對象上
8、作為構造函數:this被綁定到正在構造的新對象(雖然構造器返回的默認值是this所指的那個對象,但它仍可以手動返回其他的對象)
9、作為一個DOM事件處理函數:this指向觸發事件的元素
10、作為一個內聯事件處理函數:this指向監聽器所在的DOM元素
如:
1、<button onclick="alert(this.tagName.toLowerCase());"> Show this </button> this指向button(註意只有外層代碼中的this是這樣設置的)
2、<button onclick="alert((function(){return this})());"> Show inner this </button> 這種情況下,沒有設置內部函數的this,相當於函數簡單調用的情況,所以它指向global/window對象
部分代碼示例:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>This</title> 6 </head> 7 <body> 8 9 <script> 10 //全局上下文:無論是否在嚴格模式下,在全局執行上下文中(在任何函數體外)this都指代全局對象 11 var girl={ 12 name:"amy", 13 testThis:this 14 }; 15 /* 16 可理解為: 17 var girl=new Ojbect(); 18 girl.name="amy"; 19 girl.testThis=this; 20 */ 21 console.log(girl.testThis);//window 22 </script> 23 24 <script> 25 console.log("JS 是基於詞法作用域的語言,函數在定義它的作用域中執行,而不是在調用它的作用域中執行"); 26 console.log("類的方法默認是不會綁定 this 的,作為對象的方法:當作為對象的方法被調用時,它們的this是調用該函數的對象,並且this的綁定只受最靠近的成員引用的影響"); 27 console.log("-----------About Amy --------------"); 28 var Amy={ 29 name:"Amy", 30 sex:"girl", 31 amyOutter:function(){ 32 console.log("amyOutter:",this); 33 return function(){ 34 console.log("amyAnonymous:",this); 35 }; 36 } 37 }; 38 console.log("----Amy.func amyOutter -----"); 39 var amy_anony=Amy.amyOutter(); 40 //輸出: amyOutter: {name: "Amy", sex: "girl", amyOutter: ƒ} 41 // 解析:作為對象的方法調用 42 43 console.log("----Amy.func amyOutter quote-----"); 44 var quote=Amy.amyOutter;//獲取Amy.amyOutter函數的引用 45 quote(); 46 //輸出:amyOutter: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} 47 // 解析:這裏相當於簡單調用 48 49 console.log("----Amy.func amyAnonymous-----"); 50 amy_anony(); 51 //輸出: amyAnonymous: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} 52 // 解析:直接調用返回的匿名函數 53 54 amy_anony.call(Amy); 55 //輸出: amyAnonymous: {name: "Amy", sex: "girl", amyOutter: ƒ} 56 // 解析:Amy用call調用返回的匿名函數 57 58 </script> 59 60 <script> 61 console.log("-----------About Mike -----------"); 62 var Mike={ 63 name:"Mike", 64 sex:"boy", 65 mikeOutter:function(){ 66 console.log("mikeOutter:",this); 67 (function(){ 68 console.log("mikeAnonymous:",this); 69 })(); 70 } 71 }; 72 73 console.log("----Mike.func mikeOutter---"); 74 Mike.mikeOutter(); 75 //輸出: mikeOutter: {name: "Mike", sex: "boy", mikeOutter: ƒ} 76 // 解析:作為對象的方法調用 77 //輸出: mikeAnonymous: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} 78 // 輸出:window 解析:匿名函數被調用 79 80 console.log("----Mike.func mikeOutter quote-----"); 81 var quote=Mike.mikeOutter;//獲取Mike.mikeOutter函數的引用 82 quote(); 83 //輸出:mikeOutter: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} 84 // 解析:這裏相當於簡單調用 85 //輸出: mikeAnonymous: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} 86 // 解析:匿名函數被調用 87 88 console.log("---Mike func call---"); 89 Mike.mikeOutter.call(Amy); 90 //輸出: mikeOutter: {name: "Amy", sex: "girl", amyOutter: ƒ} 91 // 解析:Amy 用call調用返回的匿名函數 92 //輸出:mikeAnonymous: Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} 93 // 解析:匿名函數被調用 94 95 </script> 96 97 <script> 98 console.log("-----------About Guang -----------"); 99 var Guang={ 100 name:"Guang", 101 sex:"boy", 102 GuangOutterOne:function(){ 103 console.log("GuangOutterOne:",this); 104 var that=this; 105 // 正確 that 中保留了對 this 的引用 106 this.GuangOutterTwo(function(){ 107 that.GuangOutterThree(); 108 }); 109 110 // 正確 匿名函數直接綁定 this 111 // this.GuangOutterTwo(function(){ 112 // this.GuangOutterThree(); 113 // }.bind(this)); 114 115 // 出錯 匿名函數作參數 this 為 window ,window 無 GuangOutterThree 方法 116 // this.GuangOutterTwo(function(){ 117 // this.GuangOutterThree(); 118 // }); 119 }, 120 GuangOutterTwo:function(cb){ 121 console.log("GuangOutterTwo:",this); 122 cb(); 123 }, 124 GuangOutterThree:function(){ 125 console.log("GuangOutterThree:",this); 126 } 127 }; 128 129 console.log("----Guang.func GuangOutterOne---"); 130 Guang.GuangOutterOne(); 131 //輸出:GuangOutterOne: {name: "Guang", sex: "boy", GuangOutterOne: ƒ, GuangOutterTwo: ƒ, GuangOutterThree: ƒ} 132 //解析:作為對象的方法調用 133 134 //輸出: GuangOutterTwo: {name: "Guang", sex: "boy", GuangOutterOne: ƒ, GuangOutterTwo: ƒ, GuangOutterThree: ƒ} 135 //解析: GuangOutterOne 中的 this 指向 Guang 調用 Guang 中的 GuangOutterTwo 方法 136 137 //輸出: GuangOutterThree: {name: "Guang", sex: "boy", GuangOutterOne: ƒ, GuangOutterTwo: ƒ, GuangOutterThree: ƒ} 138 //解析: that 保留對 this 的引用 調用 Guang 中的 GuangOutterTwo 方法 139 140 141 </script> 142 143 <script> 144 console.log("JS 是基於詞法作用域的語言,函數在定義它的作用域中執行,而不是在調用它的作用域中執行"); 145 console.log("箭頭函數:this與封閉詞法上下文的this保持一致(即this 被設置為他被創建時的上下文)"); 146 var foo=(()=>this); 147 /* 148 可以把箭頭函數看成是 149 var foo=function(){ 150 //other code 151 return this; 152 //此處this所在的函數被創建時是在全局環境中 因為 this被設置為他被創建時的上下文 所以 this就被設置為window 153 }; 154 */ 155 // 由下可見 無論如何,foo 中的 this 都被設置為他被創建時的上下文(在上面的例子中,就是全局對象) 156 // 註意:對於箭頭函數 如果將this傳遞給call、bind、或者apply,它將被忽略 不過你仍然可以為調用添加參數,不過第一個參數(thisArg)應該設置為null 157 var obj = {foo: foo}; 158 console.log("直接調用:",foo()===window,", call調用:",obj.foo() === window,", apply調用:",foo.call(obj) === window,", bind綁定:",foo.bind(obj)() === window); // true true true true 159 160 //這同樣適用於在其他函數內創建的箭頭函數:這些箭頭函數的this被設置為封閉的詞法上下文的 161 console.log("-----------About John ------------------"); 162 var John={ 163 name:"John", 164 johnOutter:function(){ 165 //console.log("johnOutter",this);//johnOutter中的this具體情況可參考上面的Amy和Mike實例 166 var x=(()=>this); 167 //此處this所在的函數被創建時是在johnOutter中 因為 this被設置為他被創建時的上下文 所以 this就被設置為 johnOutter 函數中的this 168 return x; 169 } 170 } 171 172 var fn=John.johnOutter();//獲取返回的函數 若去掉johnOutter中console.log語句的註釋 輸出:John 解析:解析:作為對象的方法調用 173 console.log("John.johnOutter():",fn()); 174 //輸出:John.johnOutter(): Object { name: "John", johnOutter: johnOutter() } 175 //解析:此時johnOutter函數由John調用 所以johnOutter函數中的this為John,而箭頭函數的this被設置為johnOutter的this 176 177 var quote=John.johnOutter;//獲取John.johnOutter函數的引用 178 console.log("quote:",quote()()); 179 //輸出:window 180 //解析:此時quote獲取johnOutter的引用,quote()相當於簡單調用,所以johnOutter函數中的this為window,而箭頭函數的this被設置為johnOutter的this 181 182 /** 183 * 對於箭頭函數: 184 * 1、確定箭頭函數是在哪個執行環境中被創建的 185 * 2、根據執行環境確定this被設置為哪個執行環境 186 * 3、最後對函數的調用參考對象中的方法調用即可 187 * 總結可以簡單理解為: 188 * 箭頭函數的this在全局執行上下文創建時 它的this就是全局上下文中的this 189 * 箭頭函數的this在全局執行上下文創建時 它的this就是全局上下文中的this 190 */ 191 192 </script> 193 194 </body> 195 </html>
JS 中的 this 總結