call和bind和apply区别
call 和 apply 的共同点
-
都可改变 this 的指向 (通过第一个参数,来改变this指向)
-
第一个参数 (可选):
-
非严格模式下call和apply方法中如果没有传入参数,或者是传入的是null 或 undefined那么调用该方法的函数对象中的this指向就是默认的window
-
可传入对象,传入的对象会替换当前的对象 (因此会改变this的指向,若原本的指向是window,当传入的对象是object类型,则this指向会是object)
-
-
调用 call 和 apply 的对象,必须是一个函数 Function
- apply和call都是有返回值的
- 当函数方法没有设置return返回值,则结果返回的是undefined
- 当函数方法设置了return值
- 结果可以返回return的值
- 使用调用者提供的
this值和参数调用该函数的返回值
apply和call的性能
-
当参数在三个以内的话,apply和call性能差不多
-
当参数三个以上的时候,call比apply性能好一些
- 因为处理过程中apply比call步骤比较多,要获取数组长度,进行循环迭代...
- 所以后期开发的时候,可以使用call多一点
call和apply的用法区别
- 区别:call和apply的传递参数的方式不一样
- call传递参数参数列表,是一个一个传递的,可传递多个
- apply传递参数是一个数组形式
fun.call(对象, 参数1,参数2,....)
func.apply(对象, [参数1,参数2,...])
第一个参数 (可选): ( apply和call的第一个参数用法是一样的 )
-
非严格模式下call和apply方法中如果没有传入参数,或者是传入的是null 或 undefined那么调用该方法的函数对象中的this指向就是默认的window
-
可传入对象,传入的对象会替换当前的对象 (因此会改变this的指向,若原本的指向是window,当传入的对象是object类型,则this指向会是object)
function f1(x,y){
console.log('结果是:' + (x+y)+this); //300 window
return 'hello world'
}
f1(100,200)
console.log('------------------')
//此时的f1实际上是当成对象来使用,因为函数就是对象,对象可以调用方法
// apply和call方法也是函数的调用的方式
f1.apply() //window
f1.call() //window
//函数内部的this指向是全局对象,即window对象
console.log('------------------')
f1.apply(null) //window
f1.call(null) //window
f1.call(undefined) //window
f1.apply(undefined) //window
//call和apply方法中如果没有传入参数,或者是传入的是null 或 undefined
//那么调用该方法的函数对象中的this指向就是默认的window
第二个参数 (可选):
第二个参数是传递给函数的使用的
- call的第二个参数是: 指定的参数列表
- apply的第二个参数 : 传入的是数组或类数组
function f1(x,y){
console.log('结果是:' + (x+y)+this); //300 window
return 'hello world'
}
f1(100,200)
//区别:call和apply的传递参数的写法不同
//apply的第二个参数 : 传入的是数组或类数组
//call的第二个参数是: 指定的参数列表
f1.apply(null,[100,200]) // 300 window 和 f1(100,200)调用的结果是一样的
f1.call(null,100,200) // 300 window 和 f1(100,200)调用的结果是一样的
//apply和call都可以让函数或者方法来调用,传入的参数和函数自己调用的写法不一样,但效果是一样的
call和apply的作用
-
改变this的指向
-
1、通过传递第一个参数,
可传入对象,传入的对象会替换当前的对象 (因此会改变this的指向,若原本的指向是window,当传入的对象是object类型,则this指向会是object)
-
-
使用_call_方法调用父构造函数
- 通过调用父构造函数的
call方法来实现继承
- 通过调用父构造函数的
例子1
function f2(x,y){
console.log('这个函数是window对象的一个方法:' + (x+y) + this)
}
window.f2(100,200); //300 window
//由于window是可以省略的,我们经常都是省略window对象
//obj是object对象
var obj = {
age:10,
sex:'男'
}
window.f2.apply(obj,[100,200]); //300 object
window.f2.call(obj,100,200); //300 object
// 原本是window对象,通过apply把传入的对象替换了当前的对象
//即传入的对象是object替换了window当前对象
例子2
function Person(age,sex){
this.age = age;
this.sex = sex
}
Person.prototype.sayHi = function(x,y){
//构造函数this的指向是实例对象,即当前对象
console.log('您好啊'+this.sex)
}
var per = new Person(10,'男')
per.sayHi() // 您好啊 男
function Student(name,sex){
this.name = name
this.sex = sex
}
var stu = new Student('小明','人妖')
//传入stu对象,因此stu对象替换了原本的per对象
per.sayHi.apply(stu,[10,20]) // 您好啊 人妖
per.sayHi.call(stu,10,20) // 您好啊 人妖
</script>
何时用call和apply方法
- 只要是想使用别的对象的方法,并且希望这个方法是当前对象,那么就可以使用call或者apply来改变this的指向
- 组合继承的时候
call和apply方法到底是谁给的?
- call和apply方法实际上并不在函数的实例对象中,而是在Function的prototype中,即在所在的构造函数的原型对象中
bind语法
fun.bind(对象, 参数1,参数2,....) ---> 返回的值是 原函数的拷贝
function f1(x,y){
console.log((x+y)+'====>'+this.eat)
}
//返回了一个新的函数,称为绑定函数,相当于复制了一份
// var ff = f1.bind(null,20,30) //50 window
// ff()
var ff = f1.bind(null)
//bind相当于是复制的意思,可在复制的时候传递参数,也可以复制后调用的时候传递参数
ff(20,30) //50 window
function Person(){
this.age = 20
}
Person.prototype.eat = function (){
console.log('这个是吃')
}
var per = new Person()
var fff = f1.bind(per,10,20)
fff()
bind的应用 (改变定时器的this指向)
<script>
//通过对象,调用方法,产生随机数
function ShowRandom(){
// 1-10的随机数
// Math.random()可以产生0到1的之间的随机数 (不包含1本身)
this.number = parseInt(Math.random()*10+1)
}
//添加原型方法
ShowRandom.prototype.show1 = function (){
// window.setInterval(function(){
// console.log(this) //window
// },1000)
window.setInterval(this.show2.bind(this),1000) //this指的是实例对象
//因此改变了定时器的this的指向了,
//原本定时器的this是window,现在是this指向实例对象
}
ShowRandom.prototype.show2 = function (){
//显示随机数 --this
console.log(this.number)
}
var result = new ShowRandom()
//调用方法,输出随机数字
//调用这个方法一次,可以不停的产生随机数字
result.show1()
</script>
bind与call和apply的区别
- bind方法是相当于是复制的意思,因为返回的值是原函数的拷贝,在复制后调用的时候才改变this的指向
- 而call和apply是在调用的时候,改变this的指向
apply和call是立即执行,而bind方法返回值是原函数的拷贝,在需要用到 这个函数的时候调用的才执行
bind与call和apply的共同点
- 都是可以改变this的指向