ES6基础入门之let、const
以前变量的声明,可以通过var或者直接使用 直接使用相当于往window全局对象上挂了一个属性 ? ? ? ? let和var的主要区别: let声明的变量只在当前(块级)作用域内有效 let声明的变量不能被重复声明 不存在变量提升? ? ES6之前的作用域: 全局作用域? 函数作用域? eval作用域 ? ES6块级作用域: 所有用花括号包裹的代码块,如: if(){} forswitchtry{}catch(e){} {} ?但是不包括对象,如下面这种情况不是块级作用域 var obj={ } { var a=1;//不受块级作用域影响 let b=2;只作用在块级作用域内 } console.log(a); console.log(b); ? ?块级作用域可以嵌套 内层可以访问外层,外层不能访问内层 { let a=1; { let b=2; console.log(a); } console.log(b); } ? ? 使用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是存在变量提升的,比如下面这段代码 ? ?由于变量提升会把声明提前,相当于 ? ?因此结果是undefined ? ? ?如果是let,不存在变量提升,因此会报错 ? 暂存死区: ? ? ? ?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=(){ 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=(){ alert(i); } document.body.appendChild(btn); } 效果 ? const 声明常量-不可改变的量 常量必须在声明的时候赋值 跟let一样,不能重复声明,存在块级作用域,不存在变量提升 但是,当常量为引用类型的时候,是可以被修改的(不能修改引用地址,但是可以修改地址中的值) 对象: const cyy={ name:"cyy",age:18 } console.log(cyy); cyy.name="cyy2"; console.log(cyy);可以修改引用地址里的值 cyy={}; console.log(cyy);不能修改引用地址 ? ? 数组: const ARR=[]; ARR.push(1); console.log(ARR);可以修改引用里的值 ARR=[]; console.log(ARR);不可以修改引用地址 ? ? 怎么防止常量为引用类型的时候能被修改的情况: Object.freeze() const cyy= } console.log(cyy); Object.freeze(cyy);禁止对象常量的值被修改 cyy.name="cyy2"可以修改引用地址里的值 ? ? const ARR=[]; Object.freeze(ARR); ARR.push(1可以修改引用里的值 ? ? const扩展 ES6之前怎么声明常量 1、假装是常量 var CYY="cyy";
2、给对象设置不可修改的属性 Object.defineProperty var cyy={}; Object.defineProperty(cyy,"BASE_NAME"false }) cyy.BASE_NAME="cyy2"; console.log(cyy.BASE_NAME); 可以看到BASE_NAME属性并没有被更改 ?使用Object.defineProperty,并给属性设置writable:false,能让属性不可被修改;但是对象是可以新增属性的 ? 同理,如果是在全局范围内定义一个常量,就可以挂载到window上 Object.defineProperty(window,"BASE_NAME" }) BASE_NAME="cyy2"; console.log(BASE_NAME); ? ? 但是这样定义的常量,依然可以新增属性 下面代码是给window对象的BASE_NAME属性设置了不可修改,但是还是可以给window对象上新增属性 Object.defineProperty(window,1)">
})
window.a=1;
console.log(window.a);
? ? 可以使用Object.seal防止属性被扩展 Object.defineProperty(window,1)"> }) Object.seal(BASE_NAME);防止常量的属性被修改 BASE_NAME.a=1; console.log(BASE_NAME); console.log(BASE_NAME.a); ? ? Object.seal能够防止属性被扩展,但是已经存在的属性,值是可以修改的 var cyy={a:1}; Object.seal(cyy); console.log(cyy); cyy.b=2不能扩展,没有b属性 cyy.a=3属性能被修改,a被改变 ? ? 如果想要禁止属性被修改,还是使用Object.defineProperty }; 禁止修改cyy对象的a属性 Object.defineProperty(cyy,"a" }) Object.seal(cyy); console.log(cyy); cyy.a=3属性不能被修改 ? ? 也就是说,Object.defineProperty和Object.seal结合使用,可以达到Object.freeze的效果 在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); 补充:里面每一行undefined是console.log()执行之后的返回值。 log()本质上是一个函数,函数中如果没有设置return返回值,默认返回undefined。 这个不用管,不是代码的问题,忽略这个undefined,只看前面输出的内容即可 ? hasOwnProperty 判断属性是原型上的属性,还是自身的属性 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]); } } ? ? 数组使用自定义的仿freeze方法 }) } } Object.seal(obj); } }) const cyy=[]; Object.myfreeze(cyy); ? ? 但是,如果对象的属性值又是一个对象的话,那这个对象的属性值还是可以被修改的 }) } } Object.seal(obj); } }) } } Object.myfreeze(cyy); ? ? ? 需要使用递归来解决 }) } 如果属性值是对象,则再次进行遍历 if(obj[i] instanceof Object){ Object.myfreeze(obj[i]); } } Object.seal(obj); } }) } } Object.myfreeze(cyy); ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |