call,apply,bind用法以及常见作用

1 javascript 中 call,apply,bind用法,作用以及区别
2 call,apply,bind应用在setTimeout函数中
3 for循环嵌套setTimeout,setTimeout中重复执行for的最后一个值及解决方法

1 javascript 中 call,apply,bind用法,作用以及区别
call,apply,bind主要就是改变this的指向,或者说,强行调用其他对象的方法,来为自己服务

三者的用法:
call的参数是直接放进去的,第二第三第n个参数全都用逗号分隔,直接放到后面 obj.myFun.call(db,‘成都’, … ,‘string’ );

apply的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db,[‘成都’, …, ‘string’ ]);

bind除了返回是函数以外,它 的参数和call 一样。
举例子:(调用数组Array的方法)
Array.prototype.slice.call(arguments)。这里arguments 并不是一个真正的数组对象,只是与数组类似而已,所以它并没有slice这个方法,而Array.prototype.slice.call(arguments, 1)可以理解成让arguments转换成一个数组对象,让arguments具有slice()方法,要是直接写arguments.slice()会报错。

typeof arguments===“Object” //而不是 “Array”
Array.prototype.slice.call(arguments,[,arg1[arg2]])能将具有length属性的对象转成数组,尤其用于将伪类转换成真正的数组,但是旧版本的IE下用的时候会报错,因为HTMLCollection,NodeList不是Object的子类。

2 当你有一个对象,如果你想调用一个方法,但该方法,只有其他的对象才有,这时候可以通过bind,call,apply来实现
function Person(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
function Student(name,age,sex,tel,grade){
Person.call(this,name,age,sex);
this.tel=tel;
this.grade=grade;
}
var studnet= new Student(‘sunny’,123,‘male’,139,2017);

2 call,apply,bind应用在setTimeout函数中

setTimeout和setInterval中的this在非严格模式下,总是指向window(因为setTimeout是异步的代码,等到执行的时候,不一定程序已经运行到哪里了,所以当用this的时候,就不是同一个环境了)

var num = 0;
function Obj (){
    this.num = 1,
   this.getNumLater = function(){
        setTimeout(function(){
            console.log(this.num);
        }, 1000)
    }
}

obj.getNumLater()//0  打印的是window.num,值为0
所以怎样让this指向定义时的对象

1 将当前对象this存为一个变量,定时器内使用这个变量来进行引用

var num = 0;
function Obj (){
    const that = this;    //将this存为一个变量,此时的this指向obj
    this.num = 1,
 
    this.getNumLater = function(){
        setTimeout(function(){
            console.log(that.num);    //利用闭包访问that,that是一个指向obj的指针
        }, 1000)
    }
}
var obj = new Obj; 
obj.getNum();//1  打印的是obj.num,值为1
obj.getNumLater()//1  打印的是obj.num,值为1

2使用bind()方法是在Function.prototype上的一个方法,当被绑定函数执行时,bind方法会创建一个新函数,并将第一个参数作为新函数运行时的this。在这个例子中,在调用setTimeout中的函数时,bind方法创建了一个新的函数,并将this传进新的函数,执行的结果也就是正确的了。(这里不能使用call,apply,因为call,apply会立刻执行,所以定时器效果也就没有了)

var num = 0;
function Obj (){
    this.num = 1,
    this.getNum = function(){
        console.log(this.num);
    },
    this.getNumLater = function(){
        setTimeout(function(){
            console.log(this.num);
        }.bind(this), 1000)    //利用bind()将this绑定到这个函数上
    }
}
var obj = new Obj; 
obj.getNum();//1  打印的为obj.num,值为1
obj.getNumLater()//1  打印的为obj.num,值为1

3箭头函数
ES6中的箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj,因此利用箭头函数就可以轻松解决这个问题。

var num = 0;
function Obj (){
this.num = 1,
this.getNum = function(){
console.log(this.num);
},
this.getNumLater = function(){
setTimeout(() => {
console.log(this.num);
}, 1000) //箭头函数中的this总是指向外层调用者,也就是Obj
}
}
var obj = new Obj;
obj.getNum();//1  打印的是obj.num,值为1
obj.getNumLater()//1  打印的是obj.num,值为1

3 for循环嵌套setTimeout,setTimeout中重复执行for的最后一个值及解决方法

for(var i=0;i<10;i++){
setTimeout(function(){
console.log(i);
},1000);
}
以上的输出结果是10个10

解决方法,
1将for循环中的var 写成let
for(let i=0;i<10;i++)
使用立即执行函数
for(var i=0;i<10;i++){
(function(i){

   setTimeout(function(){
         console.log(i);
    },0);
})(i)

}
使用bind,因为bind创建了一个新的函数,并且它是立即执行的,所以i会传进去,当bind的第一个参数是undefined或者null时,默认调用者是window窗口对象
for(var i=0;i<5;i++){
setTimeout(function(i){
console.log(i);
}.bind(null,i),0)
}

使用立即执行函数。总结:setTimeout的第一个参数必须是需要编译的代码或者是一个函数方法,而如果直接传入一行可执行代码,那么抱歉,这里会立即执行,没有延迟效果

for (var i = 0; i < 5; i++) {
  setTimeout((function(i) {
    console.log(i);
    return function() {
        console.log('回调')
        console.log(i)
    }
  })(i), i * 1000);
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值