1. 程式人生 > >【原】javascript學習筆記之this用法

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