JavaScript中的this

字號+ 編輯: 种花家 修訂: 种花家 來源: 腾讯QQ兴趣部落 2023-09-10 我要說兩句(0)

在js中,this這個上下文總是變化莫測,很多時候出現bug總是一頭霧水,其實,只要分清楚不同的情況下如何執行就ok了。

全局執行

首先,我們在全局環境中看看它的 this 是什麽:

first. 瀏覽器:

console.log(this);// Window
{
    speechSynthesis: SpeechSynthesis,
    caches: CacheStorage,
    localStorage: Storage,
    sessionStorage: Storage,
    webkitStorageInfo: DeprecatedStorageInfo…
}

  可以看到列印出了 window 對象;

  second. node:

console.log(this);// global

  可以看到列印出了 global 對象;

  總結:在全局作用域中它的 this 執行當前的全局對象(瀏覽器耑是 Window,node 中是 global)。

函數中執行

var obj = {
    name: 'qiutc',
    foo: function() {
        console.log(this);
    },
    foo2: function() {
        console.log(this);
        setTimeout(() => {
            console.log(this);  // Object
            {name: "qiutc"}
        }, 1000);
    }
}
obj.foo2();

函數體内的this對象,就是定義時所在的對象,而不是使用時所在的對象。

根據例子我們理解一下這句話:

在 obj.foo2() 執行的時候,當前的 this 指向 obj;在執行 setTimeout 時候,我們先是定義了一個匿名的箭頭函數,關鍵點就在這,箭頭函數内的this 執行定義時所在的對象,就是指向定義這個箭頭函數時作用域内的 this,也就是 obj.foo2 中的 this,即 obj;所以在執行箭頭函數的時候,它的this->obj.foo2中的this->obj;

就問你, 繞不繞吧?

5ba02b3ccda14b5d69b8af9eef43978b.jpg

簡單來說, 箭頭函數中的 this 只和定義它時候的作用域的 this 有關,而與在哪裡以及如何調用它無關,同時它的 this 指向是不可改變的。

call, apply, bind

在 js 中,函數也是對象,同樣也有一些方法,這裡我們介紹三個方法,他們可以更改函數中的 this 指向:

apply

fun.apply(thisArg[, [arg1, arg2, ...]])

它會立即執行函數,第一個參數是指定執行函數中 this 的上下文,第二個參數是一個數組,是傳給執行函數的參數(與 call 的區別);

bind

var foo = fun.bind(thisArg[, arg1[, arg2[, ...]]]);

它不會執行函數,而是返回一個新的函數,這個新的函數被指定了 this 的上下文,後面的參數是執行函數需要傳入的參數;

這三個函數其實大同小異,總的目的就是去指定一個函數的上下文(this),我們以 call 函數爲例;

爲一個普通函數指定 this

var obj = { name: 'qiutc' };
function foo() {
    console.log(this);
}
foo.call(obj); // Object {name: "qiutc"}

可以看到,在執行 foo.call(obj) 的時候,函數内的 this 指向了 obj 這個對象,成功;

爲對象中的方法指定一個 this

var obj = {
    name: 'qiutc',
    foo: function () {
        console.log(this);
    }
}
var obj2 = {
    name: 'tcqiu222222'
};
obj.foo.call(obj2);// Object {name: "tcqiu222222"}

可以看到,執行函數的時候這裡的 this 指向了 obj2,成功;

爲構造函數指定 this

function Person(name) {
    this.name = name;
    console.log(this);
}
var obj = {
    name: 'qiutc2222222'
};
var p = new Person.call(obj, 'qiutc');// Uncaught TypeError: Person.call is not a constructor(…)

這裡報了個錯,原因是我們去 new 了 Person.call 函數,而非 Person ,這裡的函數不是一個構造函數;

換成 bind 試試:

function Person(name) {
    this.name = name;
    console.log(this);
}
var obj = {
    name: 'qiutc2222222'
};
var Person2 = Person.bind(obj);
var p = new Person2('qiutc');// Person {name: "qiutc"}console.log(obj);// Object {name: "qiutc2222222"}

列印出來的是 Person 實例化出來的對象,而和 obj 沒有關係,而 obj 也沒有發生變化,說明,我們給 Person 指定 this 上下文並沒有生效;

因此可以得出: 使用 bind 給一個構造函數指定 this,在 new 這個構造函數的時候,bind 函數所指定的 this 並不會生效;

當然 bind 不僅可以指定 this ,還能傳入參數,我們來試試這個操作:

function Person(name) {
    this.name = name;
    console.log(this);
}
var obj = {
    name: 'qiutc2222222'
};
var Person2 = Person.bind(obj, 'qiutc111111');
var p = new Person2('qiutc');// Person {name: "qiutc111111"}

可以看到,雖然指定 this 不起作用,但是傳入參數還是起作用了;

 爲箭頭函數指定 this

我們來定義一個全局下的箭頭函數,因此這個箭頭函數中的 this 必然會指向全局對象,如果用 call 方法改變 this 呢:

var afoo = (a) => {
    console.log(a);
    console.log(this);
}
afoo(1);// 1// Window
var obj = {
    name: 'qiutc'
};
afoo.call(obj, 2);// 2// Window

可以看到,這裡的 call 指向 this 的操作並沒有成功,所以可以得出: 箭頭函數中的 this 在定義它的時候已經決定了(執行定義它的作用域中的 this),與如何調用以及在

閲完此文,您的感想如何?
  • 有用

    0

  • 沒用

    0

  • 開心

    0

  • 憤怒

    0

  • 可憐

    0

1.如文章侵犯了您的版權,請發郵件通知本站,該文章將在24小時内刪除;
2.本站標注原創的文章,轉發時煩請注明來源;
3.交流群: 2702237 13835667

相關課文
  • JS如何防止父節點的事件運行

  • nodejs編寫一個簡單的http請求客戶耑代碼demo

  • 使用Sublime Text3 開發React-Native的配置

  • 說一則爲什麽後耑開發人員不選擇node.js的原因

我要說說
網上賓友點評