写过一点关于call函数的认识,但隔了一段时间后感觉不是很详尽,再重新研究一下
call apply bind
- 注意,箭头函数的this指向是固定的,始终指向函数定义时的对象,而不是使用时的对象
无法使用这三个函数来为其指定this的指向
let a = {x:3};
let func = ()=>{
console.log(this);
//箭头函数没有自己的this,它的this是该函数外层代码块的this
// 在此处是window对象
}
func(); //=> window
//call()
func.call(a); // =>window
//apply
func.apply(a); // => window
// bind()
let func2 = func.bind(a);
console.log(func2);// => ()=>{console.log(this);}
func2(); // window
-
function.call(thisArg,arg1,arg2, ...)
每个函数都有自己的this指向,使用call方法可以为我们调用的函数指定其this指向
function con(x){
console.log(this.a);
}
con(1); // => undefined
//使用call函数为其指出this指向
con.call({a:2},1); // => 2
- 当处于非严格模式时,指定的thisArg为 null undefined时,this会自动指向
全局对象(浏览器为window,node为global)
function con(){
console.log(this); // => Window对象
return 1;
}
let a = con.call(null);
console.log(a); // 1
- 我们可以使用call方法来实现继承
在JAVA中,我们给出一个Product类,声明类Food继承该Product类
class Product{
protected String name;
protected String price;
public Product(String name,String price){
this.name = name;
this.price = price;
}
}
class Food extends Product{
private String kind;
public Food(String name,String price,String kind){
super(name,price);
this.kind = kind;
}
}
Food apple = new Food("apple","15","friut");
在js中,我们可以借助call这样来写
function Product(name,price){
this.name = name;
this.price = price;
}
function Food(name,price,kind){
Product.call(this,name,price);
this.kind = kind;
}
let apple = new Food('apple','15','friut');
console.log(apple); // => Food{name:'apple',price:'15',kind:'friut'};
对比上面的写法,我们在js中使用了call来调用函数Product,类似与在java中使用super()
函数来调用父类的构造方法
- call的一个比较常见的用法是在处理类数组对象时,我们可以通过call函数,让其调用
数组的方法,完成我们需要的操作详细讲解
例如将类数组对象arguments转化为数组:
let argsArr = Array.prototype.slice.call(arguments);
使用forEach方法来遍历HTMl collection
[].forEach.call(htmlCol,(val,index,arra=>{
console.log(val);
}))
-
function.apply(thisArg,[args])
apply的用法和call差不多,区别在与apply所调用函数的参数是以数组或者类数组方式提供的
也就是说,call中能使用的地方,都可以使用apply来替代,有时apply写的还更简单
- 上面的继承使用apply改写
function Product(name,price){
this.name = name;
this.price = price;
}
function Food(name,price,kind){
Product.apply(this,arguments);
//这里直接将Food函数的arguments对象传过去,虽然多传了一个参数kind,但在写法上更简单
this.kind = kind;
}
let apple = new Food('apple','15','friut');
console.log(apple); // => Food{name:'apple',price:'15',kind:'friut'};
- 将一个数组push到另一个数组中去(使用concat会创建新数组,push不会)
let a = [1,2,3];
let b = [4,5,6];
[].push.apply(a,b);
console.log(a); // => [1,2,3,4,5,6]
- 使用max函数找出一个数组中的最大值
let a = [1,2,3,45,6,7];
let res = Math.max.apply(null,a);
console.log(res); // => 45
//另一种简化写法 : es6
Math.max(...a); // => 45
-
function.bind(thisArg,arg1,arg2 ...)
bind函数不是一次原函数的调用,它会返回一个新的函数,具有指定的this指向,并且在
调用新函数时,在bind时指定的参数会作为新函数的前几项参数值
let a = {x:3};
function func(){
console.log(this.x);
}
func(); //=> undefined
let func2 = func.bind(a);
console.log(func2);// => ()=>{console.log(this.x);}
func2(); // =>3