javascript call()、apply()和bind()

本文深入解析JavaScript中this的指向规则及call、apply、bind三大方法的使用技巧与应用场景,通过实例对比三者差异,助你掌握函数调用与参数传递的艺术。

关于这三个方法,很多大神已经总结的非常到位了。但是呢,俗话说“好记性不如烂笔头”。而且,我发现我学习了一个东西,然后自己敲一篇博客出来之后,就会进一步加深自己对它的理解,所以我还是准备把它写下来。以后也会一直写博客,一直将自己学习的东西记录下去~

关于call()、apply()和bind()这三个方法的学习,我是从一个个例子入手的:

var name = '小明',age = 18;
var obj = {
	name: '小红',
	objAge: this.age,
	myFun: function(){
		console.log("姓名:" + this.name + ";" + "年龄:" + this.age);
	}
}
obj.objAge;
运行结果:
18

obj.myFun();
运行结果:
姓名:小红;年龄:undefined

这个例子中,myFun 中的 this 指向的是 obj,所以,而 obj 没有 age 属性,所以,this.age 是undefined。

var name = '小明',age = 18;
function myFun(){
		console.log("姓名:" + this.name + ";" + "年龄:" + this.age);
}
myFun();
运行结果:
姓名:小明;年龄:18

这个例子中,myFun 中的 this 指向的是 window 对象。

加入了call()、apply()和bind()之后:

var name = '小明',age = 18;
var obj = {
	name: '小红',
	objAge: this.age,
	myFun: function(){
		console.log("姓名:" + this.name + ";" + "年龄:" + this.age);
	}
}
var args = {
	name: '小华',
	age: 20
}
obj.myFun.call(args);
运行结果:
姓名:小华;年龄:20

obj.myFun.apply(args);
运行结果:
姓名:小华;年龄:20

obj.myFun.bind(args)();
运行结果:
姓名:小华;年龄:20

可以看出,call()、apply()、bind() 的作用是:重定义 this 对象。

区别在于,bing() 返回的是一个新的函数,必须调用才能被执行。如下所示:

var name = '小明',age = 18;
var obj = {
	name: '小红',
	objAge: this.age,
	myFun: function(){
		console.log("姓名:" + this.name + ";" + "年龄:" + this.age);
	}
}
var args = {
	name: '小华',
	age: 20
}
obj.myFun.bind(args);

运行结果:
ƒ (){
	console.log("姓名:" + this.name + ";" + "年龄:" + this.age);
}

可以看到,返回了一个函数。

所以,call()、apply()、bind() 区别在于:bind()是返回一个新函数,供以后调用,而 apply() 和 call() 是立即调用。

var name = '小明',age = 18;
var obj = {
	name: '小红',
	objAge: this.age,
	myFun: function(arg,fav){
		console.log("姓名:" + this.name + " 年龄:" + this.age + " 年级:" + arg + " 喜欢:" + fav);
	}
}
var args = {
	name: '小华',
	age: 20
}
obj.myFun.call(args,'大二','苹果');
运行结果:
姓名:小华 年龄:20 年级:大二 喜欢:苹果

obj.myFun.apply(args,['大二','苹果']);
运行结果:
姓名:小华 年龄:20 年级:大二 喜欢:苹果

obj.myFun.bind(args,'大二','苹果')();
运行结果:
姓名:小华 年龄:20 年级:大二 喜欢:苹果

obj.myFun.bind(args,['大二','苹果'])();
运行结果:
姓名:小华 年龄:20 年级:大二,苹果 喜欢:undefined

上面的例子可以看出:

(1)call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象;

(2)call 的参数直接放进去,第二、第三、第 n 个参数之间用逗号分隔;

(3)apply 的参数必须放在一个数组里面传进去。

三个方法的应用:

call():

1)求数组中的最大值和最小值

let maxNum = Math.max.call(Math,5,29,15,46,26,44,23,10,2,71);
console.log(maxNum);
运行结果:
71

let minNum = Math.min.call(Math,5,29,15,46,26,44,23,10,2,71);
console.log(minNum );
运行结果:
2

2)调用对象的原生方法:

var testObj = {};
console.log(testObj.hasOwnProperty('toString'));
testObj.hasOwnProperty = function() {
    return true;
}
console.log(testObj.hasOwnProperty('toString')); 
console.log(Object.prototype.hasOwnProperty.call(testObj, 'toString')); 

运行结果:
false
true
false

3)判断变量的类型:

function isArr(obj){
	if(Object.prototype.toString.call(obj) == '[object Array]'){
		return true;
	}
	return false;
}
isArr([]);
isArr('dhj');
isArr("");
isArr({});
运行结果:
true
false
false
false

apply():

1)求数组中的最大值和最小值

let arr = [5,29,15,46,26,44,23,10,2,71];
let maxNum = Math.max.apply(Math,arr);
console.log(maxNum);
运行结果:
71

let minNum = Math.min.apply(Math,arr);
console.log(minNum);
运行结果:
2

2)追加数组:

let arr1 = [23,3,12,14,4,90];
var arr2 = [2,59,21,20,63,47];
Array.prototype.push.apply(arr1,arr2);
console.log(arr1);
console.log(arr2);
运行结果:
[23, 3, 12, 14, 4, 90, 2, 59, 21, 20, 63, 47]
[2, 59, 21, 20, 63, 47]

3)利用Array构造函数将数组的空元素变成undefined

let arr = Array.apply(null, [1, , 3]);
console.log(arr); 
运行结果:
[1, undefined, 3]

4)实现继承:

function Father(name,age){
	this.name = name;
	this.age = age;
	this.setName = function(){
		console.log(this.age);
	}
}
function Son(){
	Father.apply(this,arguments);
}
let obj = new Son('merry',15);
console.log(obj.name);
console.log(obj.age);

运行结果:
merry
15

在这里插入图片描述
bind():

1)将函数绑定新的this指向并且固定传入几个变量

let arg = {};
function myFun(...args){
	console.log(args)
}
let obj = myFun.bind(arg,'小明', '小红');
obj('小华', '小丽');
运行结果:
 ["小明", "小红", "小华", "小丽"]

这个例子在绑定时候传入了两个参数,之后调用新函数再传入别的参数,调用时传入的参数会排在后面。

对于三个方法的选取原则:

(1)不关心具体有多少参数被传入函数,用apply();

(2)确定函数可接收多少个参数,并且想一目了然表达形参和实参的对应关系,用call();

(3)想要将来再调用方法,不需立即得到函数返回结果,用bind()。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值