let与var区别
1. let为块级作用域,通过{}进行作用域设置
var为词法作用域,并且只能通过function进行作用域设置
2. let不存在作用域提升,不同的作用域相同的变量,之间不会相互影响
var存在变量提升,相同的作用域下,后面的变量会替换前部分的变量
3. let存在作用域死区,由于变量只能在声明后使用,变量的不能提升,当子作用域进行let声明,就会进行绑定。父作用域的相同名称的变量,不做用于子作用域。(导致typeof()不再安全)
var不存在死区,当全局声明后,代码便不会报错,之后重新声明会覆盖(typeof()始终安全)
4. let中相同的作用域下,不能有相同的变量名
var可以进行相同变量的命名
function在ES6中
function在ES6中与let相似,可以存在于块级作用域,并且不存在提升,因此存在死区,外部代码不能调用内部代码
if(true){
function f(){
}
}
else{function f(){
}
}
JS代码存在问题
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f();
//提升后的代码
var tmp = new Date();
function f() {
var tmp
console.log(tmp);
if (false) {
tmp = 'hello world';
}
}
f();
const
const一旦声明马上赋值, 存在块级作用域 ,死区,用于常量的声明,但是并不是指其中内容不允许改变,而是const名称所指向的地址里面的内容不会改变,但是内容所关联的其他内容是否改变,就看自己是否要锁定。(复合类型的数据主要是对象和数组,变量指向的内存地址,保存的只是一个指向实际数据的指针)
const a={}; a.name=’a’; //a里面存放的是地址,并非内容,地址里面所关联的内容改变,不会报错
锁定
Object.freeze({});//不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性
如何将对象完全冻结
var constantize =
(obj) => { //传入obj
Object.freeze(obj); //将此对象冻结
Object.keys(obj).forEach( (key, i) => { //检查是否具有属性
if ( typeof obj[key] === 'object' ) { //如果具有属性
constantize( obj[key] ); //冻结属性
}
});
};
声明变量的方式
声明变量的方式:
const function var let class import
顶层对象
顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。
window.a=1;a=2 a//2
但是从let之后 所命名的变量不再是全局对象的属性 它是全局变量