一、Object.freeze()方法來(lái)凍結(jié)對(duì)象,防止對(duì)象被修改
Object.freeze() 是JavaScript中的一個(gè)方法,用于凍結(jié)一個(gè)對(duì)象。被凍結(jié)的對(duì)象不能再被修改。具體來(lái)說(shuō),它做了兩件事情:
防止添加新的屬性:嘗試添加新屬性將失敗,不會(huì)拋出錯(cuò)誤,但新屬性不會(huì)被添加到對(duì)象中。
防止刪除屬性:嘗試刪除對(duì)象的任何屬性都將失敗,不會(huì)拋出錯(cuò)誤。
但請(qǐng)注意,它不會(huì)防止修改對(duì)象已有的屬性值。也就是說(shuō),你仍然可以更改、替換或修改對(duì)象上現(xiàn)有的屬性。
我們都知道const定義基本數(shù)據(jù)類型,這個(gè)值是不可以修改的。那么我們用const定義對(duì)象,可以修改對(duì)象嗎?
const a = 5
// a = 10 // TypeError: Assignment to constant variable.
const obj = {
name: '張三'
}
obj.name = '李四'
console.log(obj) // {name: "李四"}
答案是肯定的。那么如果我們想定義一個(gè)不可被修改的對(duì)象,應(yīng)該怎么辦呢!
那就要用到Object.freeze()了。
它的作用是凍結(jié)一個(gè)對(duì)象,被凍結(jié)的對(duì)象有以下幾個(gè)特性:
- 不能添加新屬性
- 不能刪除已有屬性
- 不能修改已有屬性的值
- 不能修改原型
- 不能修改已有屬性的可枚舉性、可配置性、可寫(xiě)性
1、基本使用
var obj = {
name: '張三',
age: 18,
address: '上海市'
}
obj.__proto__.habit = '運(yùn)動(dòng)'
// 凍結(jié)對(duì)象
Object.freeze(obj)
// 不能添加新屬性
obj.sex = '男'
console.log(obj) // {name: "張三", age: 18, address: "上海市"}
// 不能刪除原有屬性
delete obj.age
console.log(obj) // {name: "張三", age: 18, address: "上海市"}
// 不能修改已有屬性的值
obj.name = '李四'
console.log(obj) // {name: "張三", age: 18, address: "上海市"}
// 不能修改原型
obj.__proto__ = '隨便什么值'
console.log(obj.__proto__) // {habit: "運(yùn)動(dòng)", constructor: ?, __defineGetter__: ?, __defineSetter__: ?, hasOwnProperty: ?, …}
// 不能修改已有屬性的可枚舉性、可配置性、可寫(xiě)性
Object.defineProperty(obj,'address',{ // TypeError: Cannot redefine property: address
enumerable: false,// 表示是否可以枚舉。直接在對(duì)象上定義的屬性,基本默認(rèn)true
configurable: false,// 表示能否通過(guò)delete刪除屬性,能否修改屬性的特性
writable: true// 表示能否修改屬性的值。直接在對(duì)象上定義的屬性,基本默認(rèn)true
})
這里要注意一點(diǎn),Object.freeze()的返回值就是被凍結(jié)的對(duì)象,該對(duì)象完全等于傳入的對(duì)象,所以我們一般不需要接收返回值。上面我們對(duì)對(duì)象進(jìn)行了凍結(jié),那么我們可以凍結(jié)數(shù)組嗎?
2、凍結(jié)數(shù)組
var arr = [1,2,3,4,5]
Object.freeze(arr)
arr[0]='新值'
console.log(arr) // [1, 2, 3, 4, 5]
其實(shí)很容易能想明白,數(shù)組本質(zhì)也就是對(duì)象,只不過(guò)對(duì)象的key是下標(biāo),所以也可以凍結(jié)。如果我的對(duì)象里還有對(duì)象呢,那么凍結(jié)是否依然有效?
2.1、淺凍結(jié)
var obj = {
name: '張三',
info: {
a: 1,
b: 2
}
}
Object.freeze(obj)
obj.name = '李四'
console.log(obj) // {info: {a: 1, b: 2},name: "張三"}
obj.info.a = 66
console.log(obj.info) // {a: 66, b: 2}
可以看到對(duì)象中如果還有對(duì)象的時(shí)候,Object.freeze()失效了。Object.freeze()只支持淺凍結(jié),下面我們封裝一個(gè)深凍結(jié)函數(shù),日后可直接使用
2.1、深凍結(jié)
var obj = {
name: '張三',
info: {
a: 1,
b: 2
}
}
function deepFreeze(obj) {
// 獲取所有屬性
var propNames = Object.getOwnPropertyNames(obj)
// 遍歷
propNames.forEach(item => {
var prop = obj[item]
// 如果某個(gè)屬性的屬性值是對(duì)象,則遞歸調(diào)用
if (prop instanceof Object && prop !== null) {
deepFreeze(prop)
}
})
// 凍結(jié)自身
return Object.freeze(obj)
}
deepFreeze(obj)
obj.name = '李四'
console.log(obj) // {name: "張三", info: {…}}
obj.info.a = 100
console.log(obj.info) // {a: 1, b: 2}
3、應(yīng)用場(chǎng)景
Object.freeze()可以提高性能,如果你有一個(gè)對(duì)象,里面的內(nèi)容特別特別多,而且都是一些靜態(tài)數(shù)據(jù),你確保不會(huì)修改它們,那你其實(shí)可以用Object.freeze()凍結(jié)起來(lái),這樣可以讓性能大幅度提升,提升的效果隨著數(shù)據(jù)量的遞增而遞增。一般什么時(shí)候用呢?對(duì)于純展示的大數(shù)據(jù),都可以使用Object.freeze提升性能。
4、Vue中使用Object.freeze
在vue項(xiàng)目中,data初始化 里面一般會(huì)有很多變量,后續(xù)如果不想使用它,可以使用Object.freeze()。這樣可以避免vue初始化時(shí)候,做一些無(wú)用的操作,從而提高性能。
data(){
return{
list:Object.freeze({'我不需要改變'})
}
}
二、Object.assign()方法或展開(kāi)語(yǔ)法(…)來(lái)合并對(duì)象
在JavaScript中,你可以使用Object.assign()方法或者使用Spread Operator (…) 來(lái)合并對(duì)象。
1、Object.assign()
Object.assign() 靜態(tài)方法將一個(gè)或者多個(gè)源對(duì)象中所有可枚舉的自有屬性復(fù)制到目標(biāo)對(duì)象,并返回修改后的目標(biāo)對(duì)象。
1.1、語(yǔ)法
Object.assign(target, ...sources)
1.2、參數(shù)
-
target:需要應(yīng)用源對(duì)象屬性的目標(biāo)對(duì)象,修改后將作為返回值。
-
sources:一個(gè)或多個(gè)包含要應(yīng)用的屬性的源對(duì)象。
1.3、示例
let name = { name:'sea' },age = { age:15 },person= {}
Object.assign(person,name,age)
console.log(person)
//{ name:'sea',age:15 }
在這個(gè)例子中,Object.assign()方法創(chuàng)建了一個(gè)新的對(duì)象,其屬性是所有傳入對(duì)象的屬性的拷貝。
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// Expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget === target);
// Expected output: true
如果目標(biāo)對(duì)象與源對(duì)象具有相同的鍵(屬性名),則目標(biāo)對(duì)象中的屬性將被源對(duì)象中的屬性覆蓋,后面的源對(duì)象的屬性將類似地覆蓋前面的源對(duì)象的同名屬性。
2、展開(kāi)語(yǔ)法Spread Operator (…)
淺拷貝 (Shallow-cloning,不包含 prototype) 和對(duì)象合并,可以使用更簡(jiǎn)短的展開(kāi)語(yǔ)法。而不必再使用 Object.assign() 方式。
Spread運(yùn)算符也可以用來(lái)合并對(duì)象。它可以將一個(gè)數(shù)組或?qū)ο笳归_(kāi)到一個(gè)函數(shù)或數(shù)組中。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-785684.html
let name = { name:'sea' },age = { age:15 }
let person = { ...name,...age }
console.log(person)
//{ name:'sea',age:15 }
在這個(gè)例子中,Spread Operator (…) 用于擴(kuò)展對(duì)象,所以它復(fù)制了所有對(duì)象的屬性到新的對(duì)象中。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-785684.html
var obj1 = { foo: "bar", x: 42 };
var obj2 = { foo: "baz", y: 13 };
var clonedObj = { ...obj1 };
// 克隆后的對(duì)象:{ foo: "bar", x: 42 }
var mergedObj = { ...obj1, ...obj2 };
// 合并后的對(duì)象:{ foo: "baz", x: 42, y: 13 }
3、區(qū)別
- Object.assign() 函數(shù)會(huì)觸發(fā) setters,而展開(kāi)語(yǔ)法則不會(huì)。
到了這里,關(guān)于在JavaScript中,Object.assign()方法或展開(kāi)語(yǔ)法(...)來(lái)合并對(duì)象,Object.freeze()方法來(lái)凍結(jié)對(duì)象,防止對(duì)象被修改的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!