var let const以及object.freeze()

ES6之前,是没有块级作用域的概念,只有全局作用域、函数作用域,定义变量只能使用var
比如在ES5,下面的例子获取变量i,结果都是3

    
  • 1
  • 2
  • 3
... var li = document.getElementsByTagName('li'); function test() { for (var i = 0; i < li.length; i++) { li[i].onclick = function () { console.log(i) //3 3 3 } } } test()

ES5中获取真实的i,就需要使用到闭包:

    
  • 1
  • 2
  • 3
... function test2() { for (var i = 0; i < li.length; i++) { li[i].onclick = (function (i) { return function () { console.log(i) //0 1 2 } })(i) } } test2()

var:没有块的概念,可以跨块访问,不能跨函数访问,不初始化出现undefined,不会报错。

console.log(num);      //不会报错  undefined
var num = 3
console.log(num);      //3

ES6中新增了块级作用域的概念,{} 中括号创建的区域就是一个块级作用域,在块级作用域内创建的块级变量,外面是访问不到的。而let,const 就是这样的变量,比如:

    {
        var str = "this"
        let num = 1;
        console.log(str)          //this
        console.log(num)          //1
    }
    console.log(str)              //this
    console.log(num)              //Error  num is not defined

有了let,我们处理一开始的变量i,就方便很多:

    function closure() {
        for (let i = 0, len = li.length; i < len; i++) {
            li[i].onclick = function () {
                console.log(i)            //0 1 2
            }
        }
    }
    closure()

const,var定义的变量的区别不仅仅是在块级作用域,const定义的变量是不可修改的:

var num1 = 1;
num1 = 2;

let num2 = 3;
num2 = 4;

const num3 = 5;
num3 = 6             //Error Assignment to constant variable.

const定义的对象,我们无法对这个变量再次赋值,但是我们可以修改这个对象本身,比如下面这段代码:

const obj = { test:1 }
obj.test = 2                  //{test:2}
obj = 123                     //Error Identifier 'obj' has already been declared
const array = [1,2,3]
array[1] = 4                  //[1,4,3]

let:let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
const:const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。

既然讲到了const有定义变量不可修改,但是他定义的对象本身是可以更改的,如何让他能够完全不被修改,就让人想到了另一个属性Object.freeze()

const obj= {
  test:1
}
Object.freeze(obj)
obj.test=2 //没有任何反应
console.log(obj)   //{test:1}

但是Object.freeze()冻结的对象是真的无法改变了吗?也不是的,因为Object.freeze()仅仅是浅层次的冻结:

const obj= {
  test:1,
  test2:{
    num:3  
  }
}
Object.freeze(obj)
obj.test2.num=10 
console.log(obj)   //{test:1,test2:{num:10}}

对象内部的对象属性元素依然是可以更改的,要想完全冻结一个对象,得自己写一个类似于深度克隆一样的DeepFreeze递归方法去处理;而且被冻结得对象如果是let 创建的,虽然不能改变它的非对象的属性,但依然可以被重新赋值:

let obj= {
  test:1
}
Object.freeze(obj)
obj.test=2
console.log(obj)   //{test:1}
obj=2
console.log(obj)   //2

Object.freeze()方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。但是该冻结只是一个浅层次的冻结。

你可能感兴趣的:(var let const以及object.freeze())