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

    js-this作用域


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

    然而,在代码运行时,this值是不可改变的。例如,不能给this赋一个新值,因为this不是变量(相反,python编程语言中,可以显式的定义self对象,在运行的时候self对象可重复改变)
    Js代码  收藏代码
    1. var foo={x:10};  
    2. var bar={  
    3.     x:20,  
    4.     test:function(){  
    5.         console.log(this===bar);//true  
    6.         console.log(this.x);//20  
    7.         //this=foo;//error,不能改变this值  
    8.     }  
    9. };  
    10. //当进入上下文时,this值由"bar"对象决定的。为什么这样-将在下面详细讨论  
    11. bar.test();//true,20  
    12. foo.test=bar.test;  
    13. //然而,此时在这里的this将指向"foo"-即使我们调用同一个函数  
    14. foo.test();//false,10  


    (当我们在一些关于javascript 的文章和书本中会看到“this值由函数如何定义来决定:如果是全局函数,this值被设置为全局对象,如果函数时一个对象的方法,this值设置为这个 对象”-这是一个错误的描述)。从下面我们可以看出即使是一般的全局函数,也能够被产生不同this值的调用表达式所触发。
    Js代码  收藏代码
    1. function foo(){  
    2.     console.log(this);  
    3. }  
    4. foo();//打印this为Window  
    5. console.log(foo===foo.prototype.constructor);//true  
    6. //但是对于同一函数的另一种调用表达式形式,this值是不同的  
    7. foo.prototype.constructor();//打印this为foo  
    8. 调用一个被定义为对象方法的函数,但是this值不会被设置为这个对象也是同样可能的:  
    9.   
    10. var foo={  
    11.     bar:function(){  
    12.         console.log(this);  
    13.         console.log(this===foo);  
    14.     }  
    15. };  
    16. foo.bar();//foo,true  
    17. var exampleFunc=foo.bar;  
    18. console.log(exampleFunc===foo.bar);//true  
    19. //同一函数的另一种调用表达式形式,得到不同的this值  
    20. exampleFunc();//global,false  






    2013-09-10
    最近看到一句话说,js中的对象其实就是一些hash映射。简单说就是名值对,只不过这些名字对同用一个上下文(context)this。
    Js代码  收藏代码
    1. var obj = {  
    2.     fun1 : function(){  
    3.     },  
    4.     fun2 : function(){  
    5.         //在使用fun1时,像使用自己的变量一样  
    6.         var local = this.fun1();//如果有参数,还可以传递参数  
    7.     },  
    8.     fun3 : function(){  
    9.     },  
    10. };  






    2013-8-27
    this关键字

    每一个方法或函数都会有一个this对象,this对象是方法(或函数)在执行时的那个环境,也可以说是这个函数在那个作用域下运行的。
    说的更通俗一点:this就相当于咱们平时说话时候说的“我”,“我家”的概念。就是说当一个方法在运行的时候,它是属于谁的。它在运行的时候它的家是谁家。
    this的概念比较抽象,是讲课的时候的难点也是重点。
    关于this的具体表示那个对象,和函数的运行方式(或调用方式)有关。

    在JavaScript中一共有四种调用模式:
    方法调用模式(对象属性模式)、
    函数调用模式(就是普通的函数执行)、
    构造调用模式(应该叫实例上的方法模式更好)
    和apply调用模式。


    一、当它为一个对象上的方法的时候,this是当前这个对象
    方法调用模式(或称:对象属性模式)
    先了解一个概念:方法和函数的区别。方法和函数本质一样,形式不同而已。看下例:
    Js代码  收藏代码
    1. function fn(){  
    2.     alert(this)  
    3. }  

    这样就是定义了一个函数,当:fn()的时候,叫这个函数运行。同样是上面这个fn函数,如果把它赋值给一个对象的属性,就成了方法了,看下面的例子。
    Js代码  收藏代码
    1. var obj=new Object();//先定义一个对象obj  
    2. obj.objFn=fn;  

    那现在的obj.objFn就是方法了,但其实objFn和fn指向的是同一个内存地址。但fn是直接定义的,就是函数,而objFn是obj这个对象上的一个属性,则objFn就是方法了。方法和函数本质上是一样的,只是在不同的情况下的叫法不同。
    但当fn运行的时候,弹出的是window(任何函数被调用,this都表示window);而objFn运行的时候,弹出的是object,因 为当它做为一个方法运行的时候,this关键字表示的是objFn这个属性所属的这个对象obj。也就是说,在这种情况下,this表示obj。
    再啰嗦一遍:当函数成为一个对象的属性的值的时候,这个函数里的this指向当前这个对象(这时候函数就变成了方法)
        再啰嗦第三遍:当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象。方法可以使用this去访问对 象,所以它能从对象中取值或修改对象。this到对象的绑定发生在调用的时候。这个“超级”迟绑定使得函数可以对this高度复用。通过this可取得它 们所属对象的上下文的方法称为公共方法。


    二、函数调用模式
    当函数并非一个对象的属性时,那么它被当做一个函数来调用。此模式下this绑定到全局对象。通过在对象内将this赋值给that,可以使函数模式下调用that来访问指定对象。
    (就是上面解释的函数方式)


    三、类的实例上的方法中的this指向当前的实例
    例如:
    Js代码  收藏代码
    1. function Person(){  
    2.    
    3. }  
    4. Person.prototype.cry=function (){alert(this)}  
    5. var rose=new Person();  
    6. rose.cry();//现在这个cry就被称做方法,这个方法里的this就表示rose这个实例。  

    详细的讲解,请见《面向对象和设计模式》的课堂讲解和视频


    四、使用call和apply方法强制改变this关键字
    (附在面向对象一章的讲解里)
    测试题:
    题目一:
    Js代码  收藏代码
    1. var name = "The Window";  
    2.   var object = {  
    3.     name : "My Object",  
    4.     getNameFunc : function(){  
    5.       return function(){  
    6.         return this.name;  
    7.      };  
    8.     }  
    9. };  
    10. alert(object.getNameFunc()()); //The Window  

    解析:object.getNameFunc后面跟了两对括号。先运行object.getNameFunc(),这个方法运行后返回了一个函数,就是这个方法里面定义的那个匿名函数,然后再让这个匿名函数运行。
    可以分解成以下步骤:
    Js代码  收藏代码
    1. var fn= object.getNameFunc();//object.getNameFunc这个方法里的this是表示object这个对象,但它返回的是一个函数,返回的这个函数里的这个this则表示window了  
    2. fn();//当返回的这个函数运行的时候,this表示是window这个对象  


    和上一题目类似的题:
    Js代码  收藏代码
    1. function a(){  
    2. alert(this);  
    3. }  
    4. var arr = [1,2,3];  
    5. arr.f = a;  
    6. arr.f();//会输出什么  

    解析:把a函数赋给arr的属性f,则f就成为arr这个对象上的方法了,它运行的时候就表示arr这个数组对象。
    如果直接这样:a();  则这时候的this表示的是window这个对象
  • 相关阅读:
    vue项目搭建
    js监听input输入框值的实时变化实例
    nodejs-Child Process模块
    nodejs-Express框架
    前端的存储技术cookie、sessionStorage、localStorage
    node.js之path
    css两列自适应布局的多种实现方式及原理。
    React jQuery公用组件开发模式及实现
    js创建对象的几种方式
    IE9 不F12打开控制台,代码不执行。打开后正常
  • 原文地址:https://www.cnblogs.com/shsgl/p/4289870.html
Copyright © 2011-2022 走看看