这篇文章主要介绍了 JavaScript 变量的作用域的基本知识, 是 JavaScript 入门学习中的基础知识, 需要的朋友可以参考下
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
变量作用域是程序中定义这个变量的区域。
先来看一段示例:
/* 代码 1 */
- var scope = "global ";
- function checkScope() {
- var scope = "local ";
- function childCheck() {
- var scope = "childLocal ";
- document.write(scope);
- }
- function childUndefined() {
- document.write(scope);
- var scope;
- }
- function childOverride() {
- scope = "childOverride ";
- document.write(scope);
- }
- document.write(scope); //输出"local"
- childCheck(); //输出"childLocal"
- childUndefined(); //输出"undefined"
- childOverride(); //输出"childOverride"
- document.write(scope); //输出"childOverride"
- }
- checkScope(); //输出"local childLocal undefinedchildOverride childOverride"
- document.write(scope); //输出"global "
全局作用域与局部作用域
全局(global)变量的作用域是全局的,在 Javascript 中处处有定义;而函数内部声明的变量是局部(local)变量,其作用域是局部性的,只在函数体内部有定义。对于下面的输出读者应不会感到意外。
/* 代码 2 */
- var scope = "global";
- function checkScope() {
- var scope = "local";
- document.write(scope);
- }
- checkScope(); //输出"local"
- document.write(scope); //输出"global"
全局变量作用域中使用变量可以不用 var 语句,但在声明局部变量是一定要使用 var 语句,否则会视为对全局变量的引用。看下面代码:
/* 代码 3 */
- var scope = "global";
- function checkScope() {
- scope = "local";
- document.write(scope);
- }
- checkScope(); //输出"local"
- document.write(scope); //输出"local"
没有块作用域
Javascript 没有块级作用域,函数中声明的变量在整个函数中都是有定义的。对于下面的代码对于生疏的读者可能颇感意外:
/* 代码 4 */
- var scope = "global";
- function checkScope() {
- document.write(scope); //语句4.1
- var scope = "local"; //语句4.2
- document.write(scope);
- }
- checkScope(); //输出"undefinedlocal"
由于语句 4.1(var scope = "local";)声明的变量在整个 checkScope 函数作用域内都有效,因此在语句 4.2(document.write(scope); )执行的时 scope 引用的是局部变量,而此时局部变量 scope 尚未定义,所以输出 "undefined"。因此一个好的编程习惯是将所有的变量声明集中起来放在函数的开头。
在了解了上述内容之后,读者再看看代码 1 应该不会感到困惑了。
对象的属性变量
对象的属性变量比较容易理解,看一下下面的代码读者应该不会感到疑惑。
/* 代码 5 */
- var scope = "global ";
- var obj = new Object();
- obj.scope = "object ";
- obj.checkScope = function () {
- var scope = "loacl ";
- document.write(scope); //输出"loacl"
- document.write(this.scope); //输出"object"
- document.write(window.scope); //输出"global"
- }
- obj.checkScope(); //输出"loacl object global"
所谓作用域,就是说这个变量在代码块中的有效范围。如果不理解 JavaScript 作用域,调试代码的时候可能会比较困难。
在函数中,如果用 var 来声明一个变量,那么该变量的作用域就只限于该函数内部,函数外的代码无法访问该变量。如果在该函数中再声明一个函数,那么这个内部的函数也可以访问这个变量。
反过来,如果声明变量的时候没有用 var,那么此变量的作用域就不局限于这个函数了。JavaScript 引擎会再全局范围中检查该变量是否被定义过。如果该变量没有被定义过,那么它就会被定义为一个全局变量。
函数可以访问相同作用域中的变量:
- var foo = 'hello';
- var sayHello = function() {
- console.log(foo);
- };
- sayHello(); // logs 'hello'
- console.log(foo); // also logs 'hello'
变量作用域之外的代码不能访问该变量:
- var sayHello = function() {
- var foo = 'hello';
- console.log(foo);
- };
- sayHello(); // logs 'hello'
- console.log(foo); // doesn't log anything
不用作用域中名称相同的变量,有不同的值:
- var foo = 'world';
- var sayHello = function() {
- var foo = 'hello';
- console.log(foo);
- };
- sayHello(); // logs 'hello'
- console.log(foo); // logs 'world'
函数定以后可以看到函数内变量值的改变:
- var myFunction = function() {
- var foo = 'hello';
- var myFn = function() {
- console.log(foo);
- };
- foo = 'world';
- return myFn;
- };
- var f = myFunction();
- f(); // logs 'world' -- haha
作用域也会穿越 — 闭包
- // 一个自执行的匿名函数
- (function() {
- var baz = 1;
- var bim = function() {
- alert(baz);
- };
- bar = function() {
- alert(baz);
- };
- })();
- console.log(baz); // 在函数外面不能访问 baz
- bar(); // 声明 bar 的时候并没有用 var
- // 所以 bar 是一个全局变量; 但是,
- // bar 和 baz 在相同的作用域内被定义,
- // 所以 bar 可以访问 baz
- // 其实 bar 是个闭包函数
- bim(); // bim 的作用域只限于匿名函数内部,
- // 所以这里不能调用
综合
所谓作用域,就是说这个变量在代码块中的有效范围。如果不理解 JavaScript 作用域,调试代码的时候可能会比较困难。
在函数中,如果用 var 来声明一个变量,那么该变量的作用域就只限于该函数内部,函数外的代码无法访问该变量。如果在该函数中再声明一个函数,那么这个内部的函数也可以访问这个变量。
反过来,如果声明变量的时候没有用 var,那么此变量的作用域就不局限于这个函数了。JavaScript 引擎会再全局范围中检查该变量是否被定义过。如果该变量没有被定义过,那么它就会被定义为一个全局变量。
函数可以访问相同作用域中的变量:
- var foo = 'hello';
- var sayHello = function() {
- console.log(foo);
- };
- sayHello(); // logs 'hello'
- console.log(foo); // also logs 'hello'
变量作用域之外的代码不能访问该变量:
- var sayHello = function() {
- var foo = 'hello';
- console.log(foo);
- };
- sayHello(); // logs 'hello'
- console.log(foo); // doesn't log anything
不用作用域中名称相同的变量,有不同的值:
- var foo = 'world';
- var sayHello = function() {
- var foo = 'hello';
- console.log(foo);
- };
- sayHello(); // logs 'hello'
- console.log(foo); // logs 'world'
函数定以后可以看到函数内变量值的改变:
- var myFunction = function() {
- var foo = 'hello';
- var myFn = function() {
- console.log(foo);
- };
- foo = 'world';
- return myFn;
- };
- var f = myFunction();
- f(); // logs 'world' -- haha
作用域也会穿越 — 闭包
- // 一个自执行的匿名函数
- (function() {
- var baz = 1;
- var bim = function() {
- alert(baz);
- };
- bar = function() {
- alert(baz);
- };
- })();
- console.log(baz); // 在函数外面不能访问 baz
- bar(); // 声明 bar 的时候并没有用 var
- // 所以 bar 是一个全局变量; 但是,
- // bar 和 baz 在相同的作用域内被定义,
- // 所以 bar 可以访问 baz
- // 其实 bar 是个闭包函数
- bim(); // bim 的作用域只限于匿名函数内部,
- // 所以这里不能调用
来源: