11 this

33 阅读3分钟
var bar = {  
    myName:"a",  
    printName: function () {  
        console.log(myName)  
    }  
}
bar.printName()  

// 在js中没有办法像c++,那样可以直接在方法里面访问成员属性。作用域链不支持,所以又搞出了一套this的机制。

作用域链和this是完全两套不同的系统不要搞混了。 他们之间基本上没有任何联系。

看一下执行上下文的结构图 上下文outer相关的文章 zhuanlan.zhihu.com/p/302840261

变量环境(outer) 词法环境

this 可以看到this的是执行上下文绑定的

因为this是执行上下文绑定,执行上下文有三种对应的this就有三种 全局this、函数this、eval this。eval用的比较少一些所以就不介绍了着重聊聊 全局上下文this和函数this.

全局执行上下文this?

你可以在控制台中输入console.log(this)来打印出来全局执行上下文中的this,最终输出的是window
对象。所以你可以得出这样一个结论:全局执行上下文中的this是指向window对象的。这也是this和作用域链的唯一交点,作用域链的最底端包含了window对象,全局执行上下文中的this也是指向window对象

函数执行上下文this?

function foo(){  
    console.log(this)  
}  
foo()

// 我们在foo函数内部打印出来this值,执行这段代码,打印出来的也是window对象,这说明在默认情况下调用一个函数,其执行上下文中的this也是指向window对象的。

改变this的指向

1.通过函数的call方法设置 2.bind 3.apply 4.通过对象方法调用xxx.xxx(); 使用对象来调用其内部的一个方法,该方法的this是指向对象本身的 xxx.xxx() 可以理解为 xxx.xxx.call(xxx);

var myObj = {  
    name : "极客时间",  
    showThis: function(){  
    this.name = "极客邦"  
    console.log(this)  
   }  
}  
var foo = myObj.showThis  
foo()

// myObj.showThis给到了foo foo 是在全局执行的所以this被指向了window,可以理解 foo.call(window);

在全局环境中调用一个函数,函数内部的this指向的是全局变量window

通过一个对象来调用其内部的一个方法,该方法的执行上下文中的this指向对象本身

5.通过构函数设置this

function a(){this.a = 1}; 
var b = new a();

// new xx 首先创建了一个空对象tempObj;
// 接着调用a.call方法,并将tempObj作为call方法的参数,这样当a的执行上下文创建时,它的this就指向了tempObj对象;
// 然后执行a函数,此时的a函数执行上下文中的this指向了tempObj对象;
// 最后返回tempObj对象

// 拆分流程
var tempObj = {};
a.call(tempObj)
return tempObj;

这样,我们就通过new关键字构建好了一个新对象,并且构造函数中的this其实就是新对象本身

this的设计缺陷以及应对方案

1.嵌套函数中的this不会从外层函数中继承

var myObj = {  
    name : "极客时间",  
    showThis: function(){  
    console.log(this)  
    function bar(){console.log(this)}   // 指向了window
    bar()  
  }  
}
// 会发现函数bar中的this指向的是全局window对象,而函数showThis中的this指向的是myObj对象函数
// 解决方案上下文存一个_self=this 或者直接箭头函数搞定。
// ES6中的箭头函数并不会创建上下文 所以它的this就是外部的集成过来的。

通过上面的讲解,你现在应该知道了this没有作用域的限制,这点和变量不一样,所以嵌套函数不会从调用它的函数中继承this,这样会造成很多不符合直觉的代码。要解决这个问题,你可以有两种思路。

第一种是把this保存为一个self变量,再利用变量的作用域机制传递给嵌套函数

第二种是继续使用this,但是要把嵌套函数改为箭头函数,因为箭头函数没有自己的执行上下文,所以它会继承调用函数中的this。

普通函数this指向window 可以使用js中写入"use strict" 来阻断 this指向window这个时候this就是undefined.