iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
自我挑戰組

JavaScript 核心觀念系列 第 28

【Day28】this - call, apply, bind 與嚴謹模式

call, apply, bind 方法

當我們對函式使用 call, apply, bind 這三種方法時,能改變 this 的值

簡易呼叫

先來看一般的函式呼叫

var family = {
    myName: 'weiwei',
};

function fn(para1, para2){
    console.log(this, para1, para2);
};

fn(1, 2);

此時函式內的 this 是指向全域,這在昨天的文章有解釋

call()

使用 call() 時,在 () 中第一個要代入 this 的值,隨後才將參數代入

var family = {
    myName: 'weiwei',
};

function fn(para1, para2){
    console.log(this, para1, para2);
};

fn.call(family, 1, 2);

在範例中,我們將 this 指向 family 這個物件,

12 是做為參數代入函式中,

因此函式中的 this 會回傳 family

para1para2 則分別回傳 12

apply()

apply() 中第一個參數也是帶入 this 的值,隨後使用 [] 將函式的參數代入

var family = {
    myName: 'weiwei',
};

function fn(para1, para2){
    console.log(this, para1, para2);
};

fn.apply(family, [3, 4]);

該範例 this 是指向 family 這個物件,

而函式的參數 para1para2 的值為 [] 中的 34

使用上跟 call() 差不多

bind()

我們使用 bind() 時,我們會將它賦予到變數中,

() 內第一個參數也是代入 this 的值,隨後代入函式的參數

var family = {
    myName: 'weiwei',
};

function fn(para1, para2){
    console.log(this, para1, para2);
};

var fn2 = fn.bind(family, 5, 6);

fn2();

在昨天的文章中有提到,當我們使用 Simple Call 時,this 會指向全域,

而範例中 fn2() 是因為在 bind() 中,就已經將 this 指向 family 物件,

因此在執行 fn2() 時,this 會指向 family

而此時我們也能將參數放到 fn2()

var family = {
    myName: 'weiwei',
};

function fn(para1, para2){
    console.log(this, para1, para2);
};

var fn2 = fn.bind(family);

fn2(7, 8);

進階觀念

一般來說 this 會以物件形式呈現,

而在非嚴謹模式下的函式中,

當我們在 call() 的第一個參數代入原始型別時,

則會將原始型別的值進行封裝,封裝後的型別為 object

但如果帶入 nullundefined 時,

this 會指向全域,這在 MDN 文件中有說明

function fn(para1, para2){
    console.log(this, typeof this, para1, para2);
};

fn.call(1, 1, 2);
fn.call('weiwei', 1, 2);
fn.call(undefined, 1, 2);

嚴謹模式

以下列出嚴謹模式的特點

我們直接看範例

(function(){
    'use strict'
    a = 10;
})();

此執會看見 a is not defined

在嚴謹模式下會要求你先宣告變數,才能做賦予值的動作

當我們拿掉 'use strict' 時,則不會出錯

(function(){
    a = 10;
})();

接著我們在函式中加入 'use strict',使用 call() 看結果如何

function fn(para1, para2){
    'use strict';
    console.log(this, typeof this, para1, para2);
};

fn.call(1, 1, 2);

此時能看見在嚴謹模式下,如果 this 代入原始型別,其值不會被改為建構式,

那如果我們代入 undefined 會如何呢?

function fn(para1, para2){
    'use strict';
    console.log(this, typeof this, para1, para2);
};

fn.call(undefined, 7, 8);

此時 this 的值會是 undefined,而在非嚴謹模式下會指向全域,

接著我們使用簡易呼叫來看 this 的值會如何

function fn(para1, para2){
    'use strict';
    console.log(this, typeof this, para1, para2);
};

fn(9, 'weiwei');

在非嚴謹模式中函式的 this 是指向全域,

但此時能看見在嚴謹模式下函式的 thisundefined

而我們使用簡易呼叫時,概念跟使用 call() 很像,

只差別在簡易呼叫不會傳入 this 的值,此時的 this 就會是 undefined

因此我們我可以知道 this 的本質是 undefined

所以一般不太建議使用簡易呼叫中的 this

關於更多嚴謹模式的說明可到MDN 文件查看

以上是今天 call, apply, bind 與嚴謹模式的內容,感謝觀看!!


上一篇
【Day27】this - 簡易呼叫(Simple Call)
下一篇
【Day29】this - DOM
系列文
JavaScript 核心觀念30

尚未有邦友留言

立即登入留言