为了彻底搞懂 JS 中 this 机制,我总结了以下三种情况

686 阅读3分钟

这是我的第一篇掘金博客,开启掘金写作之路。

在学习JavaScript函数部分时,对于this指向问题有很大的疑惑。为了彻底搞懂 JS 中 this 机制,我通过某站和博客进行学习,我总结了以下三种情况。

实在搞不清楚时候,我都是这样来记的:不管函数是按哪种方法来调用的,谁调用这个函数或方法,this关键字就指向谁。

一、函数调用中this的指向

1.全局环境

全局环境下this就是window对象的引用

<script> 
console.log(this == window); //true 
console.log(this instanceof Object); //true 
</script> 

2.类中的方法

this指的是当前对象

let obj ={ name:'simonzhangs', 
show:function(){ console.log(this); 
return this.name; } } 
console.log(obj.show());//{name: 'simonzhangs', show: ƒ} 
//simonzhangs​

3.类中的方法中函数

在该函数中,是普通函数,this指的是window对象

let obj ={ name:'simonzhangs', 
show:function(){ 
    function show2(){ 
            console.log(this); 
            } show2(); 
       } 
    } 
    console.log(obj.show());​

二、方法调用中this的指向

可以使用构造函数和对象字面量来创建对象,上面提到函数为对象的方法时this 指向该对象。以下为两种创建对象方法实例:

1.构造函数方法

函数当被 new 时即为构造函数,一般构造函数中包含属性与方法。函数中的上下文指向到实例对象。

构造函数主要用来生成对象,里面的this默认就是指当前对象

function User() { 
    this.name = "simonzhangs"; 
    this.say = function() { 
        console.log(this); //User {name: 'simonzhangs', say: ƒ} 
        return this.name; 
     }; 
 } 
let juejin = new User(); 
console.log(juejin.say()); //simonzhangs​

2.对象字面量方法

下例中的show1函数不属于对象方法所以指向window

show属于对象方法执向 obj对象

let obj = { site: "juejin", 
show() { console.log(this.site); //juejin 
    console.log(`this in show() method: ${this}`); //this in show() method: [object Object] 
    function show1() { 
    console.log(typeof this.site); //undefined 
    console.log(`this in show1() function: ${this}`); //this in show1() function: [object Window] } 
    show1(); } }; 
    obj.show();​

3.在方法中使用函数可以改变this指向

forEach,当然还包括apply/call/bind

在show方法中,使用map函数,增加this参数可将this指向当前对象

let Lesson = { site: "掘金", 
lists: ["后端", "前端", "Android"], 
show() { return this.lists.map(function(title) { 
        return `${this.site}-${title}`; 
        }, this); 
    } 
}; 
console.log(Lesson.show()); //['掘金-后端', '掘金-前端', '掘金-Android']​

​也可以在父作用域中定义引用this的变量,将函数中的this指向当前对象,而不是window对象​

let Lesson = { site: "掘金", 
lists: ["后端", "前端", "Android"], 
show() { 
    const that = this; 
    return this.lists.map(function(title) { 
        return `${that.site}-${title}`; 
        }); 
    } 
}; 
console.log(Lesson.show());//['掘金-后端', '掘金-前端', '掘金-Android']​

三、箭头函数中没有this

箭头函数没有this, 也可以理解为箭头函数中的this 会继承定义函数时的上下文,

可以理解为和外层函数指向同一个this。

1.如果想使用函数定义时的上下文中的this,可以选择使用箭头函数

未使用箭头函数时,返回的是window对象下name属性值 ​

var name = 'juejin'; 
var obj = { 
    name: 'juejin-js', 
    getName: function () { 
        return function () { 
        return this.name; 
        } 
     } 
 } 
console.log(obj.getName()()); //返回window.name的值juejin​

使用箭头函数时,this 为定义该函数的上下文,即为定义时父作用域中的this,指向的是obj​

var name = 'juejin'; 
var obj = { 
    name: 'juejin-js', 
    getName: function () { 
        return () => this.name; 
    } 
} 
console.log(obj.getName()()); //返回obj.name的值juejin-js​

2.涉及dom对象操作时,this指向的情况

在bind()方法中,使用addEventListener来监听dom元素,此时this指向的是dom对象,即button标签 ​

<body> 
    <button btn="juejin-js">button</button> 
<script> 
    let Dom = { 
    site: "juejin", 
    bind:function() { 
        const btn= document.querySelector("button"); 
        btn.addEventListener("click", function() { 
            console.log(this.getAttribute("btn")); //juejin-js 
            }); 
         } 
    };
    Dom.bind(); 
</script> 
</body>

在使用箭头函数时,this则执行上下文对象,要想获取dom对象,需要用到event对象来获取。​

<body> 
    <button>button</button>
</body> 
<script>
    let Dom = { site: "juejin", 
    bind() { 
        const button = document.querySelector("button"); 
        button.addEventListener("click", event => { 
            alert(this.site + event.target.innerHTML); //juejinbutton 
            }); 
        } 
    }; 
Dom.bind(); 
</script>

欢迎大家在评论区提出意见和建议!