【原】javascript學習筆記之this用法
javascript中的this學習起來相對複雜,最近花了點時間研究,總結起來大概這隻有5種情況,相信只要熟悉這5種用法,基本是可以解決所有的this問題,文字不介紹this設計原理,只介紹用法,閱讀本文,你需要了解javascript執行上下文環境,博主寫這種文章的目的,主要還是給自己做下筆記,後續也會輸出javascript的學習筆記。
全域性程式碼中的this & 呼叫普通函式中的this & this作為物件的屬性值
全域性程式碼中的this ,永遠是window。
//全域性環境下,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。
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的值。
//報錯,任何時候不能改變this的值 this = '鳥'
建構函式中this
所謂建構函式就是用來new物件的函式。其實嚴格來說,所有的函式都可以new一個物件,但是有些函式的定義是為了new一個物件,而有些函式則不是。另外注意,建構函式的函式名第一個字母大寫(規則約定)。例如:Object、Array、Function等。
函式作為建構函式用,那麼其中的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);//餃子
原型鏈中this
在建構函式的prototype中,this代表函式即將new出來的物件。
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指向該Object
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) } }; var fn_new = obj.fn; var cat = '小貓';//全域性環境的cat //fn函式作為obj物件的一個屬性被呼叫,在obj環境中執行,函式中的this指向該物件 obj.fn() // 大貓 //fn_new函式被呼叫執行時,在全域性環境即window執行,此時this指向window,那麼this.cat全域性環境的cat fn_new() // 小貓
再來一個例子,物件的屬性為函式,函式中巢狀函式,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或bind呼叫
當一個函式被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
http://www.cnblogs.com/wangfupeng1988/p/3988422.html