var、let、const

一、var、let、const的区别

1. 作用域不同

  • var声明变量存在于函数级作用域内(该域内存在变量提升) ,意味着该变量将在函数退出时被销毁。
  • let/const ,可以使用块级作用域。块级作用域解决了ES5中的两个问题:
    ①内层变量可能覆盖外层变量
    ②用来计数的循环变量泄露为全局变量
  • let/const有一个暂时性死区的概念,即进入作用域创建变量到变量可以开始访问的一段时间,也就是 在使用let、const命令声明变量之前,该变量都是不可用的。
console.log(a)
var a
//var存在变量提升相当于
var a
console.log(a); //undefined

//针对let存在暂时性死区
console.log(a) // ReferenceError: a is not defined
let a

当程序的控制流程在新的作用域(module function 或 block 作用域)进行实例化时,在此作用域中用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。

通俗一点来讲就是:
S6规定,let/const 命令会使区块形成封闭的作用域。若在声明之前使用变量,就会报错。
总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。
这在语法上,称为 “暂时性死区”( temporal dead zone,简称 TDZ)。

TDZ 也意味着 typeof 不再是一个百分之百安全的操作。
看下面这段代码:

typeof a // ReferenceError: a is not defined
let a

2. 重复声明

  • var重复声明不会报错,全局声明的变量成为window对象的属性。
  • let不允许同一个块级作用域中出现冗余声明。
  • 混用var、let重复声明一个变量也会报错。

3. 变量赋值

  • let,const主要的区别在于:const一旦被赋值就不再"改变(这并不意味着声明的变量本身不可变,只是说它不可再次被赋值了。const定义引用类型时,只要它的引用地址不发生改变,仍然可以改变它的属性)
const person = { name : 'Jack'} 
person.name = 'Tom'
console.log(person); //{name: 'Tom'}

4. 指针指向

  • let和const都是ES6新增的用于创建变量的语法。
    let创建的变量是可以更改指针指向(可以重新赋值)。但const声明的变量是不允许改变指针的指向。

5. 初始值设置

  • 在变量声明时,var 和 let 可以不用设置初始值。而const声明变量必须设置初始值。

6. 给全局添加属性

  • 浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。

二、变量提升

JavaScript引擎会先进行预解析,获取所有变量的声明复制undefined,然后逐行执行,这导致所有被声明的变量,都会被提升到代码的头部(函数的top的地方,且被提升的只有变量,值不会被提升),也就是变量提升(hoisting)
我们先来看一个例子

var a = 2;
function A() { 
  console.log(a); 
}
A();

不出意外打印出的结果是2

var a = 2;
function A() { 
  console.log(a); 
  var a = 1;
}
A();

这里的打印结果与我们预想的可能有出入,执行结果是undefined,这里面隐藏了一个陷阱-----JavaScript中的变量提升(Hoisting)。
我们定义三个变量

(function(){
    var a = 'A';
    var b = 'B';
    var c = 'C';
})()

实际上它是这样的

(function(){
    var a,b,c;
    a = 'A';
    b = 'B';
    c = 'C';
})()

再回过头来看上面的代码相当于

var a = 2;
function A() { 
  var a;
  console.log(a); //undefined
  a = 1;
}
A();

因在之前打印之前只是声明了变量并未赋值,所以是undefined。

三、函数提升

函数提升是把整个函数都提到前面去。
在我们写js代码的时候,我们有2种写法,一种是函数表达式,另外一种是函数声明方式,只有函数声明形式才能被提升

function test(){
    promote();
    function promote(){
        console.log("函数声明提升成功");
    }
}
test();

能够打印出“函数提升成功”

function test(){
   promote();
   var promote = function promote(){
   	   console.log("函数表达式不能被提升");
    }
}
test();

执行报错:“promote is not a function”
在这里插入图片描述

再看一段代码的输出

var a = 2;
function A() { 
   console.log(a); 
   var a = 1;
   function a() {
   }
}

A();

以上代码类似于:

var a;
function A() { 
   var a;
   function a() {
   }
   console.log(a); 
   a = 1;
}
a = 2;

A();

运行结果打印出了方法a
在这里插入图片描述
这是因为先把变量提升了,接着函数也提升了,变量名又和函数名同名,最终函数声明的a覆盖了变量声明的 a导致最终a为声明的函数。

var fn = 721;
function fn() {
	console.log('函数声明能被提升');
}
console.log(fn);
fn(); 

以上代码类似于下面代码:

var fn;
function fn() {
	console.log('函数声明能被提升');
}
fn = 721;
console.log(fn);
fn(); 

结果为:721
结果为:fn2 is not a function
相当于函数声明被提升,变量fn被声明且赋值为721,且由于同名又覆盖了函数声明。

var fn = 721;
var fn = function() {
	console.log('函数表达式声明不能提升');
}
console.log(fn);
fn(); 

以上代码类似于下面代码:

var fn;
fn = 721;
var fn;
fn = function() {
	console.log('函数表达式声明不能提升');
}
console.log(fn);
fn(); 

结果为:function fn()
结果为:函数表达式声明不能提升
相当于声明了两个同名的变量并发生了覆盖

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值