• 浅谈js中的this关键字


    ---恢复内容开始---

    this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字this尤为重要。接下来,笔者就从作用域的角度粗谈下自己对this关键字的理解,希望能给到大家一些启示,权当交流之用。

    全局作用域中的this

    本文将以作用域由外至内的方式逐步理解this关键字。首先,看下面这行代码:

    console.log(this); // Window {top: Window, location: Location, document: document, window: Window, external: Object…}    Window全局对象

    在浏览器中执行上面的语句后,我们将得到一个Window对象,这是一个全局对象。在全局作用域内,我们可以通过this访问到所有的全局属性。如下代码所示:

    var a = 1;
    console.log(this.a); // 1

    函数作用域中的this

    现在,我们将this关键字放到函数作用域中,测试代码如下:

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

    我们可以看到此时打印出来的结果仍然是1,也就是说这时候this指向的还是全局对象。

    这里也可以澄清的是,this并没有指向函数作用域(或者说是并没有指向函数作用域链中的活动对象,有关活动对象的概念可以参考JavaScript速记5 —— 执行环境、变量对象和作用域链),那么this是否会指向函数本身呢,我们接着来看下面一个例子:

    var a = 1;
    function test(){
        var a = 2;
        console.log(this.a); // 1
    }
    test.a = 3;
    test();

    通过上面的例子,我们知道this也并未指向函数本身。上面的例子中,this最终指向的都是全局对象,那么什么情况下this会指向其他对象呢,我们再来看下面的例子:

    var a = 1;
    function test(){
        var a = 2;
        console.log(this.a); // 3
    }
    var obj = {a: 3};
    test.call(obj);

    上面的例子中this指向了对象obj。既然只有当函数被调用时,才能确定this指向的对象,那么下一节我们就针对不同的函数调用方法下,逐一说明this的使用。

    不同函数调用方法下的this

    直接调用

    var a = 1;
    function test(){
        console.log(this.a); //1
    }
    test();

    很明显,函数被直接调用是this指向的就是全局对象。

    作为对象的方法调用

    var a = 1;
    function test(){
        console.log(this.a); // 2
    }
    var obj = {a: 2, fn: test};
    obj.fn();

    当函数作为对象的方法被调用时,this指向当前调用该方法的对象。

    作为构造函数调用

    var a = 1;
    function test(){
        this.a = 2;
    }
    var obj = new test();
    console.log(a); // 1
    console.log(obj.a); // 2

    通过上面的代码结果可以看到,全局对象中的属性a并没有被改变,此时this指向该构造函数创建的对象。

    通过call或apply方法调用

    call和apply都是Function对象的方法,都可以用来动态改变this的指向,达成函数复用的目的。这里笔者不在详细介绍这两个方法,有兴趣的读者可以参考相关文章。需要特别说明的是,这两个方法的第一个参数就是this。由于这两个方法的用法类似,这里我们仅以call方法为例。上例子:

    var a = 1;
    function test(){
        console.log(this.a); // 1
    }
    test.call();

    call方法的第一个参数是this,在没有实参的情况下,上面例子中this默认指向的对象就是全局对象。我们再来看一个例子:

    var a = 1;
    function test(){
        console.log(this.a); // 1
    }
    var obj = {a: 2, fn: test};
    obj.fn.call();

    上面的例子进一步证明了,即便使用对象的方法调用call,this默认指向的依旧是全局对象。为了改变this的指向,我们需要显式的传递第一个参数过去,如下代码:

    var a = 1;
    function test(){
        console.log(this.a); // 2
    }
    var obj = {a: 2};
    test.call(obj);

    嵌套函数作用域中的this

    文章的最后我们再来看一下嵌套函数中的this引用。示例代码如下:

    var a = 1;
    function test(){
        console.log(this.a); // 2
        function test2(){
            console.log(this.a); // 1
        }
        test2();
    }
    var obj = {a: 2, fn: test};
    obj.fn();

    上面的例子说明,嵌套函数被调用是并没有继承被嵌套函数的this引用,在嵌套函数被调用时,this指向全局对象。在有些应用中,我们需要在嵌套函数中读取调用被嵌套函数的对象的属性,此时可以声明一个局部变量保存this引用,代码如下所示:

    var a = 1;
    function test(){
        console.log(this.a); // 2
        var self = this;
        function test2(){
            console.log(self.a); // 2
        }
        test2();
    }
    var obj = {a: 2, fn: test};
    obj.fn();

    ---恢复内容结束---

    this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字this尤为重要。接下来,笔者就从作用域的角度粗谈下自己对this关键字的理解,希望能给到大家一些启示,权当交流之用。

    全局作用域中的this

    本文将以作用域由外至内的方式逐步理解this关键字。首先,看下面这行代码:

    console.log(this); // Window {top: Window, location: Location, document: document, window: Window, external: Object…}    Window全局对象

    在浏览器中执行上面的语句后,我们将得到一个Window对象,这是一个全局对象。在全局作用域内,我们可以通过this访问到所有的全局属性。如下代码所示:

    var a = 1;
    console.log(this.a); // 1

    函数作用域中的this

    现在,我们将this关键字放到函数作用域中,测试代码如下:

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

    我们可以看到此时打印出来的结果仍然是1,也就是说这时候this指向的还是全局对象。

    这里也可以澄清的是,this并没有指向函数作用域(或者说是并没有指向函数作用域链中的活动对象,有关活动对象的概念可以参考JavaScript速记5 —— 执行环境、变量对象和作用域链),那么this是否会指向函数本身呢,我们接着来看下面一个例子:

    var a = 1;
    function test(){
        var a = 2;
        console.log(this.a); // 1
    }
    test.a = 3;
    test();

    通过上面的例子,我们知道this也并未指向函数本身。上面的例子中,this最终指向的都是全局对象,那么什么情况下this会指向其他对象呢,我们再来看下面的例子:

    var a = 1;
    function test(){
        var a = 2;
        console.log(this.a); // 3
    }
    var obj = {a: 3};
    test.call(obj);

    上面的例子中this指向了对象obj。既然只有当函数被调用时,才能确定this指向的对象,那么下一节我们就针对不同的函数调用方法下,逐一说明this的使用。

    不同函数调用方法下的this

    直接调用

    var a = 1;
    function test(){
        console.log(this.a); //1
    }
    test();

    很明显,函数被直接调用是this指向的就是全局对象。

    作为对象的方法调用

    var a = 1;
    function test(){
        console.log(this.a); // 2
    }
    var obj = {a: 2, fn: test};
    obj.fn();

    当函数作为对象的方法被调用时,this指向当前调用该方法的对象。

    作为构造函数调用

    var a = 1;
    function test(){
        this.a = 2;
    }
    var obj = new test();
    console.log(a); // 1
    console.log(obj.a); // 2

    通过上面的代码结果可以看到,全局对象中的属性a并没有被改变,此时this指向该构造函数创建的对象。

    通过call或apply方法调用

    call和apply都是Function对象的方法,都可以用来动态改变this的指向,达成函数复用的目的。这里笔者不在详细介绍这两个方法,有兴趣的读者可以参考相关文章。需要特别说明的是,这两个方法的第一个参数就是this。由于这两个方法的用法类似,这里我们仅以call方法为例。上例子:

    var a = 1;
    function test(){
        console.log(this.a); // 1
    }
    test.call();

    call方法的第一个参数是this,在没有实参的情况下,上面例子中this默认指向的对象就是全局对象。我们再来看一个例子:

    var a = 1;
    function test(){
        console.log(this.a); // 1
    }
    var obj = {a: 2, fn: test};
    obj.fn.call();

    上面的例子进一步证明了,即便使用对象的方法调用call,this默认指向的依旧是全局对象。为了改变this的指向,我们需要显式的传递第一个参数过去,如下代码:

    var a = 1;
    function test(){
        console.log(this.a); // 2
    }
    var obj = {a: 2};
    test.call(obj);

    嵌套函数作用域中的this

    文章的最后我们再来看一下嵌套函数中的this引用。示例代码如下:

    var a = 1;
    function test(){
        console.log(this.a); // 2
        function test2(){
            console.log(this.a); // 1
        }
        test2();
    }
    var obj = {a: 2, fn: test};
    obj.fn();

    上面的例子说明,嵌套函数被调用是并没有继承被嵌套函数的this引用,在嵌套函数被调用时,this指向全局对象。在有些应用中,我们需要在嵌套函数中读取调用被嵌套函数的对象的属性,此时可以声明一个局部变量保存this引用,代码如下所示:

    var a = 1;
    function test(){
        console.log(this.a); // 2
        var self = this;
        function test2(){
            console.log(self.a); // 2
        }
        test2();
    }
    var obj = {a: 2, fn: test};
    obj.fn();
  • 相关阅读:
    elasticsearch query 和 filter 的区别
    java 模拟简单搜索
    filterBuilders 构建过滤器query
    elasticsearch java 索引操作
    lesson4:利用jmeter来压测数据库
    lesson3:使用java代码的方式对不能识别的协议进行压力测试
    lession2:使用HTTP Cookie 管理器来传递cookies值
    lesson1:压测普通网页
    php mysql find_in_set函数 检索单子段 逗号分隔序列
    写出一种排序算法(要写出代码),并说出优化它的方法。(新浪面试题)
  • 原文地址:https://www.cnblogs.com/huaxili/p/5407559.html
Copyright © 2020-2023  润新知