分析call,apply,bind作用

call,apply,bind是Function.prototype原型上的方法
任何函数都可以访问call,apply,bind方法(原因:任何函数的原型链上都有Function.prototype原型)

bind,apply,call的区别
方法语法第一个参数其余参数
callcall(对象,参数1,参数2...)修改this指向作为函数的形参
applyapply(对象,[参数1,参数2...])修改this指向作为函数的形参
bindbind(对象,参数1,参数2...)固定this指向作为函数的形参

call,apply的作用

  1. 调用函数
//除了使用函数名() 来调用函数外,还可以使用call,apply来调用函数
function fn(){
    console.log(123);
}

fn.call();//123
fn.apply();//123
  1. 传参数
function sum(x, y) {
    console.log(x + y);//5
}

var arr = [2, 3]

//传入null/undefined的时候将执行js全局对象,浏览器中是window
sum.apply(null, arr)
sum.call(null, 2, 3)
var arr = [18, 29, 89, 73, 5, 10, 8, 99, 105, 52];

//用Math对象上max()方法求最大值
Math.max.apply(null,arr)//105
Math.max.call(null, 18, 29, 89, 73, 5, 10, 8, 99, 105, 52)//105
  1. 修改this指向
var dog = {
    name: '小黄',
    age: 3
}

function animal (a,b) {
	console.log(a + b);//3
    console.log(this);//window
    console.log(this.name);//'' 全局变量有name属性,所以不为undefined
    console.log(this.age);//undefined
}

animal(1, 2)//函数调用模式,this指向window
var dog = {
    name: '小黄',
    age: 3
}
function animal (a,b) {
	console.log(a+b);//3
    console.log(this);//对象dog
    console.log(this.name);//'小黄'
    console.log(this.age);//3
}

animal.call(dog, 1, 2)//修改this指向为对象dog
  1. 借用对象方法

    伪数组与数组

  • 伪数组也叫类数组伪数组其实就是一个对象,但是跟数组一样,伪数组也会有length属性,也有0,1,2,3等属性。

  • 伪数组并没有数组的方法,不能使用push/pop等方法。

  • 伪数组可以跟数组一样进行遍历,通过下标操作。

  • 常见的伪数组:argumentsdocument.querySelectorAll的返回值、jQuery对象

//创建一个伪数组
var obj = {
    0: "卡卡西",
    1: "佐助",
    2: "鸣人",
    length: 3
};//分号

//借用数组的方法,往伪数组最后添加一项
//Array.prototype.push.call(obj, "小樱");

[].push.call(obj, "小樱");//注意这种写法必须在对象后面添加分号,不然会被浏览器当做点语法解析
var obj = {
    0: "卡卡西",
    1: "佐助",
    2: "鸣人",
    length: 3
};

//通过silice截取数组可以将伪数组转换成真数组
var arr = [].slice.call(obj);

console.log(arr);//["卡卡西", "佐助", "鸣人"]
//数组借用Math对象方法求最大值
var arr = [18, 29, 89, 73, 5, 10, 8, 99, 105, 52];
var ret = Math.max.apply( arr, arr);//借用Math对象中max求最大值的方法
console.log(ret);//105

call,apply使用场景:
如果参数比较少,使用call会更加简洁
如果参数存放在数组中,此时需要使用apply

bind的作用

bind()方法创建一个新的函数, 可以绑定新的函数的this指向

 var fn = function () {
     console.log(this);//window
}
fn(); //函数调用模式,this指向window
//fn和fn2长的一样,但是在内存中是两份函数,地址是不一样。
 var fn = function () {
     console.log(this);//[10, 20, 30]
}
      
var fn2 = fn.bind( [10, 20, 30] ); // fn2 是创建的新函数,新函数和fn长的一样。

console.log(fn === fn2); // false 
//fn和fn2长的一样,但是在内存中是两份函数,地址是不一样。

fn2();
//fn2函数是由bind创建出来的, fn2函数内的this指向被固定了,所以this指向了[10, 20, 30]
//固定的理解: 不论fn2 函数的调用模式是何种,fn2内的this指向被固定写死了。

bind修改定时器this指向

var obj = {
    name: '吕布',
    sex: '男',
    age: 18,
    hi: function () {
        setTimeout(function () {
            console.log(this);//window
            
			//定时器中的this指向了window,window上没有age属性
            console.log('我的年龄是' + this.age);//我的年龄是undefined
        }, 1000)
    }
}

obj.hi()

解决方法:

var obj = {
    name: '吕布',
    sex: '男',
    age: 18,
    hi: function () {
        setTimeout(function () {
            console.log(this);//obj
            
            console.log('我的年龄是' + this.age);//我的年龄是18
        }.bind(this), 1000)//注意这个this不在定时器函数内部,指向的是obj
    }
}
obj.hi()

拓展:
以下两种方法同样可以解决定时器指向window的问题

方法一:var that = this;

var obj = {
    name: '吕布',
    sex: '男',
    age: 18,
    hi: function () {
		//把想要的this指向使用变量that存储了起来。
    	var that = this;	
        setTimeout(function () {
            console.log(this);//window
            
            //把this的指向赋值给变量that,that也就指向了obj
            console.log('我的年龄是' + that.age);//我的年龄是18
        }, 1000)
    }
}
obj.hi()

方法二:箭头函数;

var obj = {
    name: '吕布',
    sex: '男',
    age: 18,
    hi: function () {
        setTimeout(() => {
            // 箭头函数内部没有自己的this, 使用的是外部函数的this  
            console.log(this);//obj
            console.log('我的年龄是' + this.age);//我的年龄是18
        }, 1000)
    }
}
obj.hi()

小结:

  • call apply 作用是一样 ,唯一不同的是,call需要一个一个传参,apply可以传数组或伪数组。
  • apply有平铺性: 将apply的第二个参数数组里面的每一项取出来作为函数的实参。
  • bind 创建并返回新函数,不会来调用函数的。
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值