var、let、const的区别

1. var

1.1 描述

var用于声明一个变量,在全局范围内声明,它的作用域是全局;在函数中声明,它的作用域是它所在函数的执行上下文及其闭包(嵌套函数);

var声明的变量存在变量提升(hoisting),即把变量提升为go/ao的不可配置属性,值为undefined;函数提升,即把函数提升为go/ao的不可配置属性,值为函数对象的地址;不可配置属性代表不能使用delete关键字删除;此外,需要注意是提升到当前作用域的顶部

var允许重复声明变量,先声明的被覆盖;

1.2 示例

示例代码
  var username = '小野友树';
  var n = 100;
  foo();
  function foo() {
	var num = 10;
	console.log(num, n, 'top',username); // 10,undefined,'top','小野友树'
	var n = 20;
	console.log(num, n, 'bottum',username); // 10,20,'bottom','小野友树'
	console.log(temp); // Uncaught ReferenceError: temp is not defined 引用错误
  }
伪代码
// 全局对象预解析
globalObject = {  
	String:'',  
	Number:'',  
	setTimeout:,  // ...
	window:globalObject, // go身上又有一个window属性,指向自己
	username:undefined,  // 变量提升
	n:undefined, // 变量提升
	foo:0x11a // 函数提升, ==> foo函数对象 
}

// 全局执行上下文入栈,执行代码
username = '小野友树';
n = 100;
foo()

// 遇到函数调用语句,函数的ao预解析
ao = {
	num:undefined,
	n:undefined
}

// 函数执行上下文入栈,执行代码
num = 10;
console.log(num, n, 'top',username); // 10,undefined,'top','小野友树' 
n = 20;
console.log(num, n, 'bottum',username); // 10,20,'bottom','小野友树'
console.log(temp); // Uncaught ReferenceError: temp is not defined
输出结果

在这里插入图片描述

此例中:

  1. var存在变量和函数声明提升,因此第一句打印,n输出undefined而不是100
  2. username和temp在函数作用域内找不到,就会沿着作用域链去查找
1.3 var声明多个变量

参考链接

1. 等号

  function show() {
	var a = (b = c = d = 5);
  }
  show();
  console.log(b, c, d); // 5 5 5
  console.log(a); // Uncaught ReferenceError: a is not defined

因为赋值是从右向左结合 :
var a = b = c = d = 5;
等价于
var a = ( b = ( c = ( d = 5 ) ) );
其中只有 a 被 var 声明了,b , c 和 d 没有声明而是在函数作用域中没有寻找到,沿着作用域链也没找到,最终都自动解析为全局变量了,因此可以在全局内打印。

2. 逗号

function show(){
	var a  = 5, b = 6, c = 7;
}
show();
console.log(a,b,c); // 全都报错 var.html:34 Uncaught ReferenceError: a(b,c) is not defined

注意: var 声明了3个局部的变量

2. let

  1. let 不存在变量、函数声明提升,即不会在全局对象/ao上创建属性;

  2. let 不允许重复声明变量,否则会抛出 SyntaxError语法错误;

  3. let 声明的变量作用域只在其声明的块或子块内部,这一点,与var相似。二者之间最主要的区别在于var 声明的变量的作用域是整个封闭函数。

function varTest() {
  var x = 1;
  {
    var x = 2; // same variable!
    console.log(x); // 2
  }
  console.log(x); // 2
}

function letTest() {
  let x = 1;
  {
    let x = 2; // different variable
    console.log(x); // 2
  }
  console.log(x); // 1
}

  1. var 不同的是,let 只是开始声明,而非一个完整的表达式。这意味着你不能将单独的 let 声明作为一个代码块的主体(这是有道理的,因为声明的变量无法被访问)。
if (true) let a = 1; // SyntaxError: Lexical declaration cannot appear in a single-statement context
  1. 暂时性死区问题
var foo = 123
{ // TDZ starts at beginning of scope
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2; 
  // End of TDZ (for foo)
}

没有变量提升,且块级作用域内被let声明的变量也不会沿着作用域去找!

let foo = (foo + 55); // ReferenceError 

因为表达式是先执行右边,再赋值

  1. 暂时性死区与typeof
{
	console.log(typeof b); // undefined
	console.log(typeof a); // Uncaught ReferenceError: Cannot access 'a' before initialization
	let a = 1;
	var b = 2;
}
  1. varlet 合并的声明方式会抛出 SyntaxError 语法错误,因为 var 会将变量提升至块的顶部,这会导致隐式地重复声明变量。
let x = 1;
{
  var x = 2; // SyntaxError for re-declaration
}

3. const

let 相同的部分不再赘述。

const 声明创建一个常量,常量要求一个初始值,因此const声明必须初始化;
const 声明创建一个值的只读引用,但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配;const 声明的对象和数组,对象的属性和数组的元素是可以改变的;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值