js之旅(一)js变量

一、js中变量的定义

变量的定义过程可以分为两个部分声明赋值
在es6前,我们用var可以声明一个变量,也可以直接使用一个变量,es6新加了一种变量的声明方式let;就是下面三种变量的使用方法了。

var a;//用var声明一个变量a
let b;//用let声明一个变量b
c=10;//直接使用变量c;这里c是全局作用域
console.log(a);//undefined
console.log(b);//undefined
console.log(c);//10

1、那么问题来了,这三种使用变量的方式有什么不同?这个在第五小节给予回答。
2、现在看一下变量c的应用方式,如果我们直接下面的写法:

c;
console.log(c);

会报错如下:

VM85:3 Uncaught ReferenceError: c is not defined

对比一下:

c=10;
console.log(c); // 10

这里说明了一个问题,c变量其实已经声明过了,只不过是浏览器帮我们声明了。
3、还可以得出一个结论,仅仅声明,没有赋值的变量,值是undefined

二、js中变量的命名规则

js中变量的命名规则和其它语言类似,总结起来如下:

  • 变量以数字,字母,下划线或$组成
  • 变量以字母,下划线或$开头
  • 变量大小写敏感
  • 变量不能为js中的保留字

三、js变量的提升

js变量的提升是指:无论var变量声明在哪里,js都会把变量声明放在最前面
1、注意,是用var变量声明的变量,也就是说let是没有变量提升的。
2、如何理解js都会把变量声明放在最前面?看下面的例子:

console.log(a);//undefined
var a=10;

上面这个例子为什么会是undefined?就是因为js会把变量的声明放在前面,也就是说,js会加一个变量的声明,而且,将这个变量的声明放在代码的开头,上面的代码和下面的这个是等价的。

var a;
console.log(a);
var a=10;

有了这个理解后,下面的这个实例也就不难解释了

function fun(){
	console.log(a);//undefined
	var a=10;
}
fun();

因为在函数内部,变量的声明也会被放在函数内部的前面,上面的例子和下面的实际上是等价的。

function fun(){
	var a;
	console.log(a);//undefined
	var a=10;
}
fun();

四、js变量的作用域

讲js变量的作用域我们必须分开来说,因为var和let的作用域是不同的

1、var的的作用域

按作用域划分,var声明的变量可以化为为全局变量局部变量

  • 全局变量:声明在函数之外的变量
  • 局部变量:声明在函数里的变量

重点来了,怎么理解声明在函数里的变量?看下面这个例子:

function fun(){
	for(var i = 0; i < 10; i++){
	}
	console.log(i);
}
fun();

猜一下,它会打印什么?10,为什么?
还记得var变量的提升不?在函数内部,变量的声明也会被放在函数内部的前面,其实上面的例子和下面是等价的。

function fun(){
	var i;
	for(var i = 0; i < 10; i++){
	}
	console.log(i);
}
fun();

也就是说,局部变量是以函数块为标准划定的,无论它是在if,for,switch哪个地方定义的,看以下例子:

function fun(){
	if(1 == "1"){
		var a =10;
	}

	switch(1){
		case 1:
			var b = 10;
	}

	for(var c = 0; c < 10; c++){

	}
	d=10;
	console.log(a);//10
	console.log(b);//10
	console.log(c);//10
}
fun();
console.log(d); // 10
console.log(a); // VM197:21 Uncaught ReferenceError: a is not defined

下一个问题:在html中<script>标签引入的作用域是怎样的:

//c.js
var a = 10;
//a.html
<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>

</body>
<script type="text/javascript" src="./c.js"></script>
<script type="text/javascript">
	console.log("this is: " + a);//this is: 10
</script>
</html>

看起来答案显而易见,

//c.js
var a = 10;
//a.html
<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>

</body>
<script type="text/javascript">
	console.log("this is: " + a);//Uncaught ReferenceError: a is not defined
</script>
<script type="text/javascript" src="./c.js"></script>
</html>

它报错说a没有定义,啥情况?
对比一下:

//c.js
var a = 10;
//a.html
<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>

</body>
<script type="text/javascript">
	setTimeout(function(){
		console.log("this is: " + a);// this is 10
	}, 1000)
	
</script>
<script type="text/javascript" src="./c.js"></script>
</html>

这里和<script>标签的加载顺序有关,<script>标签加载的js文件中定义的全局变量只有在它加载完成之后我们才可以使用。

2、let的作用域
2.1块级作用域

let是块级作用域,就是说let是在{}中生效的,包括函数,if,for,switch,看下面的例子:

let a = 10;
{
	let b =10;
	console.log(b);
}

//console.log(b);
function fun (){
	let c = 10;
	for(let d = 0; d < 10; d++){

	}
	//console.log(d);

	if(1 == "1"){
		let e = 10;
	}
	//console.log(e);

	switch(1){
		case 1:
			let f = 10;
	}
	//console.log(f);
}

fun();
//console.log(c);

发现被注释的地方都在报错,这很好的解释了什么是块级作用域,就是{}里面的区域就是块级作用域

2.2暂时性死区

了解完块级作用域我们再来了解一下let的暂时性死区:在代码块中,使用let命令所声明的变量在声明之前都是不可用的。在语法上,称为“暂时性死区”(temporal dead zone)TDZ。
下面这个例子帮助理解一下什么叫暂时性死区。

console.log(a);
let a = 10;//Uncaught ReferenceError: a is not defined

因为let没有变量的提升(不太正确),所以这个地方会报错,暂时性死区就是说let定义的变量要先声明,后使用
看下面的例子:

var test = 1;
function func(){
    console.log(test);
    let test = 2;
};
func();  // Uncaught ReferenceError: Cannot access 'test' before initialization

在let声明变量前,使用该变量,它是会报错的,而不是像var那样会‘变量提升’。
其实说let没有‘变量提升’的特性,不太对。或者说它提升了,但是ES6规定了在let声明变量前不能使用该变量
看下面:

var test = 1;
function func(){
    console.log(test);
    let test = 2;
};
func();  // VM289:3 Uncaught ReferenceError: Cannot access 'test' before initialization

如果let声明的变量没有变量提升,应该打印’1’(func函数外的test);而它却报错,说明它是提升了的,只是规定了不能在其声明之前使用而已。我们称这特性叫“暂时性死区(temporal dead zone)”。且这一特性,仅对遵循‘块级作用域’的命令有效(let、const)

2.3不允许重复声明

let声明的变量不可重复声明,看下面例子:

function fun(){
	let a = 10;
	let a = 1;
}
fun();//Uncaught SyntaxError: Identifier 'a' has already been declared

即使和var重复声明也不可以(块级作用域内)

function fun(){
	let a = 10;
	var a = 1;
}
fun();//Uncaught SyntaxError: Identifier 'a' has already been declared

看一下下面的情况:

for(let i = 0; i < 3; i++){
	let i = "test";
	console.log(i);
}
// test test test

for设置循环变量的是父作用域和一个子作用域

五、let,var,直接定义变量的区别

  • let是块级做用域,var是局部做用域和全局做用域
  • let没有变量提升,var有变量提升
  • let要先声明后使用,var因为有变量提升,可以先使用后定义
  • 直接定义变量是全局变量
  • let不允许重复声明,var可以重复声明
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值