文章目录
- 转数组(常用)
- 枚举键值对(entries)
- 枚举属性名(keys)
- 枚举属性值(values)
- 判断操作
- 删除(delete)
- 判断(in)
- 判断属性名(hasOwnProperty)
- 判断原型链(isPrototypeOf)
- 判断任意值(is)
- 操作对象
- 创建对象(create)
- 合并对象(assign)
- 获取对象原型(getPrototypeOf)
- 设置对象原型(setPrototypeOf)
- 定义属性
- 单个属性(defineProperty)
- 多个属性(defineProperties)
- 获取属性
- 指定描述符(getOwnPropertyDescriptor)
- 所有描述符(getOwnPropertyDescriptors)
- 所有属性名(getOwnPropertyNames)
- 所有的符号(getOwnPropertySymbols)
- 限制对象
- 防扩对象(preventExtensions)
- 封闭对象(seal)
- 冻结对象(freeze)
转数组(常用)
枚举键值对(entries)
Object.entries(obj)
:返回对象内可枚举键值对组成的数组- 描述:
js">1. Object.entries()返回一个数组,其元素是在对象上找到的可枚举键值对。
2. 属性的顺序与通过手动循环对象的属性值所给出的顺序相同。
- 详细用法:
js">const obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
// 类数组对象
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]
// 数组一样的对象与随机键顺序
const anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.entries(anObj)); // [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ]
// getFoo是不可枚举的属性
const myObj = Object.create({}, { getFoo: { value() { return this.foo; } } });
myObj.foo = 'bar';
console.log(Object.entries(myObj)); // [ ['foo', 'bar'] ]
// 非对象参数将被强制转换为对象
console.log(Object.entries('foo')); // [ ['0', 'f'], ['1', 'o'], ['2', 'o'] ]
// 优雅地遍历key-value
const obj = { a: 5, b: 7, c: 9 };
for (const [key, value] of Object.entries(obj)) {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
}
// 使用额外的数组
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});
枚举属性名(keys)
Object.keys(obj)
:返回对象内可枚举属性名组成的数组- 描述:
js">1. Object.keys()返回一个数组,其元素是在对象上找到的可枚举属性名。
2. 这些属性的顺序与手动遍历该对象属性时的一致。
- 详细用法:
js">// 简单数组
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']
// 简单对象
var obj = { acc: 'a', dc: 'b', ac: 'c' };
console.log(Object.keys(obj)); // console: ['acc', 'dc', 'ac']
// 类数组对象
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
// 数组一样的对象与随机键顺序
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']
// getFoo是一个不可枚举的属性
var myObj = Object.create({}, {
getFoo: {
value: function () { return this.foo; }
}
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']
枚举属性值(values)
Object.values(obj)
:返回对象内可枚举属性值组成的数组- 描述:
js">1. Object.values()返回一个数组,其元素是在对象上找到的可枚举属性值。
2. 属性的顺序与通过手动循环对象的属性值所给出的顺序相同。
- 详细用法:
js">var obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]
// 类数组对象
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']
// 数组一样的对象与随机键顺序
// 当我们使用数字键时,该值根据键以数字顺序返回
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']
// getFoo 是不可枚举的属性
var my_obj = Object.create({}, { getFoo: { value: function() { return this.foo; } } });
my_obj.foo = 'bar';
console.log(Object.values(my_obj)); // ['bar']
// 非对象参数将被强制转换为对象
console.log(Object.values('foo')); // ['f', 'o', 'o']
- 其他用法:
// ts枚举类型
enum TackType {
MMDATA2PULSAR = '0',
PULSAR2CH = '1',
TDW2CH = '2',
}
Object.values(TackType).map((item) => {
console.log('枚举遍历:', item)
// 0
// 1
// 2
return {
value: item,
text: textTackType(item),
}
}),
const textTackType = (value: string | TackType) => {
switch (value) {
case TackType.MMDATA2PULSAR:
return 'mmdata2pulsar'
case TackType.PULSAR2CH:
return 'pulsar2ch'
case TackType.TDW2CH:
return 'tdw2ch'
default:
return value
}
}
判断操作
删除(delete)
delete
操作符:用于删除对象的某个属性
js">let aObj = {'a1':'a1','a2':'a2'}; // js 写法
let bObj:any = {'a1':'a1','a2':'a2'}; // ts 写法
// delete obj; // 不能直接删除对象,这里会报错
delete bObj.a1;
console.log(bObj); // 输出{a2: 'a2'};
判断(in)
in
运算符:如果指定的属性在指定的对象或其原型链中,则返回true。
js">const car = { make: 'Honda', model: 'Accord', year: 1998 };
console.log('make' in car);
// expected output: true
delete car.make;
if ('make' in car === false) {
car.make = 'Suzuki';
}
console.log(car.make);
// expected output: "Suzuki"
判断属性名(hasOwnProperty)
hasOwnProperty()
方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。
js">const object1 = {property1 : 42};
console.log(object1.hasOwnProperty('property1')); // true
console.log(object1.hasOwnProperty('toString')); // false
console.log(object1.hasOwnProperty('hasOwnProperty')); // false
判断原型链(isPrototypeOf)
isPrototypeOf()
方法用于查找一个对象是否存在于另一个对象的原型链上。
js">function Foo() {}
function Bar() {}
function Baz() {}
Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);
var baz = new Baz();
console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true
判断任意值(is)
Object.is()
方法:判断两个值是否为同一个值。- 语法:
js">/*
value1: 被比较的第一个值。
value2: 被比较的第二个值。
*/
Object.is(value1, value2);
/* 返回值 */
返回一个 Boolean 类型表示两个参数是否是同一个值。
- 基本用法:
js">Object.is('foo', 'foo'); // true
Object.is(window, window); // true
Object.is('foo', 'bar'); // false
Object.is([], []); // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false
Object.is(null, null); // true
// 特例
Object.is(0, -0); // false
Object.is(0, +0); // true
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true
操作对象
创建对象(create)
Object.create()
方法:创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
。- 语法:
js">/*
proto: 新创建对象的原型对象。
propertiesObject: 可选。需要传入一个对象。
*/
Object.create(proto,[propertiesObject])
/* 返回值 */
返回一个新对象,带着指定的原型对象和属性。
/* 注意事项 */
如果proto参数不是 null 或非原始包装对象,则抛出一个 TypeError 异常
- 基本用法:
js">const person = {
isHuman: false,
printIntroduction: function() {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
me.name = 'Matthew'; // “name”是在“me”上设置的属性,而不是在“person”上设置的属性。
me.isHuman = true; // 继承的属性可以被重写
me.printIntroduction(); // "My name is Matthew. Am I human? true"
合并对象(assign)
Object.assign()
方法:用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。- 语法:
js">/*
target: 目标对象。
sources: 源对象。
*/
Object.assign(target, ...sources)
/* 返回值 */
返回目标对象。
/* 注意事项 */
如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。
后面的源对象的属性将类似地覆盖前面的源对象的属性。
- 复制对象
js">const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
- 合并对象
js">const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };
const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
/* 合并具有相同属性的对象 */
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };
const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
获取对象原型(getPrototypeOf)
Object.getPrototypeOf()
方法:返回指定对象的原型(内部[[Prototype]]
属性的值)- 语法:
js">/*
object: 要返回其原型的对象。。
*/
Object.getPrototypeOf(object)
/* 返回值 */
给定对象的原型。如果没有继承属性,则返回 null 。
- 基本用法
js">var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
var reg = /a/;
Object.getPrototypeOf(reg) === RegExp.prototype; // true
设置对象原型(setPrototypeOf)
不推荐使用,可以使用
Object.create()
来创建带有你想要的[[Prototype]]
的新对象。
Object.setPrototypeOf()
方法:设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或 null。- 语法:
js">/*
object: 要设置其原型的对象。
prototype:该对象的新原型(一个对象 或 null).
*/
Object.setPrototypeOf(obj, prototype)
- 基本用法
js">var dict = Object.setPrototypeOf({}, null);
定义属性
- 属性的特性可分为2种,数据属性和访问器属性
- 数据属性有:
configurable
、enumerable
、writable
、value
- 访问器属性有:
configurable
、enumerable
、get()
、set()
js">1. configurable => 直接定义默认为 true,使用方法定义默认为 false
表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改。
2. enumerable => 直接定义默认为 true,使用方法定义默认为 false
定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。
3. writable => 直接定义默认为 true,使用方法定义默认为 false
设置为 false 时,该属性被称为“不可写的”。它不能被重新赋值。
4. value => 默认为 undefined
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
5. get(){} => 默认为 undefined
获取函数,在读取属性时调用。
4. set(){} => 默认为 undefined
设置函数,在写入属性时调用。
单个属性(defineProperty)
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。- 语法:
js">/*
obj: 要定义属性的对象。
prop: 要定义或修改的属性的名称或 Symbol 。
descriptor: 要定义或修改的属性描述符。
*/
Object.defineProperty(obj, prop, descriptor)
- 基本用法:
js">const object = {};
Object.defineProperty(object, 'property', {
value: 42, // value值
});
console.log(object); // { property: 42}
delete object.property // 删除操作,不生效
console.log(object); // { property: 42}
object1.property1 = 23 // 修改操作,不生效
console.log(object); // { property: 42}
for (let var1 in object1) { // 遍历操作,不生效
console.log(var1); // 无打印
}
1. 原因分析 :
Object.defineProperty(object, 'property', {
value: 42, // value值
});
== 等价于 ==
Object.defineProperty(object, 'property', {
value: 42, // value值
configurable: false, // 是否可删除
enumerable: false, // 是否可遍历
writable: false, // 是否可修改
});
2. 扩展了解 :
let object = {
property: 42
}
== 等价于 ==
Object.defineProperty(object, 'property', {
value: 42, // value值
configurable: true, // 是否可删除
enumerable: true, // 是否可遍历
writable: true, // 是否可修改
});
- 使用获取(
getter
)函数和设置(setter
)函数
js">let book = {
year_: 2017,
edition: 1,
}
Object.defineProperty(book, 'year', {
get(){
return this.year;
},
set(newValue){
if(newValue > 2017){
this.year_ = newValue;
this.edition += 1;
}
}
});
book.year = 2018;
console.log(book.edition) // 2
多个属性(defineProperties)
Object.defineProperties()
方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
js">/*
obj: 要定义属性的对象。
prop: 要定义或修改的属性的名称或 Symbol 加 要定义或修改的属性描述符。
*/
Object.defineProperties(obj, prop)
- 基本用法:
js">const object1:any = {
property1: "property1"
};
Object.defineProperties(object1, {
'property1': {
value: 'ccc',
},
'property2': {
value: 'Hello',
}
});
console.log(object1); // {property1: 'ccc', property2: 'Hello'}
- 使用获取(
getter
)函数和设置(setter
)函数
js">let book = {}
Object.defineProperties(book,{
year_:{
value: 2017,
writable: true
},
edition:{
value: 1,
writable: true
},
year:{
get() {
return this.year_;
},
set(newValue) {
if(newValue > 2017){
// 需设置writable属性,不然无法修改
this.year_ = newValue;
this.edition += 1;
}
}
}
});
book.year = 2018;
console.log(book.edition) // 2
获取属性
指定描述符(getOwnPropertyDescriptor)
Object.getOwnPropertyDescriptor()
方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
js">/*
obj: 需要查找的目标对象。
prop: 目标对象内属性名称
*/
Object.getOwnPropertyDescriptor(obj, prop)
- 基本用法:
js">let book = {}
Object.defineProperties(book,{
year_:{
value: 2017,
writable: true
},
edition:{
value: 1,
writable: true
},
year:{
get() {
return this.year_;
},
set(newValue) {
if(newValue > 2017){
// 需设置writable属性,不然无法修改
this.year_ = newValue;
this.edition += 1;
}
}
}
});
let descriptor = Object.getOwnPropertyDescriptor(book,"year_")
console.log(descriptor.value) // 2017
console.log(descriptor.configurable) // false
console.log(descriptor.writable) // true
console.log(descriptor.enumerable) // false
console.log(typeof descriptor.get) // undefined
console.log(typeof descriptor.set) // undefined
console.log(typeof Object.getOwnPropertyDescriptor(book,"year").set) // function
console.log(typeof Object.getOwnPropertyDescriptor(book,"year").get) // function
所有描述符(getOwnPropertyDescriptors)
Object.getOwnPropertyDescriptors()
方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
js">/*
obj: 需要查找的目标对象。
*/
Object.getOwnPropertyDescriptors(obj)
- 基本用法:
js">let book = {}
Object.defineProperties(book,{
year_:{
value: 2017,
writable: true
},
edition:{
value: 1,
writable: true
},
year:{
get() {
return this.year_;
},
set(newValue) {
if(newValue > 2017){
// 需设置writable属性,不然无法修改
this.year_ = newValue;
this.edition += 1;
}
}
}
});
console.log(Object.getOwnPropertyDescriptors(book))
/*
{
"year_": {
"value": 2017,
"writable": true,
"enumerable": false,
"configurable": false
},
"edition": {
"value": 1,
"writable": true,
"enumerable": false,
"configurable": false
},
"year": {
"enumerable": false,
"configurable": false,
get: ƒ get(),
set: ƒ set(newValue)
}
}
*/
所有属性名(getOwnPropertyNames)
Object.getOwnPropertyNames()
方法:返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
js">/*
obj: 需要查找的对象。
*/
Object.getOwnPropertyNames(obj)
- 基本用法:
js">// 数组
var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr)); // ["0", "1", "2", "length"]
// 对象
var obj = { aa: "a", bb: "b", cc: "c"};
console.log(Object.getOwnPropertyNames(obj)); // ['aa', 'bb', 'cc']
// 类数组对象
var arrObj = { 0: "a", 1: "b", 2: "c"};
console.log(Object.getOwnPropertyNames(arrObj)); // ["0", "1", "2"]
所有的符号(getOwnPropertySymbols)
Object.getOwnPropertySymbols()
方法:返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
js">/*
obj: 需要查找的对象。
*/
Object.getOwnPropertySymbols(obj)
- 基本用法:
js">var obj = {};
var a = Symbol("a");
var b = Symbol.for("b");
obj[a] = "localSymbol";
obj[b] = "globalSymbol";
obj.c = "ccc";
var objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(obj); // {c: 'ccc', Symbol(a): 'localSymbol', Symbol(b): 'globalSymbol'}
console.log(objectSymbols) // [Symbol(a), Symbol(b)]
限制对象
防扩对象(preventExtensions)
-
Object.preventExtensions(obj)
方法:让一个对象变的不可扩展。 -
参数是将要变得不可扩展的对象,返回已经不可扩展的对象
-
什么是不可扩展对象?
js">1. 如果一个对象不能添加新的属性,则这个对象是不可扩展的
2. 但是不可扩展对象的属性可以被删除
3. 该方法使得目标对象的 [[prototype]] 不可变;目标对象的其它属性可变
- 基本用法:
js">const object1:any = {
property1: 42
};
Object.preventExtensions(object1);
try{
object1.property1 = 33; // 可以修改属性值
console.log(object1); // {property1: 33}
delete object1.property1; // 可以删除属性
console.log(object1); // {}
// 以下情况会报错
object1.property2 = 33; // 添加属性报错
}catch(error){
console.log(error) // TypeError: Cannot add property property2, object is not extensible
// 翻译 => 类型错误: 无法添加属性 property2, 对象不可扩展
}
- 详细用法:
js">// Object.preventExtensions将原对象变的不可扩展,并且返回原对象.
var obj = {};
var obj2 = Object.preventExtensions(obj);
obj === obj2; // true
// 字面量方式定义的对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty) //=== true
// ...但可以改变.
Object.preventExtensions(empty);
Object.isExtensible(empty) //=== false
// 使用Object.defineProperty方法为一个不可扩展的对象添加新属性会抛出异常.
var nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // 抛出TypeError异常
// 在严格模式中,为一个不可扩展对象的新属性赋值会抛出TypeError异常.
function fail()
{
"use strict";
nonExtensible.newProperty = "FAIL"; // throws a TypeError
}
fail();
Object.isExtensible(obj)
方法:判断一个对象是否是可扩展的- 参数是被检测的对象,返回一个
Boolean
值 - 示例:
js">// 新对象默认是可扩展的.
var empty = {};
Object.isExtensible(empty); // === true
// ...可以变的不可扩展.
Object.preventExtensions(empty);
Object.isExtensible(empty); // === false
// 密封对象是不可扩展的.
var sealed = Object.seal({});
Object.isExtensible(sealed); // === false
// 冻结对象也是不可扩展.
var frozen = Object.freeze({});
Object.isExtensible(frozen); // === false
封闭对象(seal)
Object.seal(obj)
方法:用来封闭一个对象- 参数是被密封的对象,返回被密封的对象
- 密封一个对象有什么用?
js">1. 让这个对象变的不能添加新属性,不能删除原属性,原属性不能重新定义成为访问器属性
2. 当前属性的值只要原来是可写的就可以改变
3. 不会影响从原型链上继承的属性。但 __proto__ ()属性的值也会不能修改。
- 基本用法:
js">const object1:any = {
property1: 42
};
Object.seal(object1);
try{
object1.property1 = 33; // 可以修改属性值
console.log(object1); // {property1: 33}
// 以下情况会报错
object1.property2 = 33; // 添加属性报错
delete object1.property1; // 删除属性报错
}catch(error){
console.log(error) // TypeError: Cannot add property property2, object is not extensible
// 翻译 => 类型错误: 无法添加属性 property2, 对象不可扩展
}
- 详细用法:
js">var obj = {
prop: function() {},
foo: 'bar'
};
// 可以添加新的属性
// 可以更改或删除现有的属性
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;
var o = Object.seal(obj);
o === obj; // true
Object.isSealed(obj); // === true
// 仍然可以修改密封对象的属性值
obj.foo = 'quux';
// 但是你不能将属性重新定义成为访问器属性
// 反之亦然
Object.defineProperty(obj, 'foo', {
get: function() { return 'g'; }
}); // throws a TypeError
// 除了属性值以外的任何变化,都会失败.
obj.quaxxor = 'the friendly duck';
// 添加属性将会失败
delete obj.foo;
// 删除属性将会失败
// 在严格模式下,这样的尝试将会抛出错误
function fail() {
'use strict';
delete obj.foo; // throws a TypeError
obj.sparky = 'arf'; // throws a TypeError
}
fail();
// 通过Object.defineProperty添加属性将会报错
Object.defineProperty(obj, 'ohai', {
value: 17
}); // throws a TypeError
Object.defineProperty(obj, 'foo', {
value: 'eit'
}); // 通过Object.defineProperty修改属性值
-
Object.isSealed(obj)
方法:判断一个对象是否被密封。 -
参数是被检测的对象,返回一个
Boolean
值 -
如果这个对象是密封的,则返回 true,否则返回 false。
-
示例:
js">// 新建的对象默认不是密封的.
var empty = {};
Object.isSealed(empty); // === false
// 如果你把一个空对象变的不可扩展,则它同时也会变成个密封对象.
Object.preventExtensions(empty);
Object.isSealed(empty); // === true
// 但如果这个对象不是空对象,则它不会变成密封对象,因为密封对象的所有自身属性必须是不可配置的.
var hasProp = { fee: "fie foe fum" };
Object.preventExtensions(hasProp);
Object.isSealed(hasProp); // === false
// 如果把这个属性变的不可配置,则这个属性也就成了密封对象.
Object.defineProperty(hasProp, 'fee', {
configurable: false
});
Object.isSealed(hasProp); // === true
// 最简单的方法来生成一个密封对象,当然是使用Object.seal.
var sealed = {};
Object.seal(sealed);
Object.isSealed(sealed); // === true
// 一个密封对象同时也是不可扩展的.
Object.isExtensible(sealed); // === false
// 一个密封对象也可以是一个冻结对象,但不是必须的.
Object.isFrozen(sealed); // === true ,所有的属性都是不可写的
var s2 = Object.seal({ p: 3 });
Object.isFrozen(s2); // === false, 属性"p"可写
var s3 = Object.seal({ get p() { return 0; } });
Object.isFrozen(s3); // === true ,访问器属性不考虑可写不可写,只考虑是否可配置
冻结对象(freeze)
一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。
Object.freeze(obj)
方法:可以冻结一个对象。- 参数是被冻结的对象,返回被冻结的对象
- 冻结一个对象有什么用?
js">1. 自身属性不能被修改
2. 不能添加新的属性
3. 数据属性的值和访问器属性(有getter和setter)不可更改
4. 不能删除已有属性
- 基本用法:
js">const object1:any = {
property1: 42
};
Object.freeze(object1);
try{
console.log(object1); // {property1: 42}
// 以下情况会报错
object1.property2 = 33; // 添加属性报错
delete object1.property1; // 删除属性报错
object1.property1 = 33; // 修改属性报错
}catch(error){
console.log(error) // TypeError: Cannot add property property2, object is not extensible
// 翻译 => 类型错误: 无法添加属性 property2, 对象不可扩展
}
- 其他用法:
js">const bgNames = Object.freeze({
8: "文本8"
})
const productNames = Object.freeze({
992: "文本992",
559: "文本559",
802: "文本802",
991: "文本991",
340: "文本340",
})
/** 获取静态中文对照 */
function getLabel(index) {
const lzGaia = value.lzGaia
if (!lzGaia[index]) return false
switch (index) {
case 0:
return bgNames[lzGaia[index]] || lzGaia[index]
case 1:
return productNames[lzGaia[index]] || lzGaia[index]
default:
return lzGaia[index]
}
}
- 冻结对象
js">var obj = {
prop: function() {},
foo: 'bar'
};
// 新的属性会被添加, 已存在的属性可能
// 会被修改或移除
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;
// 作为参数传递的对象与返回的对象都被冻结
// 所以不必保存返回的对象(因为两个对象全等)
var o = Object.freeze(obj);
o === obj; // true
Object.isFrozen(obj); // === true
// 现在任何改变都会失效
obj.foo = 'quux'; // 静默地不做任何事
// 静默地不添加此属性
obj.quaxxor = 'the friendly duck';
// 在严格模式,如此行为将抛出 TypeErrors
function fail(){
'use strict';
obj.foo = 'sparky'; // throws a TypeError
delete obj.quaxxor; // 返回true,因为quaxxor属性从来未被添加
obj.sparky = 'arf'; // throws a TypeError
}
fail();
// 试图通过 Object.defineProperty 更改属性
// 下面两个语句都会抛出 TypeError.
Object.defineProperty(obj, 'ohai', { value: 17 });
Object.defineProperty(obj, 'foo', { value: 'eit' });
// 也不能更改原型
// 下面两个语句都会抛出 TypeError.
Object.setPrototypeOf(obj, { x: 20 })
obj.__proto__ = { x: 20 }
- 冻结数组
js">let a = [0];
Object.freeze(a); // 现在数组不能被修改了.
a[0]=1; // fails silently
a.push(2); // fails silently
// 在严格模式下,这种尝试将抛出TypeErrors
function fail() {
"use strict"
a[0] = 1;
a.push(2);
}
fail();
- 浅冻结
js">obj1 = {
internal: {}
};
Object.freeze(obj1);
obj1.internal.a = 'aValue';
obj1.internal.a // 'aValue'
- 深冻结
js">// 深冻结函数.
function deepFreeze(obj) {
// 取回定义在obj上的属性名
var propNames = Object.getOwnPropertyNames(obj);
// 在冻结自身之前冻结属性
propNames.forEach(function(name) {
var prop = obj[name];
// 如果prop是个对象,冻结它
if (typeof prop == 'object' && prop !== null)
deepFreeze(prop);
});
// 冻结自身(no-op if already frozen)
return Object.freeze(obj);
}
obj2 = {
internal: {}
};
deepFreeze(obj2);
obj2.internal.a = 'anotherValue';
obj2.internal.a; // undefined
Object.isFrozen(obj)
方法:判断一个对象是否被冻结。- 参数是被检测的对象,返回一个
Boolean
值 - 示例:
js">// 一个对象默认是可扩展的,所以它也是非冻结的.
Object.isFrozen({}); // === false
// 一个不可扩展的空对象同时也是一个冻结对象.
var vacuouslyFrozen = Object.preventExtensions({});
Object.isFrozen(vacuouslyFrozen) //=== true;
// 一个非空对象默认也是非冻结的.
var oneProp = { p: 42 };
Object.isFrozen(oneProp) //=== false
// 让这个对象变的不可扩展,并不意味着这个对象变成了冻结对象,
// 因为p属性仍然是可以配置的(而且可写的).
Object.preventExtensions(oneProp);
Object.isFrozen(oneProp) //=== false
// 此时,如果删除了这个属性,则它会成为一个冻结对象.
delete oneProp.p;
Object.isFrozen(oneProp) //=== true
// 一个不可扩展的对象,拥有一个不可写但可配置的属性,则它仍然是非冻结的.
var nonWritable = { e: "plep" };
Object.preventExtensions(nonWritable);
Object.defineProperty(nonWritable, "e", { writable: false }); // 变得不可写
Object.isFrozen(nonWritable) //=== false
// 把这个属性改为不可配置,会让这个对象成为冻结对象.
Object.defineProperty(nonWritable, "e", { configurable: false }); // 变得不可配置
Object.isFrozen(nonWritable) //=== true
// 一个不可扩展的对象,拥有一个不可配置但可写的属性,则它仍然是非冻结的.
var nonConfigurable = { release: "the kraken!" };
Object.preventExtensions(nonConfigurable);
Object.defineProperty(nonConfigurable, "release", { configurable: false });
Object.isFrozen(nonConfigurable) //=== false
// 把这个属性改为不可写,会让这个对象成为冻结对象.
Object.defineProperty(nonConfigurable, "release", { writable: false });
Object.isFrozen(nonConfigurable) //=== true
// 一个不可扩展的对象,值拥有一个访问器属性,则它仍然是非冻结的.
var accessor = { get food() { return "yum"; } };
Object.preventExtensions(accessor);
Object.isFrozen(accessor) //=== false
// ...但把这个属性改为不可配置,会让这个对象成为冻结对象.
Object.defineProperty(accessor, "food", { configurable: false });
Object.isFrozen(accessor) //=== true
// 使用Object.freeze是冻结一个对象最方便的方法.
var frozen = { 1: 81 };
Object.isFrozen(frozen) //=== false
Object.freeze(frozen);
Object.isFrozen(frozen) //=== true
// 一个冻结对象也是一个密封对象.
Object.isSealed(frozen) //=== true
// 当然,更是一个不可扩展的对象.
Object.isExtensible(frozen) //=== false