理解JS中this的指向
this 指代当前对象,若在全局内使用,则指代当前页面window;若在函数中使用,则依据当前函数被调用的对象而定,可初步理解为“谁调用就是谁”。
一、this的指向在函数定义时是无法确定的,只有函数执行时才能确定this到底指向谁。
1 function demo() { 2 console.log(this.fruit); 3 } 4 // 定义全局变量,等同于window.fruit = "banana"; 5 var fruit = "banana"; 6 // 此时函数中的this指向window; 7 demo(); // "banana" 8 9 var obj = { 10 fruit : "apple", 11 demo : demo 12 }; 13 // 此时函数中的this指向obj 14 obj.demo(); // "apple"
二、JS中函数也是对象,可定义属性
1 function demo() { 2 if(this === window){ 3 console.log("this is window"); 4 } 5 }; 6 // 函数也是对象,可以为对象定义属性,值为函数 7 demo.bar = function(){ 8 if(this === demo){ 9 console.log("this is demo"); 10 }else if(this === window){ 11 console.log("this is window"); 12 } 13 }; 14 15 // 等价于 window.demo(); 16 demo(); // "this is window"; 17 // 函数中this指向调用函数的对象 18 demo.bar(); // "this is demo"; 19 // 可以使用call改变函数中this指向 20 demo.bar.call(window); // "this is window";
三、对象中嵌套函数的this指向不是当前对象,而是window
1 var name = "window.name"; 2 var obj = { 3 name : "obj.name", 4 getName:function(){ 5 console.log(this.name); 6 return function(){ //return 返回一个函数, 7 console.log(this.name); 8 } 9 } 10 } 11 obj.getName()(); // "obj.name" "window.name"
obj.getName()执行后返回一个函数,这个返回函数再次执行是被window对象调用的,因此前者this指向obj对象,后者指向window对象。可通过三种方式改变此this指向。
1、使用函数的bind方法
1 var name = "window.name"; 2 var obj = { 3 name : "obj.name", 4 getName:function(){ 5 console.log(this.name); 6 return function(){ 7 console.log(this.name); 8 }.bind(this); 9 } 10 }; 11 obj.getName()(); // "obj.name" "obj.name"
2.使用变量接收上面的this,下面使用变量替代
1 var name = "window.name"; 2 var that = null; 3 var obj = { 4 name : "obj.name", 5 getName:function(){ 6 that = this; 7 console.log(this.name); 8 return function(){ 9 console.log(that.name); 10 } 11 } 12 } 13 obj.getName()(); // "obj.name" "obj.name"
3.使用ES6的箭头函数
1 var name = "window.name"; 2 var obj = { 3 name : "obj.name", 4 getName:function(){ 5 console.log(this.name); 6 return () => { 7 console.log(this.name); 8 } 9 } 10 } 11 obj.getName()(); // "obj.name" "obj.name"
四、全局函数apply和call可以用来改变this的指向
apply和call的唯一区别,就是在传参的时候,apply的参数需要放在一个数组里面,而call不需要。
1 function demo(){ 2 console.log(this.fruit); 3 } 4 // 定义一个全局变量,等同于window.fruit = "banana"; 5 var fruit = "banana"; 6 7 var obj = { 8 fruit : "apple" 9 }; 10 demo(); //相当于window.demo()和demo.apply(window); 11 demo.apply(window); // "banana"; 12 demo.call(obj); // "apple";
所谓勇者,不过是在认清生活真相之后,依然热爱生活!