Nodejs中var与this定义变量的区别以及疑惑
Nodejs中var与this定义变量的区别以及疑惑
我们知道: var可以定义一个局部变量,当然如果var定义在最外层的话,就是全局的局部变量,也就算是全局变量了。 而this关键字定义的变量准确的说应该算是成员变量。即定义的是调用对象的成员变量。 另外在“类(构造函数)”中,我们通常也会用var定义私有属性,而this定义公共属性。 以上这些是大家都知道的,若不知道看了就大概知道的。但我今天遇到了一个疑惑,恳请社区高手指点。是这样的:
//打开浏览器控制台执行一下命令
//定义了一个全局变量
var wahaha = “娃哈哈”;//这里双引号改成英文双引号
//输出“娃哈哈”
console.log(wahaha);
//输出“娃哈哈”,我们知道这里的this指向的是window,即之前的var定义已经把wahaha变量定义成了window的成员变量
console.log(this.wahaha);
上面代码两条控制台日志语句都输出了“娃哈哈”的结果,然而如果这样
//定义一个类
function ClassA(){
//定义一个私有属性
var wahaha = “娃哈哈”;//这里双引号改成英文双引号
//输出“娃哈哈”;
console.log(wahaha);
//输出undefined
console.log(this.wahaha);
}
var a = new ClassA();
这里的输出结果就不同了 ,console.log(wahaha)顺利输出“玩哈哈”,而console.log(this.wahaha);就输出了“undefined”。其实我是觉得这个示例跟之前的那个示例的效果是有矛盾的地方的。我明白很多人利用这个特性实现私有变量跟公共变量的效果,但真的不得不说这是很矛盾的并且令人费解的。
矛盾点在于:第一个例子,var定义的全局变量会很顺利的成为window的成员变量,直接用“变量名”或者“this.变量名”都能得到结果,而第二个例子中,在构造函数中用var定义变量的话,该变量却只能在内部直接通过“变量名”获得而无法通过“this.变量名”的方式获得。
不知道我的问题描述的够不够清楚,这是今天琢磨《javascript精粹》时候想不通的一个问题。恳请高手指点
当然可以!让我们来详细解释一下这个问题,并提供一些示例代码帮助理解。
区别及疑惑解析
1. var
定义的变量
- 全局作用域:如果在全局作用域下使用
var
定义变量,则该变量会成为全局变量,可以通过window.变量名
或直接通过变量名
访问。 - 局部作用域:如果在函数内部使用
var
定义变量,则该变量仅在该函数内部有效,即为局部变量。
2. this
关键字定义的变量
- 成员变量:在类或构造函数内部,
this
关键字用于定义实例的成员变量。这些变量可以在类的方法中访问,也可以通过实例对象访问。
示例代码
示例一:全局变量
// 打开浏览器控制台执行以下代码
var wahaha = "娃哈哈"; // 定义一个全局变量
console.log(wahaha); // 输出 "娃哈哈"
console.log(window.wahaha); // 输出 "娃哈哈"
示例二:构造函数中的变量
function ClassA() {
// 定义一个私有属性
var wahaha = "娃哈哈"; // 局部变量
// 输出 "娃哈哈"
console.log(wahaha); // 输出 "娃哈哈"
// 输出 undefined
console.log(this.wahaha); // 输出 undefined
}
var a = new ClassA();
解释
在构造函数 ClassA
中:
var wahaha = "娃哈哈";
定义了一个局部变量wahaha
,它仅在ClassA
的函数体内部可见。this.wahaha
尝试访问的是ClassA
实例的成员变量,但由于wahaha
是局部变量而不是通过this
定义的,因此this.wahaha
为undefined
。
疑惑点解析
在全局作用域下,var
定义的变量会自动挂载到全局对象 window
上,因此可以直接通过 window.变量名
或者 变量名
访问。
而在构造函数内部,var
定义的变量仅在当前函数作用域内有效,不会被挂载到 this
上,因此 this.变量名
返回 undefined
。
总结
- 在全局作用域中,
var
定义的变量会成为全局变量,可以通过window.变量名
或变量名
访问。 - 在构造函数内部,
var
定义的变量是局部变量,仅在当前函数作用域内有效,不会被挂载到this
上。 - 使用
this
定义的变量会成为类的成员变量,可以通过this.变量名
访问。
希望这个解释能帮助你理解 var
和 this
在 Node.js 中定义变量的区别。
this指的不是ClassA,而是a
var是在当前作用域(scope)中声明一个变量,而this则是指向当前上下文(context)。 作用域很好理解,在函数里面,作用域就是执行var语句的那个函数,否则就是root(window或者global)。 上下文是在函数调用的时候决定的:
foo.bar() // 上下文是foo(this === foo)
foo['bar']() // 上下文是root
foo['bar'].apply(obj) // 上下文是obj
foo['bar'].call(obj) // 上下文是obj
非常感谢您的回复,但请看清楚我的问题
这貌似跟我的疑惑没有关系啊?
记得以前在推上抱怨 JS 循环添加事件太恶心的时候,
人家就安慰我说, JS 的 this
本来就乱指的…
不能说乱指吧,反正规律不好找,我就把我遇到的这个特殊情况背下来得了,理解不了
不会别的,不懂专业术语.不过听说js和别的高级面向对象的好像有些不同.
`var wahaha = ‘爽歪歪’ ; function ClassA(){
//定义一个私有属性 var wahaha = “娃哈哈”;//这里双引号改成英文双引号 this.wahaha = wahaha ;
//输出undefined console.log(wahaha +"\n"+ this.wahaha +"\n"+ ClassA.wahaha ); } ClassA.wahaha = “wahaha” ;
var a = new ClassA(); console.log("\n" + wahaha +"\n"+ this.wahaha +"\n"+ ClassA.wahaha );`
楼主的意思是在window对象里用var声明变量,该变量可以顺利成为window的公开属性,而在自定义的class里确不能,
同疑惑,哈哈,不过javascript作为弱语言,很多特性都跟它的解释器有很大的关系,偶尔出点幺儿子也是很正常的
o(∩_∩)o 哈哈 终于有人明白我的帖子具体是在说什么的了~~ 对的,就是您说的这个疑惑~~我只能暂且把这个情况作为一个特例,记着了……
foo.bar() // 上下文是foo(this === foo)
foo['bar']() // 上下文是root
上面两行代码我经过测试,您说的这个情况不成立啊!不知道您的测试代码是怎样的?着两行的测试结果应该是一样的才对,无论什么情况下。
摘自《深入浅出CoffeeScript》:
回忆一下,下面对CoffeeScript中上下文的规则做了个总结,前面的的规则优先于后面的规则: (1). 当在一个函数调用之前有new关键字,则上下文为新建的对象; (2). 当一个函数使用call或者apply调用时,给定的第一个参数即为上下文; (3). 否则,如果一个函数作为一个对象的属性(obj.func)或者obj[‘func’])来调用时,它就把该对象作为上下文来运行; (4). 如果与上述几条都不符的话,则函数将在全局上下文中运行。
继续来分析你的问题:
这是一个作用域和上下文的问题。在JavaScript中,this
指向当前的上下文,而var
定义的变量值在当前作用域中有效。
JavaScript有两种作用域,全局作用域和局部作用域。局部作用域就是在一个函数里。
var
关键字使用来在当前作用于中创建局部变量的,而在浏览器中的JavaScript全局作用域中使用var
语句时,会把申明的变量挂在window
上,而全局作用域中的this
上下文恰好指向的又是window
,因此在全局作用域中var
申明的变量和window
上挂的变量,即this
可访问的变量有间接的联系,但没有直接联系,更不是一样的。
考虑new
一个函数,根据上面的(1)知道,执行构造函数时,上下文this
为新建的对象(该对象的原型链__proto__
指向了该函数的prototype
,这就是原型继承,顺便提一下,与本问题无关),而作用域确实局部的,与this
完全不同,所以自然没有什么联系,双方的赋值不会互相影响。
形象点说:
作用域就是一个执行过程,这个执行过程在JavaScript中就是一个函数,这个执行过程是如何和外界互相沟通的呢?
1.参数和返回值
2.上一级的作用域
3.this
,即上下文
在作用域中创建的变量,函数执行外就被清除了。
用this定义的是成员变量,用var定义的是局部变量,
function ClassA(){ var wahaha = ‘娃哈哈’; console.log(wahaha); console.log(this.wahaha); console.log(this); }
var a = new ClassA(); ClassA();
试试上面的语句,有助于理解。 1楼回复的对。。
你的疑惑确实有一定的复杂性,主要是因为 JavaScript 中 var
和 this
的使用场景不同导致的结果差异。
示例解析
全局作用域中的 var
在全局作用域中,var
定义的变量会自动成为全局对象(如浏览器中的 window
对象)的属性:
var wahaha = "娃哈哈"; // 变量声明为全局变量
console.log(wahaha); // 输出 "娃哈哈"
console.log(window.wahaha); // 输出 "娃哈哈"
这里 wahaha
是全局变量,可以通过 wahaha
或 window.wahaha
访问。
构造函数中的 var
和 this
在构造函数中,var
定义的变量是局部变量,仅在构造函数的作用域内可见,而 this
关键字指的是当前对象实例。因此,在构造函数内部,this
指向的是当前创建的对象实例:
function ClassA() {
var wahaha = "娃哈哈"; // 局部变量
console.log(wahaha); // 输出 "娃哈哈"
console.log(this.wahaha); // 输出 undefined
}
var a = new ClassA(); // 创建一个新的 ClassA 实例
在这个例子中,wahaha
是构造函数内部的局部变量,无法通过 this
访问。只有通过 this
在构造函数中定义的属性才能在实例中访问到:
function ClassA() {
this.wahaha = "娃哈哈"; // 成员变量
console.log(this.wahaha); // 输出 "娃哈哈"
}
var a = new ClassA();
console.log(a.wahaha); // 输出 "娃哈哈"
总结
var
定义的变量仅在其作用域内有效。this
关键字指的是当前对象实例,用于定义对象的成员变量。- 在构造函数中,
var
定义的变量是局部变量,不能通过this
访问;只有通过this
定义的变量才能在实例中访问。
希望这能帮助你理解两者之间的区别。