关于js中this的指向问题

215 阅读3分钟
              this在函数中的指向遵循两点原则
				1、谁引用他,他就指向谁
				2、就近原则
				
				
				一、普通函数中的this指向的都是window
				function f1(){
					this.a = 5;
				}
				f1();
				console.log(a);   //5  相当于console.log(window.a);
				
				
				var b = 10;
				function f2(){
					this.b = 20;
				}
				f2();
				console.log(b);   //先定义一个全局b为10;this又改变全局b的值为20,所以打印出的b的值为20.
				
				
				二 、对象中的this指向。
				1、当函数作为对象的属性来调用时,this的指向便指向了对象自身
				var obj1 = {
					a : 5,
					f1 : function(){
						console.log(this.a);    //5
						console.log(this === obj1);  //true
					}
				}
				obj1.f1();
				
				2、这就是说既然你函数都是我对象的一个属性了,那么你里面的this当然指向我,这种指向是一种隐式绑定this的现象,但是如果我们解除了这种隐式绑定呢?
				var obj2 = {
					b : 10,
					f2 : function(){
						console.log(this.b);  //undefined
						console.log(this === obj2); //false
					}
				}
				var init = obj2.f2;
				init();
				此时的this指向window
				注意,一定要看清函数在哪里调用的
				
				3、遵循就近原则调用
				虽然最终调用的是obj3,但是在遵循就近原则情况下,this指向的是obj4。
				var obj3 = {
					c: 10,
					obj4: {
						c: 10,
						f3: function() {
							console.log(this.c);
						}
					},
				}
				obj3.obj4.f3();
				
				4、将对象整体赋值给一个变量,和第二条有很大的区别。
				var obj5 = {
					a: 5,
					f5: function(){
						console.log(this.a); //5
						console.log(this === obj5); //true
					} 
				}
				var init = obj5;
				init.f5();
				
				三、call中的this关键字
				call()、bind()、apply()绑定this关键字又称为显示绑定,明面上我们可以完全看到他指向了谁。
				1、通过call()方法,函数f7被封装成obj6的一个属性。
				function f7(){
					this.x = function(){
						console.log(this.a);
					}
				}
				var obj6	= {
					a :20
				}
				f7.call(obj6);
				obj6.x();
				
				2、当call()不加参数,或参数为null时,默认this指向window
				function f8(){
					this.x = function(){
						console.log(this.a);
					}
				}
				var obj7 = {
					a:20
				}
				var a = 15;
				f8.call(); // f8.call(null);
				x();
				
				
				四、构造函数中的this,指向的是new的实例。
				new实例化的过程
				//new 过程如下
				{}
				//new 先创建了一个空对象{}(第一步)
				{}.__proto__ = F1.prototype 
				//空对象的隐式原型指向F1的原型对象(第二步)
				F1.call({});
				//利用call方法继承了F1中所有属性与方法,这一步将F1内部的this指向指向了这个空对象
				// 继而会执行这个空对象继承而来的内容,在最后
				return this; 
				//在我们不主动改变return 内容的时候,默认会将this返回出去	(第四步)
				//而Oinit = {}
				// 自然而然的最后this就指向了Oinit
			1、	实例:(不使用return)
				function F1(){
					this.a = 10;
					this.b = 20;
					this.f6 = function(){
						this.c = this.a + this.b;
						console.log(this.c);  //30
						console.log(this === F1); //false
					}
				}
				var oInt = new F1();
				oInt.f6();
			2、实例(使用return)
			在函数中如果返回的是一个对象(包括函数,数组,对象),即返回出来的是对象本身,就会覆盖原来的this对象,如果返回的是值类型, 则是返回this对象;
				function F2() {
					this.a = 10;
					var obj1 = {};
					obj1.a = 20;
					return this.a;
				}
				var init = new F2();
				console.log(init);  //F2{a : 10}
				
				
				function F2(){
					this.a = 10;
					var obj1 = {};
					obj1.a = 20;
					return obj1;
				}
				var init = new F2();
				console.log(init); //{a : 20}
				
				五、事件中使用this
				事件中,this的指向还是遵循一个原则,谁调用指向谁 + 就近原则;
				1、指向绑定的事件
				<div class="clickMe">click me</div>
				<script>
					var clickDom = document.querySelector('.clickMe');
				
					clickDom.onclick = function(){
						console.log(this.className) //clickMe
					}
				</script>
				
				2、谁调用指向谁
				<div class="clickMe">click me</div>
				<script>
					var clickDom = document.querySelector('.clickMe');
				
					clickDom.onclick = function(){
						
						function test(){ //相当于普通函数,this指向window
							console.log(this.className) //undefined
							console.log(this) //[object Window]
						}
						test();
						
					}
					</script>
				六、箭头函数中的this指向。
				// 什么时候使用箭头函数     当将一个函数作为参数传入到另一个函数中使用的是最多的.
				箭头函数中的this是如何查找的?
				向外层作用域中,一层层查找this,直到有this的定义。
				<script>
					var clickDom = document.querySelector('.clickMe');	
					clickDom.onclick = function(){	
						// function test(){ //相当于普通函数,this指向window
						// 	console.log(this.className) //undefined
						// 	console.log(this) //[object Window]
						// }
						// test();
						test = ()=>{
							console.log(this.className);  //clickMe
							console.log(this);   //<div class="clickMe">click me</div>
						}
						test()
					}
					</script>