一、call
- call、apply、bind都是改变this指向的方法
1.call是函数的方法,可以调用函数
function fun(){
console.log(this);
}
fun.call(); // Window
2.call的第一个参数可以改变函数中this的指向
function fun1(){
console.log(this.name);
}
let cat = {
name: "喵喵"
}
fun1.call(cat); // 喵喵
let dog = {
name: "旺财",
sayName(){
console.log("我是", this.name)
}
}
dog.sayName(); // 我是旺财
dog.sayName.call(cat); // 我是喵喵
3.call的第二个参数开始的参数是要传入函数的参数
let cat = {
name: "喵喵"
}
let dog = {
name: "旺财",
eat(food){
console.log("我喜欢吃", food)
},
eatMore(food1, food2){
console.log("我喜欢吃", food1, food2)
}
}
dog.eat("骨头"); // 我喜欢吃骨头
dog.eat.call(cat); // 我喜欢吃undefined
dog.eat.call(cat, "鱼"); // 我喜欢吃鱼
dog.eatMore.call(cat, "鱼", "肉"); // 我喜欢吃鱼肉
- call中的细节
(1)非严格模式
如果不传参数,或者第一个参数是null或undefined,this都指向window
function fun(){
console.log(this);
}
fun.call(); // Window
fun.call(null); // Window
fun.call(undefined); // Window
(2)严格模式
第一个参数是谁,this就指向谁,包括null和undefined,如果不传参数this就是undefined
'use strict'
function fun(){
console.log(this);
}
fun.call(); // undefined
fun.call(null); // null
fun.call(undefined); // undefined
二、apply
- apply和call的区别就是传参不一样,apply的参数列表通过数组传递
let dog = {
name: "旺财",
eatMore(food1, food2){
console.log("我喜欢吃", food1, food2)
}
}
// call传参
dog.eatMore.call(cat, "鱼", "肉"); // 我喜欢吃鱼肉
// apply传参
dog.eatMore.apply(cat, ["鱼", "肉"]); // 我喜欢吃鱼肉
三、bind
-
bind的传参方式和call一样
-
bind和call的区别在于bind不会调用函数,而是把函数作为返回值,好处就是方便多次调用
let dog = {
name: "旺财",
eatMore(food1, food2){
console.log("我喜欢吃", food1, food2)
}
}
// call传参
dog.eatMore.call(cat, "鱼", "肉"); // 我喜欢吃鱼肉
// bind传参
let bFun = dog.eatMore.bind(cat, "鱼", "肉");
bFun(); // 我喜欢吃鱼肉
- bind中的细节
bind的多次绑定只有第一次是有效的
function fun(){
console.log(this.name);
}
let cat = {
name: "喵喵"
}
let dog = {
name: "旺财",
}
var f1 = fun.bind(cat);
f1(); // 喵喵
// 第二次使用bind绑定无效
var f2 = f1.bind(dog);
f2(); // 喵喵
// 使用call绑定也无效
f1.call(dog); // 喵喵