8-js基础-变量声明和变量提升

100 阅读3分钟

解释 JavaScript 中的作用域与变量声明提升?

答案:

  • 我对作用域的理解是只会对某个范围产生作用,而不会对外产生影响的封闭空间。在这样的一些空间里,外部不能访问内部变量,但内部可以访问外部变量。
  • 所有申明都会被提升到作用域的最顶上
  • 同一个变量申明只进行一次,并且因此其他申明都会被忽略
  • 函数声明的优先级优于变量申明,且函数声明会连带定义一起被提升

作用域的分类

更多参考

答案:全局作用域、函数作用域、块级作用域

解析:

全局作用域

在代码的最外层的变量和函数称为全局作用域,有以下特点:

①在代码的任何地方都可以访问得到

②变量声明时如果省略var关键字,则为全局变量,拥有全局作用域

③window对象的属性和方法,拥有全局作用域

④浏览器打开时开启,浏览器关闭或者页面关闭时销毁

var cat = '有鱼';
function Person(){
    var name = '张三';
    per = '卡卡';// 省略var,视为全局变量
    console.log(cat);//有鱼 cat为全局变量,函数Person内部可以访问
}
console.log(cat);//有鱼 cat为全局变量,最外层代码可以访问
console.log(per);//卡卡 per为全局变量,最外层代码可以访问
复制代码

全局作用域也有弊端,如:变量命名时容易重复,造成变量污染;

函数作用域

在函数内部的变量权限称为函数作用域,有以下特点:

①每个函数都有自己的作用域,而且调用一次就会生成新的作用域

②只能在函数内部才能访问,外部是没有权限访问的

③进入函数内部时开启,函数执行完毕后销毁

var cat = '有鱼';
function Person(){
    var name = '张三';
    console.log(name);//张三 name为函数作用域,函数Person内部可以访问
}
console.log(name);//有鱼 name为函数作用域,最外层代码没有权限访问
复制代码

块作用域(ES6新增)

凡是由{}符号包裹起来的都是块作用域,ES6新增的知识点,有以下特点:

①只能在{}内部起作用,if和for的{}也是属于块级作用域

②变量声明时使用let或const关键字

③变量名不能重复,否则会报错

④变量不可以在声明之前使用

使用var进行展示:

if(true){
    var cat = '有鱼';
    console.log(cat);//有鱼 
}
console.log(cat);//有鱼
复制代码

使用let进行展示:

if(true){
    let cat = '有鱼';
    console.log(cat);// 有鱼
    // let cat = '年年';// Uncaught SyntaxError: Identifier 'cat' has already been declared

}
console.log(cat);// 访问不了cat变量  报:Uncaught ReferenceError: cat is not defined
复制代码

注意:块作用域一般用在for等循环语句中,可以避免变量外泄

JS 块级作用域、变量提升

答案:

  1. 块级作用域

JS 中作用域有:全局作用域、函数作用域。没有块作用域的概念。ECMAScript 6(简称 ES6)中新增了块级作用域。块作用域由 { } 包括,if 语句和 for 语句里面的{ }也属于块作用域。

  1. 变量提升
  • 如果变量声明在函数里面,则将变量声明提升到函数的开头
  • 如果变量声明是一个全局变量,则将变量声明提升到全局作用域的开头

解析:

<script type="text/javascript">
	{
		var a = 1;
		console.log(a); // 1
	}
	console.log(a); // 1
	// 可见,通过var定义的变量可以跨块作用域访问到。

	(function A() {
		var b = 2;
		console.log(b); // 2
	})();
	// console.log(b); // 报错,
	// 可见,通过var定义的变量不能跨函数作用域访问到

	if(true) {
		var c = 3;
	}
	console.log(c); // 3
	for(var i = 0; i < 4; i++) {
		var d = 5;
	};
	console.log(i);	// 4   (循环结束i已经是4,所以此处i为4)
	console.log(d); // 5
	// if语句和for语句中用var定义的变量可以在外面访问到,
	// 可见,if语句和for语句属于块作用域,不属于函数作用域。

	{
		var a = 1;
		let b = 2;
		const c = 3;

		{
			console.log(a);		// 1	子作用域可以访问到父作用域的变量
			console.log(b);		// 2	子作用域可以访问到父作用域的变量
			console.log(c);		// 3	子作用域可以访问到父作用域的变量

			var aa = 11;
			let bb = 22;
			const cc = 33;
		}

		console.log(aa);	// 11	// 可以跨块访问到子 块作用域 的变量
		// console.log(bb);	// 报错	bb is not defined
		// console.log(cc);	// 报错	cc is not defined
	}
</script>

拓展:

var、let、const 的区别

  • var 定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
  • let 定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
  • const 用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。
  • 同一个变量只能使用一种方式声明,不然会报错
<script type="text/javascript">
	// 块作用域
	{
		var a = 1;
		let b = 2;
		const c = 3;
		// c = 4; // 报错

		// let a = 'a';	// 报错  注:是上面 var a = 1; 那行报错
		// var b = 'b';	// 报错:本行报错
		// const a = 'a1';	// 报错  注:是上面 var a = 1; 那行报错
		// let c = 'c';	// 报错:本行报错

		var aa;
		let bb;
		// const cc; // 报错
		console.log(a); // 1
		console.log(b); // 2
		console.log(c); // 3
		console.log(aa); // undefined
		console.log(bb); // undefined
	}
	console.log(a); // 1
	// console.log(b); // 报错
	// console.log(c); // 报错

	// 函数作用域
	(function A() {
		var d = 5;
		let e = 6;
		const f = 7;
		console.log(d); // 5
		console.log(e); // 6  (在同一个{ }中,也属于同一个块,可以正常访问到)
		console.log(f); // 7  (在同一个{ }中,也属于同一个块,可以正常访问到)
	})();
	// console.log(d); // 报错
	// console.log(e); // 报错
	// console.log(f); // 报错
</script>