介绍
欲想深入call、apply 、bind,必现了解函数及其this
this就是日常我们代码中调用函数的主体对象
举个例子:
```javascript
var obj = {
foo: function(){
console.info("this===>",this)
}
}
var bar = obj.foo
obj.foo() // f打印出的this 就是obj
bar() // 打印出的this 就是window
// 简单来讲就是谁调用函数this就指向谁
```
那么通常函数的调用方式有那些以及区别和联系呢
* 作为函数调用myFun\(a,b\)
* 作为对象方法调用obj.objFun\(\)
* 作为构造函数调用 let Bar = new Animal\("cat"\)
* 作为函数的方法调用 myFun.call\(content,a,b\)
一般我们会很熟悉前面三中方式,但是最后一种myFun.call\(content,a,b\)才是正常的调用形式\(基础形式\),前面的方式都是在这一种方式上封装好的语法糖;
```
//myFun(a,b) ---> myFun.call(undefined,a,b);
//obj.objFun() ---> obj.objFun.call(obj);
因此this也就是我们上面式子中的content-->call的第一个参数
```
call apply bind的三者的异同
相同点
* 都能用于改变this的指向问题
* 三者的第一个参数都是this要指向的对象,也就是指定的上下文(content)
* 三者都可以利用后续传入参数
不同点
* bind的返回值是一个新的函数,加上调用才能被执行
* bing方法会创建一个新函数称为绑定函数
* bind返回对应函数,便于稍后调用;而call和apply都是立即调用
* call是针对于已知,逐步转入参数方便 apply时后续参数是以数组的方式
* bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。
```
var module = {
x: 42,
getX: function() {
console.log('this', this)
return this.x;
}
}
var unboundGetX = module.getX;
console.log(module.getX) // 直接是对函数的引用, this没有指定,this 为 window
console.log(module.getX()) // 使用对象module调用函数,所以this就是module
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
var boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
```
* call 的作用无非就是当执行一个方法的时候希望能够使用另一个对象来作为作用域对象而已,简单来说就是当我执行 A 方法的时候,希望通过传入参数的形式将一个对象 B 传进去,用以将 A 方法的作用域对象替换为对象 B
```
// 定义: 调用一个对象的方法,以另一个对象作为当前对象
// call的使用方法
// call修改的方式采用的是代入法
//父类 Person
function Person() {
this.sayName = function() {
return this.name;
}
}
//子类 Chinese
function Chinese(name) {
//借助 call 实现继承
Person.call(this);
this.name = name;
this.ch = function() {
alert('我是中国人');
}
}
//测试
var chinese = new Chinese('成龙'); // 调用 父类方法
console.log(chinese.sayName()); //输出 成龙
```
* apply方法让我们构建一个参数数组给调用函数,它也允许我们选择this的值
* apply接受两个参数,第一个是要绑定给this的值,第二个就是一个参数数组
* 当第一个参数为null、undefined的时候,默认指向window
```
// apply的方法
function add(a, b) {
this.a = a;
this.b = b;
this.alert = function () {
alert(this.a + this.b)
}
}
function test() {
add.apply(this, [5, 5]) //这里可以理解为 test函数中this等于add函数中的this
}
var c = new test()
c.alert() //10
```
应用场景
日常我们在开发中,也许好多小伙伴不是很习惯或者很少使用,其实他们会有很多的使用小技巧
* 工具类文件中的数据最大值和最小值
```
let basicTools = {
arrMaxOrMin:function(type,arr){
let result = Math[type].apply(null,arr);
return result;
}
}
console.info("最大值",basicTools.arrMaxOrMin("max",[1,2,3])) // 输出为3
console.info("最小值",basicTools.arrMaxOrMin("min",[1,2,3])) // 输出为1
```
* 简单数据类型的数组追加
```
let basicTools = {
arrAppendItem:function(arr1,arr2){
return arr1.push.apply(arr1,arr2);
}
}
```
为了帮助大家让学习变得轻松、高效,给大家免费分享一大批资料,帮助大家在成为全栈工程师,乃至架构师的路上披荆斩棘。在这里给大家推荐一个前端全栈学习交流圈:??947552909.,或者?wx:fxq1221623?欢迎大家进群交流讨论,学习交流,共同进步。
有些人对学习充满激情,但是缺少方向,而在浩瀚的知识海洋中看似无边无际,此时最重要的是要知道哪些技术需要重点掌握,避免做无用功,将有限的精力及状态发挥到最大化。
最后祝福所有遇到瓶颈且不知道怎么办的前端程序员们,祝大家在往后的工作与面试中一切顺利。