浅谈JavaScript中call,apply,bind方法以及它们的适用场景
其实在第一次工作面试中,就被问道了这个问题,这也是一道面试常见题。想起来就抽出时间整理一下它们三个的来历、区别和简单的适用场景吧。正文分割线call、apply、bind方法的由来 在js中,所有的函数都是Function的实例,大家应该都对原型链有所了解,对Function而言,call、apply、bind就是Function.prototype上的方法(原型方法),根据原型链的规则,所
其实在第一次工作面试中,就被问道了这个问题,这也是一道面试常见题。想起来就抽出时间整理一下它们三个的来历、区别和简单的适用场景吧。
正文分割线
- call、apply、bind方法的由来
在js中,所有的函数都是Function的实例,大家应该都对原型链有所了解,对Function而言,call、apply、bind就是Function.prototype
上的方法(原型方法),根据原型链的规则,所有的函数(Function实例)都可以使用它原型链上的方法,因此也就包含了这三个方法。
简单来说:call/apply/bind都是Function原型链上的方法,而所有函数都是它的实例。 - call、apply、bind方法的作用
其实不要想的太复杂,它们三个有一个共同的’任务‘ –改变this指向
,即通过一个指定对象来调用一个函数,接下来我们通过代码来解释。
function getInfo(age){
return '我的姓名是'+this.name+'我的年龄'+age
}
上面代码中,如果我以getInfo(18)
来直接调用,返回结果=>我的姓名是 我的年龄18
因为函数在寻找this.name
时并没有找到,所以this.name为undefined
接下来我们定义一个对象来调用函数:
function getInfo(age){
return '我的姓名是'+this.name+'我的年龄'+age
}
let person = {
name:'xiaoming',
sex:'男'
}
//通过person对象调用getInfo方法
getInfo.call(person,18)
getInfo.apply(person,[18])
getInfo.bind(person,18)()
// 上述三种不同的写法,返回值相同
// return: 我的姓名是xiaoming,我的年龄18
上述代码中我们看到,person并没有getInfo方法,我们通过改变getInfo内部this指向到对象person
上,因此getInfo找到了person的name属性。
当然如果我们直接调用person.getInfo()会报错(见下面代码块)
function getInfo(age){
return '我的姓名是'+this.name+'我的年龄'+age
}
let person = {
name:'xiaoming',
sex:'男'
}
getInfo.call(person,"男");//姓名为张三,性别为男
getInfo("男");//姓名为undefined,性别为男
person.getInfo("男");//报错
通过上面的代码演示,想必读者对改变this指向
都有了一定的理解,下面我们要说的是call / apply / bind 三者的区别
- call、apply、bind三者区别
它们在功能上其实是一样的 – 改变this指向,区别在于功能实现形式和参数传递方法上。
fun.call(对象,arg1,arg2,...) // call()的第一个参数为this指定的对象,后面是fun的参数
fun.apply(对象,[arg1,arg2,...] // apply()的第一个参数为this制定的对象,第二个参数需要为数组,接收fun的参数
fun.bind(对象,arg1,arg2,...)() // 与前两者不同,bind返回的是一个函数体,因此需要()进行调用,参数和call相同
// 三者的具体实现案例请回看第二段代码
对三者的介绍大概就到此为止了,如果对this
还不了解的小伙伴需要先去巩固一下基础啦!
接下来让我们聊一下它们的适用场景
- call、apply、bind使用场景
- Object.prototype.toString.call(obj)方法:通过Object原型上的toString方法来判断传入对象类型,详细讲解请移步文章浅谈Object.prototype.toString.call(obj)功能及原理
- Math.max.call(Math,arr)方法计算数组最大值,最小值同理
let arr = [1,4,6,3,86,34]
let max = Math.max.apply(Math,arr)
console.log(max) // 86
//直接使用 Math.max(...arr)解构数组也可以达到相同效果
- 实现继承:
function peaple(name) {
this.name = name;
this.showName = function () {
console.log(this.name);
}
}
function student(name) {
peaple.call(this, name);
}
var xiaoming = new student('xiaoming');
xiaoming.showName();
案例中,call()提供了新的this值给当前调用的函数/方法,也就是说call方法将原本peaple的this对象替换成了student的this对象。
- 数组追加:
var array1 = [1 , 2 , 3, 5];
var array2 = ["xie" , "li" , "qun" , "tsrot"];
Array.prototype.push.apply(array1, array2);
console.log(array1);
- 保存this变量:
var foo = {
bar : 1,
eventBind: function(){
var _this = this ;
$('.someClass').on('click',function(event) {
console.log(_this.bar);
});
}
}
var foo = {
bar : 1,
eventBind: function(){
$('.someClass').on('click',function(event) {
console.log(this.bar);
}.bind(this));
}
}
本次分享到此结束,如有错误请指正,望共同进步!!!
更多推荐
所有评论(0)