js 中this指向

一、前言

在js中,this关键字重要,很多同学工作几年了,依然对this问题很模糊,通过这篇文章希望能够帮助到大家,深刻理解this。

二、this的本质是什么?

在js中,所有的函数(除了箭头函数),内部都会有一个属性this,当调用函数的方式不同时,this的指向也有所不同。

三、绑定this的方式有哪些?

绑定this的方式一般包含一下几种:

  • 默认绑定(一般this指向window)
  • 隐式绑定(谁调用,指向谁,存在隐式丢失问题)
  • 显式绑定(call、apply、bind 能改变this指向)
  • new 实例化
  • es6中箭头函数(内部没有this属性,输出的是父级上下文的this)

绑定this的优先级:箭头函数 > new > 显式绑定 > 隐式绑定 > 默认绑定

四、this的默认绑定

代码:

	function foo(){
		console.log(this);
	}
	foo()    //  Window

解读:当函数被直接调用时,this默认指向window。

五、this的隐式绑定

代码:

function foo(){
	console.log(this);
}
let obj = {
	name:1,
	foo:foo
}
// 隐式绑定,对象调用,谁调用,指向谁
obj.foo();   //  {name: 1, foo: ƒ}
// 赋值给一个变量,再调用,隐式绑定丢失
let  temp = obj.foo;
temp();  // Window

解读:1、函数foo,被obj以属性的方式调用时,属于隐式绑定规则,谁调用,this就会指向谁,所以this指向obj;
2、存在隐式绑定丢失情况,如以上代码,将obj.foo赋值给一个新的变量,此时调用等同于直接调用,所以this指向window。

六、this的显式绑定

代码:

function foo(params){
	this.age = params
	console.log(this);
}
let obj = {
	foo:foo
}
let obj1 = {
	name:1,
}
let obj2 = {
	name:2,
}
let obj3 = {
	name:3,
}
obj.foo.call(obj1,18)  // {name: 1, age: 18}
obj.foo.apply(obj2,[19])  // name: 2, age: 19}
obj.foo.bind(obj3,20)()  // {name: 3, age: 20}
obj.foo.call(null,21)  //  Window

解读:通过call、apply、bind都可以显式的改变this指向,并且优先级高于隐式绑定。

七、new关键字实例化

代码:

function foo(params){
	this.age = params;
	console.log(this);  // foo {age: 18}
}
let obj = {
	foo: foo
}
let obj1 = {
	name:1
}
let temp = obj.foo.bind(obj1)
let foo1 = new temp(18)
console.log(foo1);  // foo {age: 18}
console.log(obj1);  // {name: 1}

解读:先使用bind改变this指向obj1,在使用new实例化一个对象,通过输出可以看出,当前this指向是foo1,并不是指向obj1,故,this绑定,new关键字优先于显式绑定

八、特殊案例“箭头函数”

代码:

let obj = {
	foo:()=>{
		console.log(this)
	}
}

let obj1 = {
		name:1,
	}
obj.foo.call(obj1)  // Window
//  箭头函数和new关键字,在一起如何呢?
let temp = obj.foo.bind(obj1)
let foo1 = new temp()  //   报错:temp is not a constructor

解读:1、箭头函数内部没有this,输出的this是父级上下文的this,所以即使用call也无法改变,最终还是指向Window;
2、当new关键字和箭头函数一起使用时会报错:is not a constructor,所以箭头函数不能被当做构造函数

练习

var name = 'window'
let obj1 = {
	name:1,
	fn1: function(){
		console.log(this.name)
	},
	fn2: ()=>console.log(this.name),
	fn3: function () {
			return function(){
			console.log(this.name)
		}
	},
fn4:function () {
	return ()=>console.log(this.name)
}
}
let obj2 = {
	name:2
}

obj1.fn1();  // 1
obj1.fn1.call(obj2);  //2

obj1.fn2();  // 'window'
obj1.fn2.call(obj2); // 'window'

obj1.fn3()();  // 'window'
obj1.fn3().call(obj2);  // 2
obj1.fn3.call(obj2)();  // 'window'

obj1.fn4()();  // 1
obj1.fn4().call(obj2);  // 1
obj1.fn4.call(obj2)();  //2

大家做对了吗? 欢迎大家留言评论

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值