JavaScript中var关键字的作用域与this指向详解
本文详细解析JavaScript中var关键字的作用域规则,区分全局与函数级作用域,并探讨this在不同执行上下文(普通函数调用与new实例化)中的指向差异。通过代码示例说明全局变量作为window属性的特性,以及如何在对象方法中正确访问全局或实例变量。
var关键字作用域示例分析
通过观察以下示例的运行结果,可以直观地发现问题所在:
上述三个示例的执行结果分别如下:
代码如下:
Results#region Results
No.1
0
undefined
No.2
0
1
No.3
0
undefined
#endregion函数级作用域与全局变量访问
由此可见,JavaScript中的变量确实存在作用域的概念,尽管其划分较为粗略,主要仅分为全局变量和函数级变量。在第二个示例中输出0和1,是因为所有变量均被声明为全局变量,且该语句块内仅定义了两个变量。而在第一个和第三个示例中,函数外部的全局变量是否使用var声明似乎影响不大。然而,在函数内部,var关键字的作用至关重要:它明确标识了变量为局部变量。因此,在初始化var01之前尝试输出该变量,结果自然为'undefined'。
那么,函数内部是否完全屏蔽了外部的全局var01呢?在C/C++中可以使用::来访问全局变量,JavaScript是否支持类似机制?关键在于理解全局变量的本质:全局变量实际上是动态添加到Window对象实例window上的属性。因此,只要在函数内部使用document.write(window.var01);即可获取其值1。同时,在该执行上下文中,function内部的this关键字也指向window实例,因此也可以将引用写作this.var01。
变量命名规范补充
顺便提及,在重读JScript教程时注意到,教程指出变量名必须符合[a-zA-Z_]+[a-zA-Z0-9_]*格式。然而,'$'符号实际上也可以作为变量名的字符,甚至允许出现在开头,例如$1234是合法的变量名,甚至连$$$也是合法的变量名,这确实有些令人意外。
变量声明与执行顺序疑问
我好奇的是,当调用一个函数时,程序执行顺序是否会先检查函数内部变量中是否存在关键字var,然后根据检查结果为不同的变量分配不同的作用域和值?因为我观察到在这三个函数中,var01变量的输出语句均位于其定义语句之后。
全局变量操作与this指向机制
代码如下:
function get_global_var(___name)
{
return eval(___name);
}
function set_global_var(___name,___value)
{
eval(___name+"=___value");
}
var aa=11;
Test();
WScript.Echo(aa);//22
function Test()
{
var aa=33;
WScript.Echo(get_global_var("aa"));//11
set_global_var("aa",22);
WScript.Echo(get_global_var("aa"));//22
WScript.Echo(aa);//33
}构造函数与实例中的this行为
在上面的示例中,this关键字从未指向Test函数本身,而一直指向WScript的实例。
如果我们编写语句:var test = new Test(); 此时Test函数内部的this将指向Test的一个实例。若该实例需要使用全局变量,Lostinet提供了一种方法。
不过,更简单的方式是将global对象传入构造函数,这样定义Test:
代码如下:
function Test(global)
{
// ...
}然后这样创建实例:var test = new Test(this); 就可以在Test实例中使用global对象的属性和方法了。
new运算符对this的影响
这是否意味着,在new创建的实例中,this指向该实例,而在其他情况下都指向WScript?如果更换脚本引擎,情况是否会不同?这是否是标准行为?
new constructor[(arguments)];
new运算符执行以下任务:
·创建一个没有成员的对象。
·为那个对象调用构造函数,传递一个指针给新创建的对象作为 this 指针。
·然后构造函数根据传递给它的参数初始化该对象。
需要注意的是,即使当前作用域内没有调用new,但在其父作用域中可能调用了new。因此,关于“在new的实例中,this就指实例,否则都指WScript”的说法,前半句是正确的,而后半句并不一定成立。
JavaScript异步发送HTTP请求时怎么优雅地处理错误
2026-11-05 17:10:44
5款主流JS在线运行工具对比:CodePen、JSFiddle与StackBlitz怎么选
2026-11-05 17:04:04
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
JavaScript 原生 Date 对象怎么实现日期加减
2026-11-05 14:30:00
