zoukankan      html  css  js  c++  java
  • js的this作用域

    作者:zccst

    this作用域以前专门学习研究过,但发现依然不够全面和完整。现在继续学习

    先列出之前看过的结论:

    函数在被调用的时候会意外接受两个参数:this和argument,其中this的值跟取决于函数的调用模式
    1,方法调用模式 o.a() //this指的o
    2,函数调用模式 a() //this指的windows
    3,构造器调用模式 new a() //this为a的实例对象
    4,apply(call)的间接调用模式 a.apply(xx,[yy]) //this指的xx

    但是,上面的描述并没有指出背后的联系,换一种描述方式:

    在这里列出this在ECMAScript中的不同含义:

    (1) 在全局执行环境中使用this,表示Global对象,在浏览器中就是window对象。

    (2) 当在函数执行环境中使用this时,情况就有些复杂了。如果函数没有明显的作为非window对象的属性,而只是定义了函数,不管这个函数是不是定义在另一个函数中,这个函数中的this仍然表示window对象。如果函数显示地作为一个非window对象的属性,那么函数中的this就代表这个对象。(当然可以使用apply或者call函数来取代默认this的引用,详见[P88])

    (3) 当通过new运算符来调用函数时,函数被当做一个构造函数,this指向构造函数创建出来的对象。 
    参考: 
    《JavaScript基础与案例开发详解》清华大学出版社

    场景一,一个函数的this与内部函数的this是否相等

    var a = 1;
    function f1(){
        this.a = 2;
        console.log(this.a+a);// 4
        function f2(){
            this.a = 3;
            console.log(this.a+a); // 6 如果注释掉this.a=3,则是4
        }
        f2();
    }
    f1();

    根据新的描述,虽然嵌套定义,但只是定义了函数,所以this作用域仍是window。经测试,三层嵌套后,this也指向window。

    很早就看过this的四种总结,但实际应用中还是远远不够,各种情况下还需要继续深入理解。

    在 JavaScript 中,上下文对象就是 this 指针,即被调用函数所处的环境。上下文对象的作用是在一个函数内部引用调用它的对象本身。
    在 JavaScript 中,本质上,函数类型的变量是指向这个函数实体的一个引用,在引用之间赋值不会对对象产生复制行为。我们可以通过函数的任何一个引用调用这个函数,不同之 处仅仅在于上下文。
    仔细观察上面的例子,使用不同的引用来调用同一个函数时,this 指针永远是这个引用所属的对象

    var scope = 'top';
    var f1 = function() { 
        console.log(scope);
    };
    f1(); // 输出 top
    var f2 = function() { 
        var scope = 'f2'; 
        f1(); // 输出 top
    };
    f2();

    函数作用域的嵌套关系是定义时决定的,而不是调用时决定的,也就是说,JavaScript 的作用域是静态作用域,又叫词法作用域,这是因为作用域的嵌套关系可以在语法分析时确定,而不必等到运行时确定

    场景二,定义一个函数,在不同的作用域中调用时this指代不同

    当this使用在函数代码中事情就变得有趣多了。这种情况是最难的也会引发很多的问题。在函数代码中,this值的第一(可能也是最重要的)特性就是不能 静态的绑定到一个函数上。正如上面已经提到的,this值在进入上下文时就已经被决定了,在函数代码的情形下,每次this值可以是完全不一样的。

    然而,在代码运行时,this值是不可改变的。例如,不能给this赋一个新值,因为this不是变量(相反,python编程语言中,可以显式的定义self对象,在运行的时候self对象可重复改变)

    var foo={x:10};
    var bar={
        x:20,
        test:function(){
            console.log(this===bar);//true
            console.log(this.x);//20
            //this=foo;//error,不能改变this值
        }
    };
    //当进入上下文时,this值由"bar"对象决定的。为什么这样-将在下面详细讨论
    bar.test();//true,20
    foo.test=bar.test;
    //然而,此时在这里的this将指向"foo"-即使我们调用同一个函数
    foo.test();//false,10
    

    (当我们在一些关于javascript 的文章和书本中会看到“this值由函数如何定义来决定:如果是全局函数,this值被设置为全局对象,如果函数时一个对象的方法,this值设置为这个 对象”-这是一个错误的描述)。从下面我们可以看出即使是一般的全局函数,也能够被产生不同this值的调用表达式所触发。

    function foo(){
        console.log(this);
    }
    foo();//打印this为Window
    console.log(foo===foo.prototype.constructor);//true
    //但是对于同一函数的另一种调用表达式形式,this值是不同的
    foo.prototype.constructor();//打印this为foo

    调用一个被定义为对象方法的函数,但是this值不会被设置为这个对象也是同样可能的:

    var foo={
        bar:function(){
            console.log(this);
            console.log(this===foo);
        }
    };
    foo.bar();//foo,true
    var exampleFunc=foo.bar;
    console.log(exampleFunc===foo.bar);//true
    //同一函数的另一种调用表达式形式,得到不同的this值
    exampleFunc();//global,false
    

      

  • 相关阅读:
    【转】ASP.NET页面刷新方法总结
    GridView点击超链接时弹出小窗口
    VS2008增加AJAX Control Toolkit3.5支持(组图)
    水晶报表中"已达到系统管理员配置的最大报表处理作业数限制"错误的处理
    asp.net 在使用Response.Redirect try{}catch{}块失效
    【转】ASP.NET的五大数据控件浅谈
    ASP.NET生成随机密码
    ASP.NET Web应用程序和ASP.NET网站的区别
    使用ArcGIS GP服务之一框架介绍
    mysql索引的类型和优缺点
  • 原文地址:https://www.cnblogs.com/zccst/p/3713112.html
Copyright © 2011-2022 走看看