javascript中的this學習起來相對複雜,最近花了點時間研究,總結起來大概這隻有5種狀況,相信只要熟悉這5種用法,基本是能夠解決全部的this問題,文本不介紹this設計原理,只介紹用法,閱讀本文,你須要瞭解javascript執行上下文環境,博主寫這種文章的目的,主要仍是給本身作下筆記,後續也會輸出javascript的學習筆記。javascript
全局代碼中的this ,永遠是window。html
//全局環境下,this永遠是window。 console.info(this === window);// true //定義全局對象的屬性 this.cat = '貓'; // global.cat = '貓' console.info(cat); // 貓 //給一個無標示符變量賦值 dog = '狗'; console.info(this.dog); // '狗' //經過變量聲明 var bird = '鳥'; console.info(this.bird); // '鳥'
調用普通函數中的this,永遠是window。java
function fn1() { this.cat = '包子' console.info(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} console.info(this.cat);//包子 } fn1()
this做爲對象的屬性值,永遠是window。小程序
let obj = { cat : '貓寶寶', cat_father : this, cat_self : this.cat } console.info(obj.cat_father);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} console.info(obj.cat_self);//undefined
其它注意:任什麼時候候不能改變this的值。app
//報錯,任什麼時候候不能改變this的值 this = '鳥'
函數做爲構造函數用,那麼其中的this就表明它即將new出來的對象。函數
function Fn2() { this.cat = '包子', this.dog = '餃子' console.info(this);//Fn2 {cat: "包子", dog: "餃子"} } let fn2 = new Fn2(); console.info(fn2.cat);//包子 console.info(fn2.dog);//餃子
在構造函數的prototype中,this表明函數即將new出來的對象。post
function Fn3() { this.cat = '包子' } Fn3.prototype.getItem = function(){ return this.cat; } let fn3 = new Fn3(); console.info(fn3.getItem());//包子
其實,不單單是構造函數的prototype,即使是在整個原型鏈中,this表明的也都是當前對象的值。學習
函數做爲對象的一個屬性被調用,函數中的this指向調用它的對象。加深紅色的這句話很是關鍵,必定要記住!必定要記住!必定要記住!。this
let obj = { cat : '貓寶寶', fn : function(){ console.info(this === obj);//true console.info(this.cat);//貓寶寶 } } obj.fn()
又如小程序中,使用Page(Object) 函數用來註冊一個頁面,接受一個 Object 類型參數,那麼this指向該Objectspa
Page({ data: { version: '1.0.1', cat:'張老闆他妹' }, onLoad: function () { console.info(this.data);//{version: "1.0.1", cat: "張老闆他妹"} } })
在函數中this到底取何值,是在函數真正被調用執行的時候肯定的,函數定義的時候肯定不了。由於this的取值是執行上下文環境的一部分,每次調用函數,都會產生一個新的執行上下文環境,但最終函數中的this指向調用它的對象
let obj = { cat: '大貓', fn: function () { console.info(this.cat) } }; //fn函數做爲obj對象的一個屬性被調用,在obj環境中執行,函數中的this指向該對象 obj.fn() // 大貓 var fn_new = obj.fn; var cat = '小貓';//全局環境的cat //fn函數賦值給變量fn_new的時候並無執行,此時this指向window,那麼執行fn_new()時,this.cat對應取值爲window.cat fn_new() // 小貓
再來一個例子,對象的中嵌套子對象,子對象的屬性值爲函數,函數被子對象調用,那麼函數中的this指向子對象,也就是函數中的this指向調用它的對象)
let obj = { cat: '大貓', obj_in: { fn: function () { console.info(this.cat) //undefined } } } //fn函數是被obj_in對象所調用,因此this指向的也obj_in對象 obj.obj_in.fn();
最後一個例子,對象的屬性爲函數,函數中嵌套函數,this放在嵌套函數中的狀況
let obj = { cat : '貓', fn : function(){ function fn_in(){ console.info(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} console.info(this.cat);//undefined } //執行fn函數後,嵌套函數fn_in在fn環境中執行,回到文章中說的第一種狀況,此時fn_in是普通函數,則它的this指向window fn_in(); } } obj.fn()
當一個函數被call和apply調用時,this的值就取傳入的對象的值。
let obj1 = { baobao : '貓' } let obj2 = { baobao : '羊' } let obj3 = { baobao : '鵝' } let fn3 = function(){ console.info(this.baobao); } fn3.apply(obj1);//貓 fn3.call(obj2);//羊 fn3.bind(obj3)();//鵝
同函數做爲對象的一個屬性被調用同樣,函數fn4_in是在obj.fn4內部定義的,因此它仍然是一個普通的函數,this仍然指向window。
let obj3 = { baobao : '貓' } let fn4 = function(){ function fn4_in(){ console.info(this.baobao);//undefined } fn4_in() } fn4.apply(obj3);
參考資料
http://www.ruanyifeng.com/blog/2018/06/javascript-this.html
http://www.cnblogs.com/TomXu/archive/2012/01/17/2310479.html