欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ES6基础入门之let、const

程序员文章站 2022-04-03 21:30:46
以前变量的声明,可以通过var或者直接使用 直接使用相当于往window全局对象上挂了一个属性 let和var的主要区别: let声明的变量只在当前(块级)作用域内有效 let声明的变量不能被重复声明 不存在变量提升 ES6之前的作用域: 全局作用域 函数作用域 eval作用域 ES6块级作用域: ......

以前变量的声明,可以通过var或者直接使用

直接使用相当于往window全局对象上挂了一个属性

ES6基础入门之let、const

 

 ES6基础入门之let、const

 

 

let和var的主要区别:

let声明的变量只在当前(块级)作用域内有效

let声明的变量不能被重复声明

不存在变量提升 

 

es6之前的作用域:

全局作用域  函数作用域  eval作用域

 

es6块级作用域:

所有用花括号包裹的代码块,如:

    if(){}
    for(){}
    switch(){}
    try{}catch(e){}
    {}

 但是不包括对象,如下面这种情况不是块级作用域

var obj={

    
}
{
    var a=1;//不受块级作用域影响
    let b=2;//只作用在块级作用域内
}
console.log(a);
console.log(b);

ES6基础入门之let、const

 

 块级作用域可以嵌套

内层可以访问外层,外层不能访问内层

{
    let a=1;
    {
        let b=2;
        console.log(a);
    }
    console.log(b);
}

ES6基础入门之let、const

 

 

使用let或者const声明的变量,不能再被重新声明

var a=1;
var a;
console.log(a);//1  不会是undefined
var a=2;
console.log(a);//2

let c=1;
let c;//报错

 

let不存在变量提升

var是存在变量提升的,比如下面这段代码

ES6基础入门之let、const

 

 由于变量提升会把声明提前,相当于

ES6基础入门之let、const

 

 因此结果是undefined

 

ES6基础入门之let、const

 

 如果是let,不存在变量提升,因此会报错

 

暂存死区:

ES6基础入门之let、const

 

 ES6基础入门之let、const

 

 es6规定,如果在一个作用域中存在let或者const声明的变量,那么会形成一个封闭作用域,因此会拿不到外面的变量

ES6基础入门之let、const

 

 ES6基础入门之let、const

 

 

 

使用let实现面试常见小例子

生成10个按钮,每次点击弹出1-10

使用var来实现

for(var i=0;i<10;i++){
    (function(i){
        var btn=document.createelement("button");
        btn.innertext=i;
        btn.onclick=function(){
            alert(i);
        }
        document.body.appendchild(btn);
    })(i);
}

使用let来实现(不再需要闭包来实现内部的作用域)

for(let i=0;i<10;i++){
    let btn=document.createelement("button");
    btn.innertext=i;
    btn.onclick=function(){
        alert(i);
    }
    document.body.appendchild(btn);
}

效果

ES6基础入门之let、const

 

const 声明常量-不可改变的量

常量必须在声明的时候赋值

跟let一样,不能重复声明,存在块级作用域,不存在变量提升

但是,当常量为引用类型的时候,是可以被修改的(不能修改引用地址,但是可以修改地址中的值)

对象:

const cyy={
    name:"cyy",
    age:18
}
console.log(cyy);
cyy.name="cyy2";
console.log(cyy);//可以修改引用地址里的值
cyy={};
console.log(cyy);//不能修改引用地址

ES6基础入门之let、const

 

 

数组:

const arr=[];
arr.push(1);
console.log(arr);//可以修改引用里的值
arr=[];
console.log(arr);//不可以修改引用地址

ES6基础入门之let、const

 

 

怎么防止常量为引用类型的时候能被修改的情况:

object.freeze()

const cyy={
    name:"cyy",
    age:18
}
console.log(cyy);
object.freeze(cyy);//禁止对象常量的值被修改
cyy.name="cyy2";
console.log(cyy);//可以修改引用地址里的值

ES6基础入门之let、const

 

 

const arr=[];
object.freeze(arr);
arr.push(1);
console.log(arr);//可以修改引用里的值

ES6基础入门之let、const

 

 

const扩展

es6之前怎么声明常量

1、假装是常量

var cyy="cyy";

2、给对象设置不可修改的属性

object.defineproperty

var cyy={};
object.defineproperty(cyy,"base_name",{
    value:"cyy",
    writable:false
})
cyy.base_name="cyy2";
console.log(cyy.base_name);

可以看到base_name属性并没有被更改

ES6基础入门之let、const

 

 

同理,如果是在全局范围内定义一个常量,就可以挂载到window上

object.defineproperty(window,"base_name",{
    value:"cyy",
    writable:false
})
base_name="cyy2";
console.log(base_name);

ES6基础入门之let、const

 

 

但是这样定义的常量,依然可以对属性做修改

object.defineproperty(window,"base_name",{
    value:"cyy",
    writable:false
})
base_name.a=1;
console.log(base_name.a);

ES6基础入门之let、const

 

 不过看我打印出来的,貌似是不能修改……

 

可以使用object.seal防止属性被扩展

object.defineproperty(window,"base_name",{
    value:"cyy",
    writable:false
})
object.seal(base_name);//防止常量的属性被修改
base_name.a=1;
console.log(base_name);
console.log(base_name.a);

ES6基础入门之let、const

 

 

object.seal能够防止属性被扩展,但是已经存在的属性,值是可以修改的

var cyy={a:1};
object.seal(cyy);
console.log(cyy);
cyy.b=2;
console.log(cyy);//不能扩展,没有b属性
cyy.a=3;
console.log(cyy);//属性能被修改,a被改变

ES6基础入门之let、const

 

 

如果想要禁止属性被修改,还是使用object.defineproperty

var cyy={a:1};
//禁止修改cyy对象的a属性
object.defineproperty(cyy,"a",{
    writable:false
})
object.seal(cyy);
console.log(cyy);
cyy.a=3;
console.log(cyy);//属性不能被修改

ES6基础入门之let、const

 

 

也就是说,object.defineproperty和object.seal结合使用,可以达到object.freeze的效果

//在es6之前,封装函数,使得常量不能被修改
//引用类型的常量,属性也不能被修改和扩展
object.defineproperty(object,"myfreeze",{
    value:function(obj){
        for(var i in obj){
            if(obj.hasownproperty(i)){
                object.defineproperty(obj,i,{
                    writable:false
                })
            }
        }
        object.seal(obj);
    }
})

const cyy={a:1};
object.myfreeze(cyy);

ES6基础入门之let、const

 

 

hasownproperty 判断属性是原型上的属性,还是自身的属性

var obj1={
    a:1,
    b:2
}
var obj2=object.create(obj1);
obj2.c=3;
obj2.d=4;

//for in遍历到了所有属性,有原型上的a和b属性,还有自身的c和d属性
for(var i in obj2){
    console.log(obj2[i]);
}

//hasownproperty 只会显示自身的属性(不包括原型属性)
for(var i in obj2){
    if(obj2.hasownproperty(i)){
        console.log(obj2[i]);        
    }
}

ES6基础入门之let、const

 

 

数组使用自定义的仿freeze方法

//在es6之前,封装函数,使得常量不能被修改
//引用类型的常量,属性也不能被修改和扩展
object.defineproperty(object,"myfreeze",{
    value:function(obj){
        for(var i in obj){
            if(obj.hasownproperty(i)){
                object.defineproperty(obj,i,{
                    writable:false
                })
            }
        }
        object.seal(obj);
    }
})

const cyy=[];
object.myfreeze(cyy);

ES6基础入门之let、const

 

 

但是,如果对象的属性值又是一个对象的话,那这个对象的属性值还是可以被修改的

//在es6之前,封装函数,使得常量不能被修改
//引用类型的常量,属性也不能被修改和扩展
object.defineproperty(object,"myfreeze",{
    value:function(obj){
        for(var i in obj){
            if(obj.hasownproperty(i)){
                object.defineproperty(obj,i,{
                    writable:false
                })
            }
        }
        object.seal(obj);
    }
})

var cyy={
    name:"cyy",
    age:18,
    num:{
        a:1,
        b:2
    }
}
object.myfreeze(cyy);

 

ES6基础入门之let、const

 

 

需要使用递归来解决

//在es6之前,封装函数,使得常量不能被修改
//引用类型的常量,属性也不能被修改和扩展
object.defineproperty(object,"myfreeze",{
    value:function(obj){
        for(var i in obj){
            if(obj.hasownproperty(i)){
                object.defineproperty(obj,i,{
                    writable:false
                })
            }

            //如果属性值是对象,则再次进行遍历
            if(obj[i] instanceof object){
                object.myfreeze(obj[i]);
            }
        }
        object.seal(obj);
    }
})

var cyy={
    name:"cyy",
    age:18,
    num:{
        a:1,
        b:2
    }
}
object.myfreeze(cyy);

ES6基础入门之let、const