JavaScript中this指向问题------某种意义上来说,apply比call效率更高

JavaScript中this指向问题

JavaScript中的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数执行环境决定的,而不是函数声明时的环境,大多数情况下我们可以把函数中this的指向分为四种情况

  1. 函数作为对象的方法调用时的this指向
  2. 函数作为普通函数调用时的this指向
  3. 函数作为构造器函数调用时的this指向
  4. 函数使用call方法或者apply方法调用时的this指向

函数作为对象的方法调用时

当函数作为对象的方法调用时,this指向该对象:

let obj = {
	a: 1,
	getA: function() {
		console.log(this === obj);	// 输出:true
		console.log(this.a);	// 输出:1
	}
}
obj.getA();	// getA函数作为obj的方法调用

函数作为普通函数调用时

当函数作为普通函数调用时,this总是指向全局对象(在浏览器的JavaScript中,全局对象是window对象):

window.a = 'globalA';
let obj = {
	a: 1,
	getA: function() {
		return this.a;
	}
}
let getA = obj.getA;
console.log(getA());	// 输出:global

在这种情形下我们通常会遇到给标签绑定事件函数时,回调函数的this指向问题:

window.id = 'globalId';
document.getElementById('btn').onclick = function() {
	console.log(this.id);	// 输出:btn
	let callback = function() {
		console.log(this.id); //	输出: globalId
	};
	callback();
}

当我们点击按钮时触发onclick函数,这时onclick函数是作为document.getElementById('btn')方法返回的节点对象的方法来调用的,所以此时函数里的this指向该节点对象;
callback函数显然是作为普通函数直接调用的,所以此时callback函数中this指向全局对象window
有一种简单的解决方案就是手动保存一个当前调用对象的this

window.id = 'globalId';
document.getElementById('btn').onclick = function() {
	console.log(this.id);	// 输出:btn
	const _this = this;
	let callback = function() {
		console.log(_this.id); //	输出: btn
	};
	callback();
}

特殊情况:strict模式下,普通函数调用下的thisundefined

函数作为构造器调用时

当使用new关键字来调用函数创建一个对象时,这个函数就是一个构造函数,它总会返回一个对象(这是new关键字实现原理),而构造函数里面的this就指向返回的这个对象:

function Class1() {
	this.name = 'weiwl';		
}
let obj1 = new Class1();
console.log(obj1.name)	// 输出:weiwl

function Class2() {
	this.name = 'weiwl';
	return {
		name: 'wll'
	};
}
let obj2 = new Class2();
console.log(obj2.name);	// 输出:wll

函数使用call或者apply调用时

Function.prototype.callFunction.prototype.apply方法都可以动态修改函数this指向,他们的第一个参数就算函数调用时的this指向:

let obj1 = {
	name: 'weiwl',
	getName: function() {
		return this.name;	
	}
}
let obj2 = {
	name: 'wll'
}
console.log(obj1.getName());	// 输出:weiwl
console.log(obj1.getName.call(obj2));	//输出:wll
console.log(obj1.getName.apply(obj2));	输出:wll

call和apply的区别

applycall方法都可以改变函数的this指向,他们使用的区别就在于接收的参数上:

apply接收两个参数:第一个参数是调用函数内this的指向,第二个参数是一个带下标的集合(通常传数组或者arguments);

function sum(a, b, c){
	console.log([a, b, c]);	
}
sum.apply(null, [1, 2, 3]);	// 输出:[1, 2, 3]

call可以接收多个参数:第一个参数也是调用函数内this的指向,后续参数会依次作为实参传入函数

sum.call(null, 1, 2, 3);	// 输出:[1, 2, 3]

apply某种意义上比call高效

由于JavaScript解释器不会计较形参和实参在数量、类型和顺序上的区别,其参数在内部就是用一个数组来表示的,所以我们如果不关心具体有多少参数被传入函数,这种意义上applycall高效

有问题,烦请不吝赐教

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值