js中this的指向问题

// 1.严格模式下,普通函数中,指向undefined
		/* "use strict"
		function foo(){
			console.log(this)
		}
		foo()//undefined */
		
		
		// 2.在普通模式下,普通函数中,谁调用这个函数,this就指向谁
		/* function foo(){
			console.log(this)
		}
		foo()//全局函数可以看成是window对象的方法,相当于是window调用 */
		
		
		/* var obj={
			name:"obj",
			sayHello:function(){
				console.log(this)
			}
		}
		obj.sayHello()//obj调用,指向obj */
		
		
		/* var age1="window"
		let age2=10
		var obj={
			name:"obj",
			sayHello:function(){
				console.log(this)
			}
		}
		console.log(window.age1)  //window
		console.log(window.age2)  //undefined */
		
		
		/* var name="window"
		var obj={
			name:"obj",
			sayHello:function(){
				console.log(this)
			}
		}
		console.log(obj.name)  //obj
		obj.sayHello() //指向obj */
		
		
		/* var name="window"
		var obj={
			name:"obj",
			sayHello:function(){
				return function(){
					console.log(this.name)
				}
			}
		}
		obj.sayHello() //没有结果,返回的函数体没有执行
		console.log(obj.sayHello())  //返回函数体
		obj.sayHello()()  //window */
		
		
		/* var name="window"
		var obj={
			name:"obj",
			sayHello:function(){
				console.log(this.name)//obj
				setTimeout(function(){//setTimeout是全局方法(window的方法)
					console.log(this.name)//window
				})
			}
		}
		obj.sayHello() */
		
		
		
		//3.箭头函数中的this指向
		//指向定义这个箭头函数时所在环境中的this,在哪个地方定义,指向那个地方的this
		/* var foo=()=>{
			console.log(this)
		}
		foo()//window */
		
		
		/* var name="window"
		/* var obj={
			name:"obj",
			sayHello:()=>{
				console.log(this.name)
			}
		} 
		//相当于下面的代码
		var obj={}
		obj.name="obj"
		obj.sayHello=()=>{
			console.log(this.name)
		}
		obj.sayHello()//window */
		
		
		/* var name="window"
		var obj={
			name:"obj",
			sayHello:function(){
				return ()=>{
					console.log(this.name)
				}
			}
		}
		obj.sayHello()()  //obj,所在的环境为obj */
		
		
		/* var name="window"
		var obj={
			name:"obj",
			sayHello:()=>{
				console.log(this)
				return ()=>{
					console.log(this.name)
				}
			}
		}
		obj.sayHello()() //window */
		
		
		/* var name="window"
		var obj={
			name:"obj",
			sayHello:()=>{
				console.log(this)//window
				return function(){
					console.log(this.name)//window
				}
			}
		}
		obj.sayHello()() */
		
		
		/* var name="window"
		var obj={
			name:"obj",
			sayHello:function(){
				console.log(this)//{name: "obj", sayHello: ƒ}
				return ()=>{
					console.log(this.name)//obj
				}
			}
		}
		obj.sayHello()()  */
		
	    4.补充(补充部分的参考网址:https://juejin.im/post/5c96d0c751882511c832ff7b)
	    
		补充1(隐式绑定):对象属性链中只有最后一层会影响到调用位置。
		function sayHi(){
	    console.log('Hello,', this.name);
		}
		var person2 = {
		    name: 'Christina',
		    sayHi: sayHi
		}
		var person1 = {
		    name: 'YvetteLau',
		    friend: person2
		}
		person1.friend.sayHi();//Hello, Christina.
		隐式绑定有一个大陷阱,绑定很容易丢失(或者说容易给我们造成误导,我们以为this指向的是什么,但是实际上并非如此).
		function sayHi(){
		    console.log('Hello,', this.name);
		}
		var person = {
		    name: 'YvetteLau',
		    sayHi: sayHi
		}
		var name = 'Wiliam';
		var Hi = person.sayHi;
		Hi();
		Hi直接指向了sayHi的引用,在调用的时候,跟person没有半毛钱的关系
		隐式绑定的丢失是发生在回调函数中(事件回调也是其中一种),我们来看下面一个例子:
		 function sayHi(){
	          console.log('Hello,', this.name);
	       }
	       var person1 = {
	           name: 'YvetteLau',
	           sayHi: function(){
	               setTimeout(function(){
	                   console.log('Hello,',this.name);
	               })
	           }
	       }
	       var person2 = {
	           name: 'Christina',
	           sayHi: sayHi
	       }
	       var name='Wiliam';
	       person1.sayHi();//Hello,Wiliam
	       setTimeout(person2.sayHi,100);//Hello,Wiliam
	       setTimeout(function(){
	           person2.sayHi();
	       },200);//Hello, Christina
	       注: person1.sayHi()和person2.sayHi不一样,一个是隐式绑定,一个是相当于是变量
	       第一条输出很容易理解,setTimeout的回调函数中,this使用的是默认绑定,非严格模式下,执行的是全局对象
		   第二条输出是不是有点迷惑了?说好XXX.fun()的时候,fun中的this指向的是XXX呢,为什么这次却不是这样了!Why?
		  其实这里我们可以这样理解: setTimeout(fn,delay){ fn(); },相当于是将person2.sayHi赋值给了一个变量,最后执行了变量,这个时候,sayHi中的this显然和person2就没有关系了。
		  第三条虽然也是在setTimeout的回调中,但是我们可以看出,这是执行的是person2.sayHi()使用的是隐式绑定,因此这是this指向的是person2,跟当前的作用域没有任何关系。
		  
		  补充2(显示绑定):显式绑定比较好理解,就是通过call,apply,bind的方式,显式的指定this所指向的对象。
		call,apply和bind的第一个参数,就是对应函数的this所指向的对象。call和apply的作用一样,只是传参方式不同。call和apply都会执行对应的函数,而bind方法不会。
		function sayHi(){
		    console.log('Hello,', this.name);
		}
		var person = {
		    name: 'YvetteLau',
		    sayHi: sayHi
		}
		var name = 'Wiliam';
		var Hi = person.sayHi;
		Hi.call(person); //Hi.apply(person)
		输出的结果为: Hello, YvetteLau. 因为使用硬绑定明确将this绑定在了person上。
		那么,使用了硬绑定,是不是意味着不会出现隐式绑定所遇到的绑定丢失呢?显然不是这样的,不信,继续往下看。
		function sayHi(){
			console.log('Hello,', this.name);
		}
		var person = {
			name: 'YvetteLau',
			sayHi: sayHi
		}
		var name = 'Wiliam';
		var Hi = function(fn) {
			fn();
		}
		Hi.call(person, person.sayHi); //Hello, Wiliam
		   输出的结果是 Hello, Wiliam. 原因很简单,Hi.call(person, person.sayHi)的确是将this绑定到Hi中的this了。但是在执行fn的时候,相当于直接调用了sayHi方法(记住: person.sayHi已经被赋值给fn了,隐式绑定也丢了),没有指定this的值,对应的是默认绑定。
		现在,我们希望绑定不会丢失,要怎么做?很简单,调用fn的时候,也给它硬绑定。
		function sayHi(){
			console.log('Hello,', this.name);
		}
		var person = {
			name: 'YvetteLau',
			sayHi: sayHi
		}
		var name = 'Wiliam';
		var Hi = function(fn) {
			fn.call(this);
		}
		Hi.call(person, person.sayHi);//Hello, YvetteLau
		


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值