浅谈JavaScript中call,apply,bind方法以及它们的适用场景

  其实在第一次工作面试中,就被问道了这个问题,这也是一道面试常见题。想起来就抽出时间整理一下它们三个的来历、区别和简单的适用场景吧。

正文分割线


  • 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使用场景
  1. Object.prototype.toString.call(obj)方法:通过Object原型上的toString方法来判断传入对象类型,详细讲解请移步文章浅谈Object.prototype.toString.call(obj)功能及原理
  2. 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)解构数组也可以达到相同效果
  1. 实现继承:

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对象。

  1. 数组追加:

var array1 = [1 , 2 , 3, 5];
var array2 = ["xie" , "li" , "qun" , "tsrot"];
Array.prototype.push.apply(array1, array2);
console.log(array1);

  1. 保存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));
    }
}

本次分享到此结束,如有错误请指正,望共同进步!!!

猜你喜欢

转载自blog.csdn.net/hanyanshuo/article/details/110222695