1. 程式人生 > >Javascript學習---函式內建方法call/apply

Javascript學習---函式內建方法call/apply

Javascript預設為每個函式提供了call()和apply()用來設定函式的上下文物件


call()

call()方法的具體語法內容如下:

func.call(context, arg1, arg2, ...)

其中context是上下文物件;arg1,arg2,...是函式func的引數,以列表的形式接受


這裡是一個例子:

function say(phrase) {
  alert(this.name + ': ' + phrase);
}

let user = { name: "John" };
let admin = { name: "Admin" };

// user becomes this, and "Hello" becomes the first argument
say.call( user, "Hello" ); // John: Hello
say.call( admin, "Hello" ); // Admin: Hello

此時因為call()傳遞給say()的上下文物件為user或者admin,故say()中的this所指向的上下文物件就為user或admin


apply()

apply()的用法和call()很像,具體語法如下:

func.apply(context, args)
與call()不同的是,apply()的第二個引數args接受的是函式引數所組成的陣列,看下面例子:
function say(time, phrase) {
  alert(`[${time}] ${this.name}: ${phrase}`);
}

let user = { name: "John" };

let messageData = ['10:00', 'Hello']; // become time and phrase

// user becomes this, messageData is passed as a list of arguments (time, phrase)
say.apply(user, messageData); // [10:00] John: Hello (this=user)

apply()和call()不同的是,call()接受的是函式引數的列表,而apply()接受的是函式引數的陣列形式,如下:

let args = [1, 2, 3];

func.call(context, ...args); // pass an array as list with spread operator
func.apply(context, args);   // is same as using apply
上面例子的最終效果是一樣的,我們已經知道rest引數的拓展操作可以將陣列等可迭代物件轉換為列表,故這裡使用...args來進行轉換args陣列


借用別的物件的方法

call()和apply()除了設定上下文物件外,還可以用來呼叫其他物件的方法,先看下面例子:

function hash() {
  alert( arguments.join() ); // Error: arguments.join is not a function
}

hash(1, 2);

這裡arguments.join()報錯了,因為arguments引數是函式的預設內建引數,其中包含了函式的所有輸入引數,然而它是類陣列和可迭代的物件,不是真正的陣列物件,故使用jion()這個陣列專有的方法就會報錯(join()以字串的形式返回陣列的內容)。為了解決這個問題,我們可以使用call()或者apply()來借用陣列物件的方法,例如:

function hash() {
  alert( [].join.call(arguments) ); // 1,2
}

hash(1, 2);
這裡join()的上下文物件被設定為arguments,join()內部原理是迭代陣列物件每一個元素並將元素內容拼接到一個字串中,再返回,所以[].join.call(arguments)可以正常工作