一. call和apply的作用
运用call()和apply()以及bind()这三个方法,都是为了改变this的指向
语法都是:函数.call(),函数.apply(),函数.bind()
二. call和apply的区别
call,apply可以立即执行,bind不会立即执行(因为bind返回的是一个函数需要加入()执行)
它们的第一个参数都是this要指向的对象,不同的是,call方法传递函数调用形参是以散列形式,apply方法的形参是一个数组。在传参情况下,call的性能要高于apply,因为apply在执行时还多一步解析数组。
举例一
let person = {
getName:function(){
return this.name
}
}
let person1 = {
name:'李莲花'
}
console.log(person.getName()) //这个时候的this指向的是window
console.log(person.getName.call(person1)) //这个时候的this指向的是person1
// 打印出undefined
// 打印出李莲花
举例二
var obj={
name:"李相夷",
age:18
}
function method(){
console.log(this) //window
}
method()
上面的this指向的是window,如何让他指向对象obj呢?
1. 使用call
var obj={
name:"李相夷",
age:18
}
function method(a,b,c){
console.log(this,a,b,c) //{name: "李相夷", age: 18} 1 2 3
}
method.call(obj,1,2,3)
2. 使用apply
var obj={
name:"李相夷",
age:18
}
function method(a,b,c){
console.log(this,a,b,c) //{name: "李相夷", age: 18} 1 2 3
}
method.apply(obj,[1,2,3])
三. 实际开发过程中的使用场景
1. 使用call实现判断复杂数据类型
console.log(Object.prototype.toString.call({}) === '[object Object]') // ture
console.log(Object.prototype.toString.call([]) === '[object Array]') // true
2. es5把伪数组转为真正的数组
function get () {
console.log(arguments)
// 方法一
console.log([...arguments])
// 方法二
console.log(Array.prototype.slice.call(arguments))
}
get(1,2,3)
3. JS的继承,构造函数的继承就是靠call来实现的
function Animal(name){
this.name = name
this.showName = function (){
console.log(this.name)
}
}
function Cat(name){
Animal.call(this,name)
// 使用this对象代替Animal对象,Cat中就有了Animal的所有属性和方法
}
let cat = new Cat('Tony')
cat.showName() // 打印出Tony
必须用apply的情况(因为apply第二个参数是数组)
<script>
var arr1 = [1,2,4,5,7,3,321];
console.log(Math.max(1,2,4,5,7,3,321)); // 打印出321
console.log(Math.max(arr1)); // 这样写是找不到arr的,所以会打印出NAN
/* 此时就需要用到apply */
console.log(Math.max.apply(null,arr1)); // 打印出321
</script>
必须用bind的情况(因为bind返回的是一个函数,需要加入()执行)
<body>
<div id="btn">按钮btn</div>
<div id="atm">按钮atm</div>
<script>
var btn = document.getElementById("btn");
var atm = document.getElementById("atm");
btn.onclick = function(){
console.log(this); // 此时打印出的结果是:<div id="btn">按钮btn</div>
}
</script>
</body>
/* 想让其打印出atm的dom */
<body>
<div id="btn">按钮btn</div>
<div id="atm">按钮atm</div>
<script>
var btn = document.getElementById("btn");
var atm = document.getElementById("atm");
btn.onclick = function(){
console.log(this); // 此时打印出的结果是:<div id="atm">按钮atm</div>
}.bind(atm)
</script>
</body>
// 因为function(){}.bind()正好返回的是一个函数,而我们恰好需要通过等待点击事件onclick去触发函数,如果不用bind,而是用call或者apply,那它两是立即执行的。