zoukankan      html  css  js  c++  java
  • 关于困惑已久的var self=this的解释

    首先说下this这个对象的由来(属于个人理解):
    每个函数在定义被ECMAScript解析器解析时,都会创建两个特殊的变量:this和arguments,换句话说,每个函数都有属于自己的this对象,这个this对象是在运行时基于函数的执行环境绑定的,即在全局对象中,this指向的是window对象;在自定义函数中,this对象指向的是调用这个函数的对象,
    也就是说,this指向的是调用执行环境的那个对象。
    如果是在函数嵌套环境中,this指代的是调用外部函数或者内部函数的执行环境的对象;

    (注意:可以通过使用call()或者apply()改变函数执行环境的情况下,this就会指向其他对象。)

    哎。。以上的描述还是有点啰嗦,那么就看例子吧:
     /*----- 2014-2-10 这个例子是错误的 -----*/
    function BaseType(name,age){
        //用一个变量保存当前函数执行环境中的this对象
        //这里可能会有疑问:为什么非得把this保存起来呢?这是因为,内部函数(比如本函数里面包含的两个匿名函数)
        //在搜索this变量时,只会搜索到属于它自己的this,而不会搜索到包含它的那个函数的this。
        //所以,为了在内部函数能使用外部函数的this对象,要给它赋值了一个名叫self的变量。
        var self=this;
        this.name=name;
        this.age=age;
        this.sayHello=function(){
            console.log("My name is "+this.name+", and i'm "+this.age+"years old.");
        }
        this.saySomething=function(){
               //此处用法有点欠妥,完全可以不用self,而用this
               //self.sayHello();
               //正确的做法是:
               return function () { self.sayHello(); }
               //详见:http://skybirdzw.blog.163.com/blog/static/72570626201411032516719/ 

        }
    }
    var b1=new BaseType("wede",30);
    b1.saySomething(); //My name is wede, and i'm 30years old.

    从结果来看,是预期的结果。
    那么这里可能又会出现新的疑问:为什么在saySomething()方法中非要用self.sayHello()来调用呢,
    直接sayHello()多好?
    其实这又涉及到另一个话题:实例成员与局部成员。
    我们创建构造函数的意义就是要用它来创建实例,那么所有属于实例的成员都需要用this来定义;
    而只有那些不属于实例的成员才不会用this定义;
    当然,用this定义了方法以后,在函数作用域内部要调用此方法时,就需要加上this了。

    为了证明这一点,来看下面的代码:
    function BaseType(name,age){
        var self=this;
        this.name=name;
        this.age=age;
        this.sayHello=function (){
            console.log("My name is "+this.name+", and i'm "+this.age+"years old.");
        }
        this.saySomething=function(){
            sayHello();
        }
    }
    var b1=new BaseType("wede",30);
    b1.saySomething(); //ReferenceError: sayHello is not defined
    结果显示:sayHello方法未定义。
    就是说明,我们调用的其实是局部方法sayHello,而现在只有实例方法sayHello,所以会出现异常。

    下面来改装下(注意加粗的部分):
    function BaseType(name,age){
        var self=this;
        this.name=name;
        this.age=age;
        var sayHello=function (){
            console.log("My name is "+name+", and i'm "+age+"years old.");
        }

        this.saySomething=function(){
            sayHello();
        }
    }
    var b1=new BaseType("wede",30);
    b1.saySomething();//My name is wede, and i'm 30years old.

    可以看出,输出了预期的结果。
    而这时候,我们把sayHello方法变成了一个局部方法(对于实例不可见),然后再在saySomething方法中调用就可以了。

  • 相关阅读:
    光脚丫学LINQ(036):一对一映射关系
    光脚丫学LINQ(033):建立映射关系的两个实体类必须分别包含一个主键列成员
    ASP.NET4的网页指令
    光脚丫学LINQ(032):探究AssociationAttribute.Storage
    [代码]服务器端的隐藏重定向
    maven项目bulid失败_No compiler is provided in this environment.
    [SC] OpenSCManager 失败 5:拒绝访问
    c3p0连接池:com.mysql.cj.exceptions.InvalidConnectionAttributeException
    iframe高度自适应
    彻底卸载mysql数据库~
  • 原文地址:https://www.cnblogs.com/zhaow/p/9754592.html
Copyright © 2011-2022 走看看