• 对this关键字的深入探究


      this无疑是javascript中特别复杂的机制了,最使我们困扰的就是this的指向,仅以本文对我所理解的this做一个总结和记录。每一句话都是重点!文章参考《你不知道的javascript》。

      首先需要对this有一个大概的理解:每个函数的this都是在调用时被绑定的,完全取决于函数的调用位置。

    绑定规则

      当我们找到函数的调用位置以后,需要判断应用了哪条绑定规则,绑定规则分为四种:默认绑定,隐式绑定,显式绑定,new绑定。

    一,默认绑定

      这是最常用的函数调用类型:独立函数调用。可以把这条规则看作是无法应用其他规则时的默认应用。

      如下,这里的foo()是直接使用不带任何修饰的函数引用进行调用的,因此只能使用默认绑定,无法应用其他规则。

    function foo() {
        console.log(this.a);
    }
    var a = 2;
    foo();    //2

      注意虽然this的绑定规则完全取决于调用位置,但是只有foo()运行在非严格模式下默认绑定才能绑定到全局对象。严格模式下与foo()的调用位置无关。如果使用严格模式,那么全局对象将无法使用默认绑定,因此会绑定到undefined。

    function foo() {
        "use strict";
        console.log(this.a);
    }
    var a = 2;
    foo();

      报错:

    二,隐式绑定

      这条规则需要考虑的是调用位置是否有上下文对象,或者说是否被某个对象拥有或包含。当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象像下面这个样子,调用foo()时this被绑定到obj,因此this.a和obj.a是一样的:

      对象属性引用链中只有最后一层会影响调用位置。

    function foo() {
        console.log(this.a);
    };
    var obj2 = {
        a: 32,
        foo: foo
    }
    var obj1 = {
        a: 2,
        obj2: obj2
    };
    obj1.obj2.foo();    //32

    隐式丢失

      这也是最常见的this绑定问题了,被隐式绑定的函数会丢失绑定对象,也就是说会应用默认绑定,从而把this绑定到全局对象或者undefined上(取决于是否严格模式)。

      有以下几种情况:

      1.虽然bar是obj.foo的引用,但是实际上它引用的是foo函数本身,此时的bar便是一个不带任何修饰的函数调用,因此应用了默认样式。

    function foo() {
        console.log(this.a);
    };
    var obj = {
        a: 2,
        foo: foo
    }
    var bar = obj.foo;
    var a = "global";
    bar();    //global

      2.参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值。

    function foo() {
        console.log(this.a);
    };
    function doFoo(fn) {
        fn();
    }
    var obj = {
        a: 2,
        foo: foo
    }
    var a = "global";
    doFoo(obj.foo);    //global

      3.参数传入内置函数时也是一样

    function foo() {
        console.log(this.a);
    };
    var obj = {
        a: 2,
        foo: foo
    }
    var a = "global";
    setTimeout(obj.foo, 100);    //global

    三,显式绑定

      如果不想在对象内部包含函数引用,而想在某个对象上强制调用函数,可以使用call()和apply()方法,它们的第一个参数时对象,会把这个对象绑定到this。称之为显式绑定

      强制把foo的this绑定到obj,无论之后如何调用bar,总是会在obj上调用。

    function foo() {
        console.log(this.a);
    };
    var obj = {
        a: 2
    }
    var bar = function() {
        foo.call(obj);
    }
    bar();    //2
    setTimeout(bar, 100);    //2
    bar.call(window);    //2  

    四,new绑定

      使用new来调用foo时,会构造一个新的对象并把它绑定到foo()调用中的this上。

    function foo(a) {
        this.a = a;
    };
    var bar = new foo(2);
    console.log(bar.a);    //2

    优先级

      既然几种绑定规则讨论完了,那么我们来比较一下他们的优先级顺序。细节不做讨论,可以自行测试。总之结果是:new绑定 > 显式绑定 > 隐式绑定 > 默认绑定

      也就是说:

      如果函数在new中调用,则this指向的是新创建的对象;再看是否通过call,apply调用,是的话this就指向指定的那个对象;然后看是否在某个上下文调用,如果是,就指向这个上下文对象;最后若都没有就是默认绑定了。

     

  • 相关阅读:
    C++小结
    进程
    JavaScript中如何获取当前点击对象信息!
    form表单中enctype="multipart/form-data"的传值问题
    WebMagic框架总结
    工具类:自己总结的利用fileupload包上传文件的工具类!
    工具类:关于如何找到两个List数组中不同的数据的算法!
    工具类:关于解决数据库中的日期格式,经过response.getWriter().write(json)打到前台日期格式混乱的问题的总结
    工具类:将其他编码类型转换成UTF-8或者其他类型的工具类
    博主收藏的前端框架,极力推荐!
  • 原文地址:https://www.cnblogs.com/PeriHe/p/8452053.html
Copyright © 2020-2023  润新知