快捷搜索: 王者荣耀 脱发

彻底搞懂Js中this指向,Js中this通俗易懂讲解

静态作用域与动态作用域

Javascript 采用的是词法作用域(静态作用域),也就是说函数的作用域(可以访问到的变量)在函数定义的时候就确定了。

与之相反的是动态作用域,即函数的作用域在函数调用时才确定。

下边的代码可以很好的说明Js是一个静态作用域语言,如果函数的作用域是在运行时确定的话,运行foo函数时, 从 foo 函数内部没有找到局部变量 value后,会从调用函数的作用域,也就是 bar 函数内部查找 value 变量,那么会打印 2。

Js引擎底层的实现为:函数在定义的时候,会把其所属环境(全局环境)的变量生成一个变量对象放入到函数的scope属性,调用函数时,会生成执行环境并创建一个作用域链,即先把函数scope属性中的变量对象放到作用域链中,再利用函数参数和内部变量生成一个活动对象,并放入作用域链的前端。

var value = 1;
function foo() {
          
   
    console.log(value);
}
function bar() {
          
   
    var value = 2;
    foo();
}
 
bar(); // 1  

this 关键字是 JS 中的动态作用域机制,是为了在 JS 中加入动态作用域而做的努力,因为this指向的对象是在函数调用时绑定的。

在任何函数中,this的指向都不是静态的(static)。它总是在你调用一个函数,但尚未执行函数内部代码前被指定。即this的指向与函数被调用的方式(语法)有关。

下边的代码可以很好的说明这一点

var o = {
          
   
    a: 10,
    b: {
          
   
        fn: function() {
          
   
            console.log(this);
        }
    }
}
o.b.fn(); //指向o中的对象b
var j = o.b.fn;
j(); //指向全局对象

上述代码的执行结果为

可以看到,函数内部的this指向和其调用方式有关,和函数本身的定义方式无关

绑定规则

this对象有四种绑定规则,优先级有高到低分别如下:

  1. 构造绑定:通过new关键字调用构建函数。此时会生成一个实例对象,并且this指向这个实例对象。这种方式实际上是new的底层实现修改了this指向 var savedThis; function Constr() { // 保存构造函数中的this savedThis = this; } // 通过new关键字执行构造函数 var inst = new Constr(); // 构造函数中的this指向的就是新创建的对象实例inst console.log(savedThis === inst); // true
  2. 显式绑定:apply()、call()、bind()三个方法改变函数的调用对象(this对象)
  3. 隐式绑定:某个上下文对象中调用函数。比如使用 obj.foo() 这样的语法来调用函数,函数 foo 中的 this 绑定到 obj 对象 //对象的方法 var o = { a:10, b:{ fn:function(){ console.log(this.a); //undefined,this指向b对象 } } } o.b.fn(); // 事件处理函数 function doAlert() { alert(this); } doAlert(); // 全局对象 var myElem = document.getElementById(test); myElem.onclick = doAlert; myElem.onclick(); // 指向myElem元素
  4. 默认绑定:不符合上述三种情况,在一个函数中使用了 this,但是没有为 this 绑定对象。这种情况下,严格模式this绑定到undefined,非严格模式this绑定到全局对象(Node 环境中的 global,浏览器环境中的window) var o = { a:10, b:{ a:12, fn:function(){ console.log(this.a); //undefined console.log(this); //window } } } var j = o.b.fn; j();

对于3、4两点,可以用一个简单的规则去判断

当一个函数被调用时,应该立马看()左边的部分。

    如果()左边是一个引用(reference),那么函数的this指向这个引用所属的对象(隐式绑定) 否则this指向的就是全局对象或者undefined(默认绑定)

上边代码中fn是一个引用,属于b这个对象,所以this指向b;j不是引用,所以this指向window

经验分享 程序员 微信小程序 职场和发展