.call() 和 .apply()函数用于在调用函数时改变上下文。这给了你令人难以置信的编程能力(和一些终极权限来驾驭代码)。 要使用call或apply函数,您只需要在函数上调用它,而不是使用一对括号调用函数,并将新的上下文作为第一个参数传递。 函数自己的参数可以在上下文之后传递。(愚人码头注:call或apply用另一个对象来调用一个方法,将一个函数上下文从初始的上下文改变为指定的新对象。简单的说就是改变函数执行的上下文。)
function hello() {
// do something...
}
hello(); // 通常的调用方式
hello.call(context); // 在这里你可以传递上下文(this 值)作为第一个参数
hello.apply(context); // 在这里你可以传递上下文(this 值)作为第一个参数
.call()和.apply()之间的区别在于,在.call()中,其余参数作为以逗号分隔的列表,而.apply()则允许您在数组中传递参数。
function introduce(name, interest) {
console.log('Hi! I\'m '+ name +' and I like '+ interest +'.');
console.log('The value of this is '+ this +'.')
}
introduce('Hammad', 'Coding'); // 通常的调用方式
introduce.call(window, 'Batman', 'to save Gotham'); // 在上下文之后逐个传递参数
introduce.apply('Hi', ['Bruce Wayne', 'businesses']); // 在上下文之后传递数组中的参数
// 输出:
// Hi! I'm Hammad and I like Coding.
// The value of this is [object Window].
// Hi! I'm Batman and I like to save Gotham.
// The value of this is [object Window].
// Hi! I'm Bruce Wayne and I like businesses.
// The value of this is Hi.
.call()的性能要比.apply()稍快。
以下示例将文档中的项目列表逐个记录到控制台。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Things to learn</title>
</head>
<body>
<h1>Things to Learn to Rule the World</h1>
<ul>
<li>Learn PHP</li>
<li>Learn Laravel</li>
<li>Learn JavaScript</li>
<li>Learn VueJS</li>
<li>Learn CLI</li>
<li>Learn Git</li>
<li>Learn Astral Projection</li>
</ul>
<script>
// 在listItems中保存页面上所有列表项的NodeList
var listItems = document.querySelectorAll('ul li');
// 循环遍历listItems NodeList中的每个节点,并记录其内容
for (var i = 0; i < listItems.length; i++) {
(function () {
console.log(this.innerHTML);
}).call(listItems[i]);
}
// Output logs:
// Learn PHP
// Learn Laravel
// Learn JavaScript
// Learn VueJS
// Learn CLI
// Learn Git
// Learn Astral Projection
</script>
</body>
</html>
HTML仅包含无序的项目列表。然后 JavaScript 从DOM中选择所有这些项目。列表循环,直到列表中的项目结束。在循环中,我们将列表项的内容记录到控制台。
该日志语句包裹在一个函数中,该 call 函数包含在调用函数中的括号中。将相应的列表项传递给调用函数,以便控制台语句中的 this 关键字记录正确对象的 innerHTML 。
对象可以有方法,同样的函数对象也可以有方法。 事实上,JavaScript函数附带了四种内置方法:
Function.prototype.apply()
Function.prototype.bind() ( ECMAScript 5 (ES5) 中引进)
Function.prototype.call()
Function.prototype.toString()
Function.prototype.toString() 返回函数源代码的字符串表示形式。
与 .call() 和 .apply()不同,.bind() 本身不调用该函数,它只能用于在调用函数之前绑定上下文和其他参数的值。在上面的一个例子中使用 .bind() :
(function introduce(name, interest) {
console.log('Hi! I\'m '+ name +' and I like '+ interest +'.');
console.log('The value of this is '+ this +'.')
}).bind(window, 'Hammad', 'Cosmology')();
// logs:
// Hi! I'm Hammad and I like Cosmology.
// The value of this is [object Window].
.bind() 就像.call()函数一样,它允许你传递其余的参数,用逗号分隔,而不是像apply,在数组中传递参数。