JavaScript笔记(自用)——03变量(varletconst)

Posted 蓝Builing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript笔记(自用)——03变量(varletconst)相关的知识,希望对你有一定的参考价值。

javascript笔记(自用)——03变量

笔记均参考自JavaScript高级程序设计

ECMAScript变量可以用于保存任何类型的数据。有三个关键字可以声明变量:var、const和let。(let和const只能在ES6以后本版使用)

var 关键字

定义变量可以使用 var 操作符(var是一个关键字),后跟一个变量名:

var messagr;	//声明了一个名为message的变量,可保存任意类型数据
				//不初始化的情况下,会保存一个特殊的值undefind

初始化变量:

var message="hi";

赋值

message=100;

var声明作用域

在function外部定义为全局变量
在function内部定义为局部变量
没有var直接给标识符赋值为全局变量

<script>
		var message="hi";	//全局变量
		function test(){
			b = "我是全局变量b";	//全局变量,但不推荐,严格模式下会抛出异常
			var a=3;		//局部变量
			console.log(a);	//3
		}
		console.log(message);	//“hi”
		console.log(b);	//“我是全局变量b”
		console.log(a);	//出错!
	</script>

定义多个变量可以在一条语句中用逗号分隔每个变量(及初始化):

var snake="si",
	age=18,
	message="haha";

var声明提升

提升是指把所有的变量声明都拉到函数作用域的顶部。

function foo(){
	console.log(age);
	var age=26;
}
foo();	//undefined

等价于

function foo(){
	var age;
	console.log(age);
	gae=26;
}
foo();	//undefined

let声明

let和var的作用差不多,但有非常重要的区别:
let声明的范围是块作用域,var声明的范围是函数作用域

if(true){
	var name='haha';
	console.log(name);	//haha
} 
console.log(name);	//haha

if(true){
	let age=18;
	console.log(age);	//18
}
console.log(age);	//ReferenceError: age is not defined(age没有定义)

这里age变量之所以不能在if块外部被引用,是因为它的作用域仅限于该块内部
块作用域是函数作用域的子集,因此适用于var的作用域限制也同样适用于let

let不允许同一个块作用域中出现冗余声明。这样会导致报错:

var name;
var name;

let age;
let age;	//SyntaxError: Identifier 'age' has already been declared
			//即 SyntaxError: 标识符age已声明过了

JavaScript引擎会记录用于变量声明的标识符及其所在的块级作用域,因此嵌套使用相同的标识符不会报错。因为同一个块中没有重复声明

var name='lan';
console.log(name);	//lan
if(true){
	var name='jing';
	console.log(name);	//jing
}

	
let age=30;
console.log(age);	//30
if(true){
	let age=18;
	console.log(age);	//18
}

对声明冗余的变量不会因为混用let和var受影响。这两个关键字声明的并不是同类型的变量,它们只是指出变量在相关作用域如何存在。

var num1;
let num1;	//SyntaxError

暂时性死区

let与var的另一个重要区别就是let声明的变量不会在作用域中被提升

在解析代码时,javascript引擎也会在意出现在块后面的let声明,在此之前不能以任何方式来引用未声明的变量。

在let被声明之前执行的瞬间被称为“暂时性死区”,在此阶段引用任何后面才声明的变量都会抛出ReferenceError

//name会被提升
console.log(name);	//undefined
var name='lan';

//age不会被提升
console.log(age);	//ReferenceError: age is not defined
let age=18;

全局声明

使用let在全局作用域中声明的变量不会成为window对象的属性(var声明的变量则会)
*注意:let声明任然是在全局作用域中发生的,相应的变量会在页面的生命周期内存续。为了避免SyntaxError,必须确保页面不会重复声明同一个变量

var name='lan';
console.log(window.name);	//lan

let age=26;
console.log(window.age);	//undefined

for循环中的let声明

在let出现之前,for循环定义的迭代变量会渗透到循环体外部

for(var i=0;i<5;++i){
	//循环逻辑
}
console.log(i);	//5

let之后,这个问题就消失了。(作用域)

for(let i=0;i<5;++i){
	//循环逻辑
}
console.log(i);	//ReferenceError:i没有定义

对迭代变量的奇特声明和修改:

for(var i=0;i<5;++i){
	setTimeout(()=>console.log(i),0);
}
//输出为:5,5,5,5,5
  • 在退出循环时,迭代变量保存的是导致循环退出的值。在之后的执行超时逻辑时,所有的i都是同一个变量。

  • 使用let声明迭代变量时,JavaScript引擎在后台会为每个迭代循环声明一个新的迭代变量。

     for(var i=0;i<5;++i){
     	setTimeout(()=>console.log(i),0);
     }
     //输出为:0,1,2,3,4
    

const声明

  • const的行为与let基本相同。

  • const声明变量时必须同时初始化变量

  • 试更改const声明的变量会导致运行时错误.。

     const age=15;
     age=18;	//TypeError:给常量赋值
     
     //const也不允许重复声明
     const name='lan';
     const name='jing';	//SyntaxError
     
     //const声明的作用域也是块
     const name='lan';
     if(true){
     	const name='jing';
     }
     console.log(name);	//lan
    

const声明的变量引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制。

const person={};
person.name='lan';	//ok
  • javascript引擎会未for循环中的let声明分别建立独立的变量实例,const与let变量相似,也不能const来声明迭代变量(迭代变量会自增):

     for(const i=0;i<10;++i);	//TypeError:给常量赋值
    
  • 可以只用const声明一个不被修改的for循环变量。即:每次迭代只是创建一个新变量。

     let i =0;
     for(const j=7;i<5;++i){
     	console.log(j);
     }
     //7,7,7,7,7
    

声明风格建议

  • 不使用var
    只使用let和const有助于提升代码质量,因为变量有明确的作用域、声明位置、不变的值
  • const优先,let次之
    • 使用const声明可以让浏览器运行时强制保持变量不变。
    • 也可以让静态代码分析工具提前发现不合法的赋值操作。
    • 有利于后期维护。

以上是关于JavaScript笔记(自用)——03变量(varletconst)的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript笔记(自用)——02语法

JavaScript笔记(自用)——01什么是JavaScript

JavaScript笔记(自用)——01什么是JavaScript

JavaScript学习笔记——闭包

[Effective JavaScript 笔记] 第9条:始终声明局部变量

自用RNN+LSTM笔记