【原】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

函數作爲構造函數用,那麼其中的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指向調用它的對象,加深紅色的這句話非常關鍵。

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) 
    }
};
//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或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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章