每个函数在定义被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(); }

           //通常用法:将上下文this缓存到一个变量中

           //以便在本函数作用域内包含另一个函数作用域的情况下可以继续使用此上下文对象this

           //如果省略var self=this; 这行,那么在嵌套函数作用域内就无法访问到本函数作用域的成员了。        


}

}

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方法中调用就可以了。

js中var self=this的解释的更多相关文章

  1. js中var的有或无--重复声明和以后的声明

    js中var的有或无--重复声明和以后的声明 使用var语句多次声明一个变量不仅是合法的,而且也不会造成任何错误. 如果重复使用的一个声明有一个初始值,那么它担当的不过是一个赋值语句的角色. 如果重复 ...

  2. 浅谈JS中 var let const 变量声明

    浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...

  3. 【前端开发】】js中var写和不写的区别

    js中var用与不用的区别 Javascript声明变量的时候,虽然用var关键字声明和不用关键字声明,很多时候运行并没有问题,但是这两种方式还是有区别的.可以正常运行的代码并不代表是合适的代码. v ...

  4. js中var,let,const理解

    var变量提升: 解释:在声明a之前输出a,因为a是使用var声明变量得到提升,解释为下句 var a: console.log(a) a = 1; var声明会提到最上面的位置,但是赋值的位置还是当 ...

  5. js中,var 修饰变量名和不修饰的区别

    js中 允许在定义变量的时候 不加var 修饰符.js会在当前作用域下寻找上下文是否定义了此变量, 如果没有找到则会为这个变量分配内存.当且将其视为window的成员. 也就是全局变量. 如果加了va ...

  6. js中var 笔记

    js中声明变量会用到Var; 1,var a;声明一个变量a,此时输出a,会显示undefined:因为此时的a未定义: 2, var a=0;和b=0;有什么区别呢? 当声明一个全局变量时,实际是定 ...

  7. js 中var that=this

    js中经常出现var that=this,为什么这么做? http://stackoverflow.com/questions/4886632/what-does-var-that-this-mean ...

  8. JS中var声明与function声明两种函数声明方式的区别

    JS中常见的两种函数声明(statement)方式有这两种: // 函数表达式(function expression) var h = function() { // h } // 函数声明(fun ...

  9. js中var

    js中声明一个变量的时候,建议要加上var.如果不加,除非你知道自己在干什么,否则哪天会吃亏哈哈. 不加var,js会认为你声明的是全局变量. 举个小例子. function test1(){ a = ...

随机推荐

  1. mount不是很熟悉 转载文章了解下 转自http://forum.ubuntu.org.cn/viewtopic.php?f=120&t=257333

    纯粹针对刚刚解封开包的新新手,老鸟们请自觉绕行,否则浪费你的时间你非要逼我做谋杀犯可不光我的事你还没地方说理去.如果你正好是个崭新的新手,就耐心的花点时间看看吧,至少大概看看,不要在一个陌生又黑暗的到 ...

  2. ThinkPHP 关于namespace的事儿

    如题,php通常是不允许函数重名的,例如a.php中有一个getName(),b.php中有一个getName(),在require_once a.php和b.php后就会报getName重复定义的错 ...

  3. win10 下runtime error 解决办法

    下载http://120.52.73.50/download.microsoft.com/download/5/2/1/5212066c-5f48-4b16-a059-ed84b505a65d/vcr ...

  4. OpenGL学习笔记1——第一个程序

    学习的参考书基本是按照GL编程指南,如果有消息机制概念,对于GLUT的理解是很自然的.下面就按照自己写的第一个程序详细解释一下GL,还是比较容易上手的. 程序实现的功能是,根据当前随即种子摇出来的结果 ...

  5. 如何用Visual Studio 2013 (vs2013)编写C语言程序 (转)

    http://blog.sina.com.cn/s/blog_964ee6730101jvvi.html

  6. SqlServer实现先将所有数据排好序再进行分页

    平时,我们对数据进行分页,然后将分页后的数据再进行排序输出.这样做只是针对每次请求,也就是前TOP个数据进行了排序,并不是将数据库中的所有的数据进行了排序.当我们需要将数据库中的所有数据排序后在进行分 ...

  7. 500lines项目简介

    "500行或更少" "What I cannot create, I do not understand." -- Richard Feynman <50 ...

  8. oracle批量修改多个表的数据

    方法一 写PL/SQL,开cursor declare  l_varID varchar2(20);  l_varSubName varchar2(30);  cursor mycur is sele ...

  9. CodeSmith7代码生成器针对PostgreSQL数据库无法使用的Bug修复全过程

    前言 最近公司需要将原来使用的MSSQL数据库整体迁移至pgsql,需要使用CodeSmith生成IBatisNet的配置文件.按照提示安装了Npgsql.dll后依然无法使用.引发了本次通过反编译修 ...

  10. Objective C ARC 使用及原理

    手把手教你ARC ,里面介绍了ARC的一些特性, 还有将非ARC工程转换成ARC工程的方法 ARC 苹果官方文档 下面用我自己的话介绍一下ARC,并将看文档过程中的疑问和答案写下来.下面有些是翻译,但 ...