一. 前言
此篇文档主要用来对call,apply以及bind的学习成果进行汇总。
bind是返回对应函数,便于稍后调用;call,apply则是立即调用。
二. 先来学习一下call,apply
在JavaScript中,call以及apply都是为了改变某个函数运行时的上下文(context),换句话说就是为了改变函数内部this的指向而存在的。
JavaScript的一大特点就是,函数存在定义时上下文,运行时上下文以及上下文可以改变这样的概念。
function Fruits() { };
Fruits.prototype = {
color: 'red',
say: function () {
console.log(this);
console.log('my color is' + this.color);
}
}
var apple = new Fruits();
// this 指向 Fruits{}
apple.say(); // my color is red
现有banana想要也想实现say()方法,但是我们不想重新定义,就可以通过call或apply使用apple的say()方法
const banana = {
color: 'yellow'
}
// this 指向 banana{color:'yellow'}
apple.say.apply(banana); // my color is yellow
由此可见:
cally以及apply都是为了动态改变this而出现的,当一个object没有某个方法而另外一个object有的时候,就可以借助call或apply来实现了!
三. call、apply的区别
对于call、apply来说,作用完全是一样的,只是接受的参数格式不同。
var func = function(arg1, arg2) { ... }
// this是你想要指定的上下文,可以是任何一个JavaScript对象。
func.call(this, arg1, arg2); // call需要把参数按照顺序传递进去
func.apply(this, [arg1, arg2]) // apply则是把参数放到数组里面
四. 使用call、apply的例子
数组追加
var array1 = [12, "foo", { name: "Joe" }, -2458];
var array2 = ["Doe", 555, 100];
Array.prototype.push.apply(array1, array2);
console.log(array1); // [12, "foo", {…}, -2458, "Doe", 555, 100]
获取数组中的最大值与最小值
var numbers = [5, 34, 56, 23];
var maxNumber = Math.max.apply(Math, numbers);
console.log(maxNumber); // 56
验证是否是数组
function isArr(arr) {
return Object.prototype.toString.call(arr) === '[object Array]'
}
const array = [1, 2, 3, 4];
console.log(isArr(array)); // true
类(伪)数组使用数组的方法
var domNodes = Array.prototype.slice.call(document.getElementsByTagName('div'));
关于伪数组:
JavaScript中存在一种名为伪数组的对象结构,像:arguments对象,还有像调用getElementsByTagName…,它们返回的都是NodeList对象,都是伪数组。这类是无法使用数组的push…等方法的。
但是,我们可以通过使用 Array.prototype.slice.call() 转化为真正的数组。
四. bind
bind()方法和call、apply很相似,都是为了改变函数体内this的指向。
var write = document.write;
// write函数改变this的指向为全局window!
write('王晓雯'); // Illegal invocation
// 使用bind纠正
write.bind(document)('wxw');
write.call(document, 'wxw');
this.num = 9;
var myMoudle = {
num: 80,
getNum: function () {
console.log(this.num, this);
}
}
myMoudle.getNum(); // 80 myModle{... }
var getNum = myMoudle.getNum;
getNum(); // 9 window
// 使用bind 可以纠正this的指向为原来的的对象!
getNum.bind(myMoudle)(); // 80 myModle{... }
五. call、apply、bind的区别
var obj = {
x: 90
}
var foo = {
getX: function() {
return this.x
}
}
console.log(foo.getX()); // undefined
console.log(foo.getX.bind(obj)()); // 90
console.log(foo.getX.call(obj)); // 90
console.log(foo.getX.call(obj)); // 90
call、apply、bind都能改变this的指向,区别是:当你希望改变上下文环境后而非立即执行,而是回调执行的时候,就可以使用bind()方法,而call、apply则会立即执行。
再总结一下:
call、apply、bind三者都是用来改变函数体内this的指向的
call、apply、bind三者的第一个参数都是this要指向的对象,也就是想指定的上下文
call、apply、bind三者都可以利用后续的参数传真
bind是返回对应的函数,方便后续调用;apply、call则是立即执行