浏览器环境下this指向问题总结

一.全局执行:

1.在全局作用域中 this 指向当前的全局对象 Window

2.代码:

	console.log(this);
	// Window

二.函数中执行:

1.非严格模式中:

(1) this指向Window

(2)代码:

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

2.严格模式中:

(1)this未定义undefined

(2)代码:

		"use strict";
		function func () {
			  console.log(this);
		}
		func();
		// undefined	

三.作为对象的方法调用:

1.当一个函数被当作一个对象的方法调用的时候,this 指向当前的对象 obj

代码:

		var obj = {
			  name: 'kk',
			 func: function () {
   					 console.log(this.name);
			 }
		}
		obj.func();
		// kk

2.如果把对象的方法赋值给一个变量,调用该方法时,this 指向 Window:

代码:

		var obj = {
			  name: 'kk',
			 func: function () {
  					  console.log(this);
				}
		}
		var test = obj.func;
		test();
		// Window

四.作为一个构造函数使用:

1.为了实现类,我们需要定义一些构造函数,在调用一个构造函数的时候加上 new 这个关键字

代码:

		function Person (name) {
			  this.name = name;
				  console.log(this);
		}
		var p1 = new Person('kk');
		// Person

this 指向这个构造函数调用的时候实例化出来的对象

2.若将构造函数当做普通函数来调用,this 指向 Window:

代码:

		function Person (name) {
			  this.name = name;
				  console.log(this);
		}
		var p2 = Person('MM');
		// Window

五.在定时器中使用:

1.如果没有特殊指向,setInterval 和setTimeout 的回调函数中 this 的指向都是 Window 。这是因为 JS 的定时器方法是定义在 Window 下的

2.示例代码:

	setInterval(function () {
			console.log(this);
	}, 2000)
	// Window

六.箭头函数:

1.在全局环境中调用:

	var func = () => {
		 console.log(this);
	}
	func();
	// Window

2.作为对象的一个函数调用:

普通函数作为对象的一个函数被调用,this 指向 obj,箭头函数作为对象的一个函数被调用,this 指向 Window

代码:

		var obj = {
		   name: 'hh',
		  func: function () {
 				  console.log(this);
			 }
		}
		obj.func();
		// obj

		var obj = {
		      name: 'hh',
		      func: () => {
			    console.log(this);
			 }
		}
		obj.func();
		// Window

3.结合定时器调用的特殊情况:

(1)若在对象的函数中,普通函数作为定时器延时执行的函数调用,this 指向 Window

代码:

			var obj = {
				 name: 'hh',
				   func: function () {
  						  setTimeout(function () {
     							   console.log(this);
  						  }, 0)
				 }
			}
			obj.func();
			// Window

(2)箭头函数作为定时器延时执行的函数调用, this 指向定义时所在的对象,也就是 func 中的 this,即 obj。

代码:

			var obj = {
				 name: 'hh',
				  func: function () {
						    setTimeout(() => {
       							 console.log(this);
						    }, 0)
				 }
			}
			obj.func();
			// obj

4.总结:

箭头函数中 this 的值取决于该函数外部非箭头函数的 this 的值,且不能通过 call() 、 apply() 和 bind() 方法来改变 this 的值

有定时器延时执行时除外

七.call、apply、bind:

1.call:

(1)语法:

		fun.call(thisArg[, arg1[, arg2[, ...]]])

(2)会立即执行函数,第一个参数是指定执行函数中 this 的上下文,后面的参数是执行函数需要传入的参数

2.apply:

(1)语法:

		fun.apply(thisArg, [argsArray])

(2)会立即执行函数,第一个参数是指定执行函数中 this 的上下文,第二个参数是一个数组,是传给执行函数的参数(与 call 的区别)

3.bind:

(1)语法:

		var foo = fun.bind(thisArg[, arg1[, arg2[, ...]]]);

(2)不会执行函数,而是返回一个新的函数,这个新的函数被指定了 this 的上下文,后面的参数是执行函数需要传入的参数;

4.使用示例代码:

	function Person(name, age) {
		 this.name = name;
		 this.age = age;
		 console.log(this);
	}
	var obj = {
		 name: 'kk',
		 age: 6
	};
	Person.call(obj, 'mm', 10);
	// obj,{name: "mm", age: 10}

	Person.apply(obj, ['mm', 10]);
	// obj,{name: "mm", age: 10}

	var p1 = Person.bind(obj, 'mm', 10)
	var p2 = new p1();
	// Person {name: "mm", age: 10}

5.三者区别:

(1)call、apply 会立即执行函数,call 和 apply 的区别就在于传递的参数,call 接收多个参数列表,apply 接收一个包含多个参数的数组;

(2)bind 不是立即执行函数,它返回一个函数,需要执行 p2 才能返回结果,bind 接收多个参数列表

八.怎么改变this的指向:

1.使用 es6 的箭头函数:

(1)修改前代码:

		var name = "hh";
		var obj = {
			  name : "kk",
				 func1: function () {
  					  console.log(this.name)     
				  },
			  func2: function () {
   					 setTimeout(function () {
      						  this.func1()
   						 }, 1000);
			 }
		};

		obj.func2();
		// Uncaught TypeError: this.func1 is not a function

		//会报错,因为 setTimeout 里函数的 this 指向 Window,而 Window 对象上是没有 func1 这个函数的

(2)修改后代码:

		var name = "hh";
		var obj = {
			 name : "kk",
			 func1: function () {
  					  console.log(this.name)     
			 },
			  func2: function () {
   					 setTimeout(() => {
    						    this.func1()
 					   }, 1000);
			   }
		};

		obj.func2();
		// kk	
		
		//没有报错,因为箭头函数的 this 的值取决于该函数外部非箭头函数的 this 的值,也就是 func2 的 this 的值, 即 obj

2.在函数内部使用 _this = this:

(1)示例代码:

		var name = "hh";
		var obj = {
			  name : "kk",
			  func1: function () {
				     console.log(this.name)     
			  },
			  func2: function () {
 					   let _this = this;
  					  setTimeout(function () {
     							   _this.func1()
 					  	 }, 1000);
			 }
		};

		obj.func2();
		// kk

(2)在 func2 中,首先设置 var _this = this,这里的 this 是指向 func2 的对象 obj,为了防止在 func2 中的 setTimeout 被 window 调用而导致的在 setTimeout 中的 this 为 window。

我们将 this (指向变量 obj) 赋值给一个变量 _this,这样,在 func2 中我们使用 _this 就是指向对象 obj 了

3.使用 call、apply、bind:

(1)call代码示例:

		var name = "hh";
		var obj = {
			    name : "kk",
			  func1: function () {
   					 console.log(this.name)     
			   },
			  func2: function () {
 					   setTimeout(function () {
      							  this.func1()
  					  }.call(obj), 1000);
			  }
		};

		obj.func2();
		// kk

(2)apply示例代码:

		var name = "hh";
		var obj = {
			 name : "kk",
			 func1: function () {
					    console.log(this.name)     
			 },
			 func2: function () {
  					  setTimeout(function () {
   							     this.func1()
				     }.apply(obj), 1000);
			 }
		};

		obj.func2();
		// kk

(3)bind示例代码:

		var name = "hh";
		var obj = {
			   name : "kk",
				func1: function () {
 					   console.log(this.name)     
			 },
			 func2: function () {
    					setTimeout(function () {
       							 this.func1()
					    }.bind(obj)(), 1000);
			 }
		};

		obj.func2();
		// kk

4.new实例化一个对象:

作为一个构造函数使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值