美文网首页
深入理解JavaScript之this

深入理解JavaScript之this

作者: 萧玄辞 | 来源:发表于2017-10-24 09:05 被阅读0次

    this是JavaScript中的一个很特别的关键字,同时,它也是JavaScript中最复杂的机制之一,重要性同闭包、原型不相伯仲。如果你缺乏对this的清晰认识,this的指向足以让你眼花缭乱,这完全就是一种魔法。

    this是什么

    当一个函数被调用时,除了传入了函数的显式参数以外,名为this的隐式参数也被传入了函数。this引用了与该函数调用进行隐式关联的一个对象,被称之为函数上下文。函数上下文包含了函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息。this在函数运行时进行绑定,并不是在编写时绑定,它的上下文取决于函数调用时得各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式,而this则指的是调用函数的那个对象。

    现在,我们来看看在具体的调用方式中this是怎样的。

    一. 作为函数进行调用

    当一个函数作为函数进行调用时,是区别于其他调用机制:方法、构造器以及apply、call。

    使用这种方式进行调用通常在函数上使用了()操作符,使用了()操作符的表达式并没有将函数作为对象的一个属性。

    下面是一个示例:

    ``` js

    function foo(){

    console.log(this.a);

    }

    var a=2;

    foo();//2

    ```

    如你所见,a是声明在全局作用域中的变量,a也是全局对象的一个同名属性。当foo()被调用时,this.a被解析称为了全局变量a,因此this指向全局对象,函数的上下文是全局上下文——window对象。

    如果使用严格模式(strict mode),则this并不能指向全局对象,this此时将会指向undefined:

    ``` js

    function foo(){

    "use strict";

    console.log(this.a);

    }

    var a=2;

    foo();

    //TypeError: Cannot read property 'a' of undefined(…)

    ```

    二. 作为方法进行调用

    当一个函数被赋值为对象的一个属性,并使用引用该函数的这个属性进行调用时,那么函数就是作为对象的一个方法进行调用的。

    示例如下:

    ``` js

    var obj={

    a:2

    };

    obj.foo=function(){

    console.log(this.a);

    };

    obj.foo();//2

    ```

    如果你对面向对象了解的话,你肯定知道,一个方法所属的对象在该方法体内可以以this的形式进行引用。在这里,将函数作为对象的一个方法进行调用时,该对象就变成了函数的上下文,并且在函数内部可以以this参数的形式进行访问。

    请看下面示例:

    ``` js

    function foo(){

    console.log(this.a);

    }

    var obj={

    a:2,

    foo:foo

    };

    var bar=obj.foo;

    var a="two";

    bar();//"two"

    ```

    在这里,虽然bar是obj.foo的一个引用,但是实际上,它引用的是foo函数本身,因此此时的bar()其实是一个不带任何修饰的函数调用,因此this指向全局对象。当使用严格模式时,this指向undefined。

    三. 作为构造器进行调用

    将函数进行构造器(constructor)进行调用,我们要在函数进行调用前使用new关键字。

    ``` js

    function foo(){

    return this

    }

    new foo();

    ```

    将函数作为构造器进行调用,或者说使用new来调用函数,会自动执行下面的操作。

    - 创建一个新的空对象。

    - 传递给构造器的对象是this参数,从而成为构造器的函数上下文。

    - 如果没有显式的返回值,新创建的对象则作为构造器的返回值进行返回。

    请看下面代码:

    ``` js

    function foo(a){

    this.a=a;

    }

    var bar=new foo(2);

    console.log(bar.a);

    ```

    作为构造函数调用时foo()时,我们会构造一个新对象并把它绑定到foo(...)调用中的this上。

    四. 使用apply()/call()方法进行调用

    在函数调用的时候,JavaScript为我们提供了一种方式,可以显式指定任何一个对象作为其函数上下文。JavaScript的每个函数都有apply()和call()方法,它们的功能相同,仅仅是传入参数不同。

    通过函数的apply()方法来调用函数,我们要给apply()传入两个参数:一个是作为函数上下文的对象,另外一个是作为函数参数所组成的数组。call()方法的使用方式类似,唯一不同的是,给函数传入的参数是一个参数列表,而不是单个数组。

    请看示例:

    ``` js

    function foo(){

    console.log(this.a);

    }

    var obj={

    a:2,

    };

    foo.call(obj);

    ```

    在这段代码中,通过foo.call(...),我们在调用foo时强制把它的this绑定到obj上。

    总结

    如果要判断一个运行中函数的this绑定,就需要找到这个函数的直接调用位置,然后根据其调用方式来判断this的绑定对象。

    1. 作为构造器进行调用,this指向新创建的对象。

    2. 使用call/apply方法调用时,this指向指定的对象。

    3. 作为方法进行调用时,this指向拥有该方法的对象

    4. 作为普通函数进行调用时,this指向全局对象window,严格模式下指向undefined。

    相关文章

      网友评论

          本文标题:深入理解JavaScript之this

          本文链接:https://www.haomeiwen.com/subject/xaftpxtx.html