YDKJS01-深入理解this

97 阅读3分钟

你不知道的JSthis全面解析

2.1 调用位置

在理解this的绑定之前要理解this调用位置:调用位置就是函数在代码中被调用的位置 说成人话就是要确定this调用所在的作用域

例子:

	function baz(){
		console.log(this);	//这个this指向的就是函数baz
	}
	console.log(this);		//这个this就是指向的window

2.2绑定规则

2.2.1默认绑定

例子:

	function foo(){
		console.log(this.a);
	}
	var a=2;
	foo();		//这里返回的是2,

上面这个this.a实际上就是在函数作用域中找,然后找不到之后就跑到全局作用域中去找了。

	function foo(){
		"use strict"
		console.log(this.a);
	}
	var a=2;
	foo();	//	这里返回undefined

如果采用严格模式,就会返回undefined

2.2.2隐式绑定

	function foo(){
		console.log(this.a)
	}
	var obj={
		a:2,
		foo:foo
	}
	var a=10086;
	var st=obj.foo;
	st();	//这里返回10086
	obj.foo();	//这里返回2

上面这段代码返回2,obj.foo()是通过obj对象去调用foo()函数,this是指向obj,在obj对象中找,再找不到就返回undefined。

st()是在window中找a也就是全局作用域下,this指向的是window,st()可以写为,window.st()

	function foo(){
		
		console.log(this.a);
	}
	var obj={
		a:2,
		foo:foo
	}
	var a=10086
	var st=obj.foo
	obj.foo();		//这里是在obj中调用的,this指向的是obj,隐式绑定
	st();			//这里是在全局中调用的st(),this指向window,隐式绑定
	foo();	//这里是在全局中调用的st(),this指向window,隐式绑定

2.2.3 显式绑定

通过call和apply方法来进行绑定

	function foo(){
		var a="this is foo"
		console.log(this.a);
	}
	var obj={
		a:2
	}
	var a=10086
	foo.call(obj)	//这里返回2,将this绑定给了obj
	foo.call(window);	//这里返回10086,将this绑定给了window
	foo.call(foo);	//这里返回undefined,虽然绑定给了foo,但是无法访问里面的a只能通过闭包来访问
	

1、硬绑定

	function foo(){
		console.log(this.a);
	}
	var obj={
		a:2
	}
	var bar=function(){
		foo.call(obj)	//这里是硬绑定
	}
	bar();
	setTimeout(bar,100)
	bar.call(window);	//硬绑定之后无法修改它的this值

硬绑定的典型应用场景就是创建一个包裹函数,负责接收参数并返回值

		function foo(someth){
			console.log(this.a,someth);	//返回2,3
			return this.a+someth	//ret 2+3
		}
		var obj={
			a:2
		}
		var bar=function(){
			return foo.apply(obj,arguments);
		}
		var b=bar(3);
		console.log(b);	//返回5

2.2.4 new绑定

传统面向对象语言中,“构造函数”是类的一种特殊方法,使用new初始化类时会调用类中的构造函数。

JS中的new是操作符,和绝大多数面向对象语言的new则完全不同。被new操作符调用的函数实际上就是普通的函数,也不会被实例化一个类。

使用new操作符调用函数会发生以下操作:

1、创建(或者说构造)一个全新的对象。

2、这个新对象会被执行[[Prototype]]连接,也就是绑定在prototype上

3、这个新对象会绑定到函数中调用this

4、如果函数没有其他返回对象,new自动返回这个新对象

2.3优先级

默认绑定是绑定中优先级最低的

	function foo(){
		console.log(this.a);
	}
	var obj1={
		a:2,
		foo:foo
	}
	var obj2={
		a:3,
		foo:foo
	}
	obj1.foo();		//这里返回2
	obj2.foo();		//这里返回3
	
	obj1.foo.call(obj2);	//这里返回3
	obj2.foo.call(obj1);	//这里返回2

显式绑定优先级更高,也就是说在判断是应当考虑可以存在的显式绑定

2.4绑定例外

2.4.1 被忽略的this

如果你把null或者undefined作为this的绑定对象传入call,apply或者bind,这些值在调用时会忽略,实际应用的是默认绑定规则

	function foo(){
		console.log(this.a);
	}
	var a=2
	foo.call(null);		//这里返回的是2