Skip to content

Instantly share code, notes, and snippets.

@zhouyanyu
Last active November 6, 2023 02:17
Show Gist options
  • Save zhouyanyu/6c9b04f57e6be8b9824e6c1690733bb9 to your computer and use it in GitHub Desktop.
Save zhouyanyu/6c9b04f57e6be8b9824e6c1690733bb9 to your computer and use it in GitHub Desktop.
title date tags categories
this指向哪去了?
2017-12-12 10:54:01 -0800
JavaScript
JavaScript

我们知道ES5中的坑众多,尤其是this的只想问题,应该算是其中一个大坑了😣,今天总结一下关于this的指向问题,以及如何改变它们的指向,并对callapplebind进行区分。

this是啥?

很简单,this就是调用的那个对象,其实就是父级对象, 举个栗子:

var a = {
    b:'zyy',
    c:function(){
        console.log(a.b);//zyy
    }
}
a.c();

想在我们看到能打印zyy,可是我们要是把a换个名字,就会显示a未定义了,所以我们把它写成this指向父级,就不会发生这种错误了,这就是this。

var aaaa = {
    b:'zyy',
    c:function(){
        console.log(this.b);//zyy
    }
}
aaaa.c();

this的指向

其实乍一看可能觉得this的指向会有些混乱,但是我们只要记住一个真理-->this永远指向最后调用它的那个对象,我们的问题就会迎刃而解。

我们下面简单看几个例子。

默认绑定

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

在上面我们看到,this指向的就是Window,为什么呢?因为我们说过,它永远指向最后调用的对象,而Window正是这个全局变量,所以指向Window。

隐式绑定

var people = {
    name:'zyy',
    log:function(){
        console.log(this.name);//zyy
        console.log(this);//people
    }
}
people.log();

从这个例子中我们看到,我们调用的log函数是people这个对象中的,所以不出意外,this指向最后调用的对象本身。

即使现在你把调用改为了

window.people.log();

它也仍然会是以上的结果,因为最后调用的对象还是没变。

隐式丢失

还是回归上面的代码,我们定义一个变量:

var people = {
    name:'zyy',
    log:function(){
        console.log(this.name);//zyy
        console.log(this);//Window
    }
}
var f = people.log
f();

这时候你会发现:夭寿了!!!,this指向又变成全局对象了! 为什么!!! 因为**this永远指向最后调用它的那个对象**,这里没有对象调用,所以又默认了全局对象。

所以我们调用ajax的时候,为什么回调函数我们要加一个var self = this,因为函数调函数的时候,我们的this丢失了指向,通过这种方法我们可以找回指向。

通过这几个例子我们�只要记住,�找最后调用对象,就能找到指向。

注意,在严格模式下,�指向全局对象会显示�undefined。

如何改变指向

使用var self = this

var name = 'zyyWin';
var people = {
    name:'zyy',
    log:function(){
        var self = this;
        (function() {
            console.log(this.name);//>>> zyyWin
            console.log(this);//>>> window
            console.log(self.name);//>>> zyy
            console.log(self);//>>> people
        })();
    }
}
people.log();

显示:

VM8067:7 zyyWin
VM8067:8 Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
VM8067:9 zyy
VM8067:10 {name: "zyy", log: ƒ}

我在函数内部套了个自调用函数,通过self赋值this,这样最后调用时,就指向了people。

箭头函数

var name = 'zyyWin';
var people = {
    name:'zyy',
    log:function(){
        (() => {
            console.log(this.name);//>>> zyy
            console.log(this);//>>> people
        })();
    }
}
people.log();

显示:

VM8255:6 zyy
VM8255:7 {name: "zyy", log: ƒ}

关于箭头函数,只需记住,“箭头函数中的this是在定义函数的时候绑定,而不是在执行函数的时候绑定”。

使用callapplybind

继承已经介绍了call的使用方法,具体我要过一阵子在区分一下。

实例化new

实例化this指向会改变,我们也在原型和继承已经说过了,就不过多赘述了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment