ES6基础入门之let、const

前端之家收集整理的这篇文章主要介绍了ES6基础入门之let、const前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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

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

@H_404_1@@H_404_1@

 @H_404_1@

 

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

let和var的主要区别:@H_404_1@

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

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

不存在变量提升 @H_404_1@

 @H_404_1@

ES6之前的作用域:@H_404_1@

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

 @H_404_1@

ES6块级作用域:@H_404_1@

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

    if(){}
    forswitchtry{}catch(e){}
    {}

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

var obj={

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

@H_404_1@@H_404_1@

 @H_404_1@

 块级作用域可以嵌套@H_404_1@

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

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

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

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

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

let c=1;
let c;报错

 @H_404_1@

let不存在变量提升@H_404_1@

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

@H_404_1@@H_404_1@

 @H_404_1@

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

@H_404_1@@H_404_1@

 @H_404_1@

 因此结果是undefined@H_404_1@

 @H_404_1@

@H_404_1@@H_404_1@

 @H_404_1@

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

 @H_404_1@

暂存死区:@H_404_1@

@H_404_1@@H_404_1@

 @H_404_1@

 

@H_404_1@@H_404_1@

 @H_404_1@

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

@H_404_1@@H_404_1@

 @H_404_1@

 

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

 @H_404_1@

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

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

使用var来实现@H_404_1@

for(var i=0;i<10;i++){
    (function(i){
        var btn=document.createElement("button");
        btn.innerText=i;
        btn.onclick=(){
            alert(i);
        }
        document.body.appendChild(btn);
    })(i);
}

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

for(let i=0;i<10;i++){
    let btn=document.createElement("button");
    btn.innerText=i;
    btn.onclick=(){
        alert(i);
    }
    document.body.appendChild(btn);
}

效果@H_404_1@

@H_404_1@@H_404_1@

 @H_404_1@

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

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

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

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

对象:@H_404_1@

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

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

数组:@H_404_1@

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

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

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

Object.freeze()@H_404_1@

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

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

const ARR=[];
Object.freeze(ARR);
ARR.push(1可以修改引用里的值

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

const扩展@H_404_1@

ES6之前怎么声明常量@H_404_1@

1、假装是常量@H_404_1@

var CYY="cyy";

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

Object.defineProperty@H_404_1@

var cyy={};
Object.defineProperty(cyy,"BASE_NAME"false
})
cyy.BASE_NAME="cyy2";
console.log(cyy.BASE_NAME);

可以看到BASE_NAME属性并没有被更改@H_404_1@

@H_404_1@@H_404_1@

 使用Object.defineProperty,并给属性设置writable:false,能让属性不可被修改;但是对象是可以新增属性的@H_404_1@

 @H_404_1@

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

Object.defineProperty(window,"BASE_NAME"
})
BASE_NAME="cyy2";
console.log(BASE_NAME);

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

但是这样定义的常量,依然可以新增属性@H_404_1@

下面代码是给window对象的BASE_NAME属性设置了不可修改,但是还是可以给window对象上新增属性@H_404_1@

Object.defineProperty(window,1)">
})
window.a=1;
console.log(window.a);

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

可以使用Object.seal防止属性被扩展@H_404_1@

Object.defineProperty(window,1)">
})
Object.seal(BASE_NAME);防止常量的属性修改
BASE_NAME.a=1;
console.log(BASE_NAME);
console.log(BASE_NAME.a);

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

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

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

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

如果想要禁止属性修改,还是使用Object.defineProperty@H_404_1@

};
禁止修改cyy对象的a属性
Object.defineProperty(cyy,"a"
})
Object.seal(cyy);
console.log(cyy);
cyy.a=3属性不能被修改

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

也就是说,Object.defineProperty和Object.seal结合使用,可以达到Object.freeze的效果@H_404_1@

在ES6之前,封装函数,使得常量不能被修改
//引用类型的常量,属性也不能被修改和扩展
Object.defineProperty(Object,"myfreeze"(obj){
        var i in obj){
            (obj.hasOwnProperty(i)){
                Object.defineProperty(obj,i,{
                    writable:
                })
            }
        }
        Object.seal(obj);
    }
})

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

@H_404_1@@H_404_1@

补充:里面每一行undefined是console.log()执行之后的返回值。@H_404_1@

log()本质上是一个函数函数中如果没有设置return返回值,默认返回undefined。@H_404_1@

这个不用管,不是代码的问题,忽略这个undefined,只看前面输出内容即可@H_404_1@

 @H_404_1@

hasOwnProperty 判断属性是原型上的属性,还是自身的属性@H_404_1@

var obj1={
    a:1
}
var obj2=Object.create(obj1);
obj2.c=3;
obj2.d=4;

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

hasOwnProperty 只会显示自身的属性(不包括原型属性
 obj2){
    (obj2.hasOwnProperty(i)){
        console.log(obj2[i]);        
    }
}

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

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


                })
            }
        }
        Object.seal(obj);
    }
})

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

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

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


                })
            }
        }
        Object.seal(obj);
    }
})


    }
}
Object.myfreeze(cyy);

 @H_404_1@

@H_404_1@@H_404_1@

 @H_404_1@

 @H_404_1@

需要使用递归来解决@H_404_1@


                })
            }

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


    }
}
Object.myfreeze(cyy);

@H_404_1@@H_404_1@

 @H_404_1@

猜你在找的ES6相关文章