let和var和const
let
-
不能重复声明
-
不存在变量提升
-
只在作用域内有效
常量
const Name = "kangkang"
NAME = "mary" // 报错
声明时必须被初始化(赋值),一经声明不可改变,常量为引用类型时,不能保证不可变
- 不存在提升
- 不能重复声明
- 只在当前作用域内有效
常量为对象时修改对象里的内容和修改常量的地址变量是不同的,常量对象被定义好意味着常量的地址不可再被改变,但是内容obj.name = 'kangkang'
是可以改变的!!! (基本类型赋值是拷贝值,而引用类型是内存地址赋变量)
const obj = {
name ="kangkang",
age = 21
}
let obj2 = {}
let name ="Jack"
obj = obj2 // 报错
obj.name = name //修改成功 Jack
数组也是一样的
const Arr = []
Arr.push("2")
console.log(Arr) // 2
如何避免常量被修改?
Object.freeze(obj);
方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze()
返回和传入的参数相同的对象。这个方法返回传递的对象,而不是创建一个被冻结的副本。
const Arr = []
Object.freeze(Arr)
Arr.push("2") //报错
console.log(Arr) // []
ES6之前怎么声明常量?
Object.defineProperty(obj, prop, descriptor)
obj
要在其上定义属性的对象
prop
要定义或修改的属性的名称
descriptor
将被定义或修改的属性描述符
属性描述符
对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一;不能同时是两者。
数据描述符和存取描述符均具有以下可选键值:
configurable
当且仅当该属性的 configurable 为 true 时,该属性
描述符
才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。
enumerable
当且仅当该属性的
enumerable
为true
时,该属性才能够出现在对象的枚举属性中。默认为 false。数据描述符同时具有以下可选键值:
value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
writable
当且仅当该属性的
writable
为true
时,value
才能被赋值运算符改变。默认为 false。存取描述符同时具有以下可选键值:
get
一个给属性提供 getter 的方法,如果没有 getter 则为
undefined
。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this
对象(由于继承关系,这里的this
并不一定是定义该属性的对象)。默认为 undefined。
set
一个给属性提供 setter 的方法,如果没有 setter 则为
undefined
。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。默认为 undefined。
返回值
被传递给函数的对象
在ES6中,由于 Symbol类型的特殊性,用Symbol类型的值来做对象的key与常规的定义或修改不同,而
Object.defineProperty
是定义key为Symbol的属性的方法之一。
objce.seal(obj)
方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。返回值是被封闭的对象。(和object.freeze(obj)
区别是他可以对已存在的属性进行修改,阻止添加新属性)
Object.defineProperty(Object,'freezeProfill',{
value: function (obj) {
for( let i in obj) {
if(obj.hasOwnProperty(i)) {
Object.defineProperty(obj,i,{
writable: false
})
}
}
Object.seal(obj)
}
})
const profile = {
name: "kangkang",
age: 25
}
Object.freezeProfill(profile)
// 实现未深层递归的Object.freeze()功能
递归版本
Object.defineProperty(Object,"freezeProfill",{
value: function(obj) {
for(let i in obj) {
console.log(i)
if(obj.hasOwnProperty(i)){
if(!(obj[i] instanceof Object)){
Object.defineProperty(obj,i, {writable : false})
} else {
Object.freezeProfill(obj[i])
}
}
}
Object.seal(obj)
}
})
const obj2 = {
name: "kangkang",
age: 32,
profile: {
adr: "laian"
}
}
Object.freezeProfill(obj2)