var与let,const的区别详解

自从ES6新增后给前端的js代码书写带来很大的变化或者便利性。其中对于变量的定义var,let,const我们就来说说之间的区别吧。

let声明变量有以下几个特点:

1.没有预解析过程(即没有变量提升,var有变量提升)

2.不可以重复声明。

3.{}代表块级作用域,let有块级作用域,var只有函数作用域。

下面我们就一一举例来说明这些问题。

预解析问题:

function sayname() {
        	console.log(name)
        	console.log(age)
        	var name = "lili"
        	let age = "20"
        }
        sayname()
// undefined
// Uncaught ReferenceError

上面打印也很好理解:var 有变量提升,有个预解析的过程,所以在打印之前相当于先var name,然后再name = “lili”,所以第一个打印为undefined。第二个打印因为let没有预解析过程,所以就直接报错了。

下面我们来讲讲js中的变量提升与作用域的问题:

我们来先看一段代码,看看会打印什么:

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

结果是:

f a(){}

1

1

为什么呢?

这代码执行的情况是这样的:

先预编译var a = undefined,再预编译function a(){},函数a覆盖了a的默认值undefined,再a = 1

所以JS的预解析大致可以概括为:

1.从代码开始搜索直到结尾,只去查var  function和参数等内容

2.遇到函数与变量重名的,只留函数

3.遇到函数与函数重名的只留最后一个。

4.所有函数,在正式运行代码之前,都是整个函数块。

重复声明问题:

        var a = 1
        var a = 3
        let b = 2
        let b = 3

很简单,当你在一个块级作用域声明了一个b,你不能再声明b,否则会报错,当然在不同的块级作用域是可以重复声明的。然而var就可以

块级作用域与函数作用域问题:

         function tes(){
        	var a = 'var ok'
        	let b = 'let ok'
        	for (var i = 0; i < 1; i++) {
        	var a = 'var change'
        	let b = 'let change'
        	}
        	console.log(a)
        	console.log(b)
        }
        tes()

打印:var change    let ok

因为var只有函数作用域的概念,所以命名相同参数在同一作用域下会覆盖的,而let有块级作用域,function和for循环是两个不同的作用域,所以打印b不会取不同作用域的值。

类似的,在for循环中的定时器打印数据的问题上两者写法也有很大不同:

var 传统的写法,需要用闭包:

        for (var i = 0;i < 5;i++){
        	(function(a){
        		setTimeout(function(){
        			console.log(a)
        		},1000)
        	})(i)
        }

运用闭包参数被引用的缓存机制,使得不会被销毁。

let的写法:

       for (let i=0; i<5;i++){
        	setTimeout(function(){
        		console.log(i)
        	},1000)
        }

相当于let定义的i有两个作用域,let i一直被引用,所以不会被销毁

const讲解:

const声明常量,只可以声明一次,并且必须赋值,可以防止命名冲突,防止之后发生错误的修改。

        const g = 1 
        const g=2  // 报错
        g=2 // 报错

但是下面的修改却成功修改成功了,这是为什么呢? 

        const d = {
        	name:'allen'
        }
        d.name = 'zhaosi'
        console.log(d)

因为const只是修饰栈空间的地址不可更改,并没有修饰堆空间的值不可修改。

你可能感兴趣的:(ES6)