javascript中变量的范围是什么?它们在函数内部的作用域与在函数外部的作用域相同吗?或者这有关系吗?此外,如果变量是全局定义的,那么变量存储在哪里?
当前回答
据我理解,关键是Javascript具有函数级作用域,而不是更常见的C块作用域。
这是一篇关于这个主题的好文章。
其他回答
试试这个奇怪的例子。在下面的示例中,如果a是一个初始化为0的数字,您将看到0,然后是1。除了a是一个对象,javascript将向f1传递a的指针,而不是它的副本。结果是两次都得到相同的警报。
var a = new Date();
function f1(b)
{
b.setDate(b.getDate()+1);
alert(b.getDate());
}
f1(a);
alert(a.getDate());
几乎只有两种类型的JavaScript作用域:
每个var声明的范围都与最直接的封闭函数相关联如果var声明没有封闭函数,则为全局范围
因此,除函数之外的任何块都不会创建新的作用域。这解释了for循环覆盖外部范围变量的原因:
var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5
改用函数:
var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10
在第一个示例中,没有块范围,因此最初声明的变量被覆盖。在第二个示例中,由于函数的原因,出现了一个新的作用域,因此最初声明的变量是SHADOWED,而不是重写。
就JavaScript范围而言,这几乎是您需要了解的全部内容,除了:
try/catch仅为异常变量本身引入新范围,其他变量没有新范围with子句显然是另一个例外,但不鼓励使用with子句(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with)
因此,您可以看到JavaScript作用域实际上非常简单,尽管并不总是直观的。需要注意的几点:
var声明被提到了范围的顶端。这意味着无论var声明发生在哪里,对于编译器来说,就像var本身发生在顶部一样同一范围内的多个var声明组合在一起
因此,此代码:
var i = 1;
function abc() {
i = 2;
var i = 3;
}
console.log(i); // outputs 1
相当于:
var i = 1;
function abc() {
var i; // var declaration moved to the top of the scope
i = 2;
i = 3; // the assignment stays where it is
}
console.log(i);
这似乎与直觉相悖,但从命令式语言设计者的角度来看,这是有道理的。
1) 有一个全局作用域、一个函数作用域以及with和catch作用域。一般来说,变量的作用域没有“块”级别的作用域——with和catch语句为其块添加名称。
2) 作用域一直由函数嵌套到全局作用域。
3) 通过原型链解决财产问题。with语句将对象属性名称带入with块定义的词法范围。
编辑:ECMAAScript 6(Harmony)被指定为支持let,我知道chrome允许一个“和谐”标志,所以也许它确实支持它。。
这将是对块级范围的支持,但必须使用关键字才能实现。
编辑:根据本杰明在评论中指出的with和catch语句,我编辑了帖子,并添加了更多内容。with和catch语句都将变量引入到各自的块中,这是一个块范围。这些变量是传递给它们的对象的财产的别名。
//chrome (v8)
var a = { 'test1':'test1val' }
test1 // error not defined
with (a) { var test1 = 'replaced' }
test1 // undefined
a // a.test1 = 'replaced'
编辑:澄清示例:
test1的作用域为with块,但别名为a.test1Vartest1'在上层词法上下文(函数或全局)中创建一个新的变量test1,除非它是一个属性——它就是这样。
诶呀小心使用'with'——就像var是noop一样,如果变量已经在函数中定义,那么它也是从对象导入的名称的noop!对已经定义的名称稍加注意会使其更加安全。因此,我个人永远不会使用。
运行代码。希望这能提供一个关于范围界定的想法
Name = 'global data';
document.Name = 'current document data';
(function(window,document){
var Name = 'local data';
var myObj = {
Name: 'object data',
f: function(){
alert(this.Name);
}
};
myObj.newFun = function(){
alert(this.Name);
}
function testFun(){
alert("Window Scope : " + window.Name +
"\nLocal Scope : " + Name +
"\nObject Scope : " + this.Name +
"\nCurrent document Scope : " + document.Name
);
}
testFun.call(myObj);
})(window,document);
在“Javascript 1.7”(Mozilla对Javascript的扩展)中,还可以使用let语句声明块范围变量:
var a = 4;
let (a = 3) {
alert(a); // 3
}
alert(a); // 4
推荐文章
- Javascript和regex:分割字符串并保留分隔符
- 如何检查DST(日光节约时间)是否有效,如果是,偏移量?
- 如何打破_。在underscore.js中的每个函数
- 如何在jQuery中获得当前日期?
- 如何创建一个日期对象从字符串在javascript
- 输入触发器按钮单击
- 获取对象的属性名
- 如何检查用户是否可以回到浏览器历史
- 相当于字符串。jQuery格式
- 如何在vue-cli项目中更改端口号
- Angular 2模板中的标签是什么意思?
- JavaScript .includes()方法的多个条件
- 窗口。亲近与自我。close不关闭Chrome中的窗口
- 同步和异步编程(在node.js中)的区别是什么?
- 在d3.js中调整窗口大小时调整svg的大小