Files
notes_estom/JavaScript/ecmascript-5/scope.md
2022-04-18 20:40:34 +08:00

4.6 KiB
Raw Blame History

变量和函数都具有作用域。作用域就是变量和函数的可被访问的范围,控制着变量和函数的可见性和生命周期。

变量的作用域可被分为全局作用域和函数作用域(局部作用域)。如果变量是被定义在全局作用域的话,在 JavaScript 代码中的任何位置都可以访问该变量;如果变量是被定义在指定函数内部的话,在 JavaScript 代码中只能在该函数内访问该变量。

函数的作用域也可被分为全局作用域和函数作用域(局部作用域)。被定义在指定函数内部的函数被称之为局部函数或内部函数。

值得注意的是: ECMAScript 6 之前的 JavaScript 没有语句块作用域。

变量的作用域

全局变量

在所有函数之外声明的变量,叫做全局变量,因为它可被当前文档中的其他代码所访问。具体内容如下述代码所示:

var msg = "this is message";// 定义全局变量 msg

// 在全局作用域访问变量 msg
console.log( msg );// 输出 this is message

function fn(){
	// 在函数作用域访问变量 msg
	console.log( msg );// 输出 this is message
}
fn();

除了上述定义全局变量外,还有一种比较特殊的方式定义全局变量(具体用法如下述代码)。但这种特殊用法并不推荐!

function fun(){
	// 定义变量时没有使用关键字 var
	msg = "this is message";
	// 在函数作用域访问变量 msg
	console.log( msg );// 输出 this is message
}
fun();

// 在全局作用域访问变量 msg
console.log( msg );// 输出 this is message

局部变量

在函数内部声明的变量,叫做局部变量,因为它只能在该函数内部访问。具体用法如下述代码所示:

function fun(){
	// 定义局部变量 msg
	var msg = "this is message";
	// 在函数作用域访问变量 msg
	console.log( msg );// 输出 this is message
}
fun();

// 在全局作用域访问变量 msg
console.log( msg );// 输出报错

声明提前

JavaScript 变量的另一特别之处是,你可以引用稍后声明的变量,而不会引发异常。这一概念称为变量声明提升。

JavaScript 变量感觉上是被“举起”或提升到了所有函数和语句之前。然而提升后的变量将返回 undefined 值所以即使在使用或引用某个变量之后存在声明和初始化操作仍将得到 undefined 值。

全局变量声明提前

console.log( msg );// 不会报错,输出 undefined
var msg = "this is message";// 定义全局变量 msg
console.log( msg );// 输出 this is message

上述代码中的第一行输出不会报错,而是输出 undefined值。效果等同于如下述代码:

var msg;// 定义全局变量 msg但未初始化
console.log( msg );// 不会报错,输出 undefined
msg = "this is message";// 初始化全局变量 msg
console.log( msg );// 输出 this is message

局部变量声明提前

function fn(){
	console.log( msg );// 不会报错,输出 undefined
	var msg = "this is message";// 定义全局变量 msg
	console.log( msg );// 输出 this is message
}
fn();
console.log( msg );// 输出报错

效果等同于如下述代码:

function fn(){
	var msg;// 定义局部变量 msg但未初始化
	console.log( msg );// 不会报错,输出 undefined
	msg = "this is message";// 定义全局变量 msg
	console.log( msg );// 输出 this is message
}

按值传递

按值传递就是指将实参变量的值复制一份副本给函数的形参变量。JavaScript 中为函数传递参数时,都是按值传递的。

如果向函数传递的参数是原始类型数据,则在函数中修改参数变量的值,不会影响外部实参的变量。

var n = 100;// 全局变量n
function fun( n ){// 参数变量也是局部变量
	n -= 3;// 修改的是局部变量n
	console.log( n );// 输出的是局部变量n
}
fun( n );// 按值传递,方法内输出 97
console.log( n );// 输出全局变量的值 100

函数的作用域

全局函数

函数与变量类似,具有全局作用域和函数作用域(局部作用域)。与全局变量类似,全局函数是被定义在全局作用域的,在任何位置都可以访问或调用该函数。

function fn( num1, num2){
	console.log( num1 + num2 );// 输出 3
}
fn( 1, 2 );

内部函数

function outer(){// 全局函数
	function inner(){// 局部函数
		console.log("inner");
	}
	inner();// 调用正常
}
inner();// 输出报错