JavaScript中this的用法

this的指向:在函数运行时,当前的运行环境属于谁,this就指向谁

独立使用

在命名完一个函数后直接使用。其实是省略了window。

console.log(this == window) //true	
function test(){
		console.log(this == window)//函数中指向window
	}
test() // true
window.test() // true

函数在命名完成后直接使用,也是独立使用。

(function(){
	console.log(this)
})() //window

隐式绑定(谁调用指向谁)

这里有一个非常实用的小技巧,就是看调用的方法前面有没有出现obj.如果有证明这个调用属于某个对象,而没有则属于window。

  • 对于第一个this,是在obj调用foo函数时产生的,因此指向obj
  • 对于第二个this,虽然也是在obj调用foo函数时产生的,但是执行到test函数的时候,可以理解为是一个独立调用的函数(可能有点不好理解,可以简单地理解说不是obj直接调用地,而是过了一手的感觉。)
//例子1
var obj = {
	a : 2,
	foo: function(){
		console.log(this); //obj
		function test(){
			console.log(this) // window
		}
		test()
	}
}
obj.foo()

obj.foo()其实返回值就是一个test函数,所以可以obj.foo()()=test(),所以是独立使用

//例子2
var obj = {
	a : 2,
	foo: function(){
		function test(){
			console.log(this)
		}
		return test
	}
}

obj.foo()() //window

第一个是对象直接调用函数
第二个过了一手,obj.foo已经直接指向了这个函数,不能算对象的直接调用,因此是window

//例子3
var obj = {
	a : 2,
	foo: function(){
		console.log(this)
	}
}

obj.foo() // obj

var test = obj.foo
test() // window

obj.foo就是指向了test这个函数,但是在bar()执行的时候,它依然是属于window的,然后它的参数是来自与对象的一个属性所指向的函数。这是一个干扰项,要把握住执行的那一个时刻this指向谁。

//例子4
function bar(fn){
	fn()
}

var obj = {
	foo : test,
}

function test(){
	console.log(this)
}
bar(obj.foo) //window

显式绑定(call apply blind)

call apply blind的用法:就是为了改变this指向而存在的

new绑定

实例化对象
this就指向这个新的实例化后的对象。

function Person(){
	this.name = 'Frank';
	this.age = 18;
	return 1;
}
var oPerson = new Person()
console.log(oPerson.name+'\'s age is', oPerson.age) // Frank's age is 18
console.log(oPerson) // 是一个对象而不是1
function Person(){
	this.name = 'Frank';
	this.age = 18;
	return {};
}
var oPerson = new Person()

console.log(oPerson) // {} 但是如果返回值是一个引用,this指向就不会指向这个对象.多以如果要实例化对象,一般不写返回值
console.log(oPerson.name) // undefined

四种this的作用方式中,优先级为:
new绑定 > 显式绑定 > 隐式绑定 > 默认绑定

//这个例子是关于new绑定和显式绑定的比较
function foo(b){
	this.a = b;
}
var obj1 = {}

var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a)
/*
这里通过new对构造函数进行实例化的时候:
因为bar是foo通过foo的显式绑定构建的。如果new的优先级比显式绑定低,则此时this还是
指向obj1,则obj1.a = 3。这与输出的结果矛盾,因此new的优先级比显式绑定高。	
*/
var baz = new bar(3);
console.log(obj1.a);
console.log(baz.a)

箭头函数中的this

结论:箭头函数中没有this指向,它的this同其父级作用域的this指向。
由于子函数的this可能与父函数的this指向不相同,下面是两个常用的解决办法。

//方法一
var object = {
	outer : function(){
		var that = this; 
		function inner(){
			console.log(that) //定义了一个that用来记录父函数的this
		}
		inner()
	}
}
object.outer()

//方法二
var object = {
	outer : function(){
		function inner(){
			console.log(this)
		}
		inner.apply(this) //对inner函数进行显式绑定到夫函数上。
	}
}
object.outer()

this指向父作用域

//例子一
var object = {
	outer : () => {
		console.log(this) //输出结果是window而不是object。在这里outer函数的父级作用域就是window
	}
}
object.outer()

//例子二
var object = {
	outer : function(){
		console.log(this)
		var inner = () =>{
			console.log(this) //指向object对象。因为inner的父级作用域中的this指向了object.
		}
		
		inner()
	}
}
object.outer()		

这一部分的代码不是很重要,主要是要理解:4中更改this指向的绑定规则,对箭头函数都无效。箭头函数的this指向,只与父级作用域的this指向有关。

function foo(){
		console.log(this);
		var test = () =>{
			console.log(this)
		}
		return test
	}
	var obj1 = {
		a : 1,
		foo : foo,
	}
	var obj2 = {
		a : 2,
		foo : foo,
	}
	
	//如果test不是箭头函数,那么这个调用应该是独立调用,应该指向window,但是结果是obj1,
	//这表示:独立调用对箭头函数无效
	obj1.foo()() 
	//foo中的this指向obj2,但是由于是独立调用,因此指向window
	//f00()执行返回了test,相同于test.apple(obj2),如果显式绑定生效,则this指向obj2,但是结果是window,证明显式绑定没用。
	foo().apply(obj2) 
	
	// 箭头函数是不能当作构造函数使用的,即不能用new来创建对象。语法上是直接报错的。

一个练习小例子

var name = "window";
var 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)
	}
}

var 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

参考资料
参考资料

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值