【JS】对象方法(工作常用)

文章目录

    • 转数组(常用)
      • 枚举键值对(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种,数据属性和访问器属性
  • 数据属性有:configurableenumerablewritablevalue
  • 访问器属性有:configurableenumerableget()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

http://www.niftyadmin.cn/n/509299.html

相关文章

【JS】事件详解(使用手册)

文章目录一、事件绑定1.1、HTML的 on- 属性1.2、元素的 .on 属性1.3、事件监听addEventListener(绑定事件)removeEventListener(移除事件)dispatchEvent(触发事件)二、事件传播2.1、事件执行机制2.2、冒泡、…

vue中的computed计算属性

computed:相当于method一样,可以当做方法执行,返回function内return的值赋值在DOM上。但是多个{{}}(模板语法)使用了computed,computed内的function也只执行一次。仅当function内涉及到Vue实例绑定的data的值的改变,fu…

锚点跳转(vue)

目录 a标签href属性 scrollTop keep-alive属性缓存 scrollIntoView()方法 a标签href属性 利用a标记的herf属性和id属性来完成跳转,a标记的herf属性值等于想要跳转去的div的id属性的值。 这种方法的缺点是点击锚点之后,浏览器的URL会发生变化&#x…

vue 安装 bootstrap(vue安装JQuery)

vue项目中使用bootstrap的时候需要安装jquery,bootstrap,并配置,为什么要安装jquery呢,来看bootstrap官网的一段介绍 Bootstrap 中的许多组件需要依赖 JavaScript 才能运行。具体来说,他们依赖的是 jQuery、Popper.js …

JQuery Ajax方法常用参数详解

type: 表示发送请求的类型,string类型,有 GET POST PUT DELETE,最常用的就是GET POST,GET一般用于从服务器端获取数据,POST一般用于向服务器端发送数据。 (简述二者的不同点:GET当然也可以…

forEach()与each()方法的区别

forEach()为JavaScript(ES5)的方法,而each()方法是JQuery的方法。 forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。 注意: forEach() 对于空数组是不会执行回调函数的。 forEach()的回调函数有三个参数,index,v…

window onload和$(document).ready()及DOMContentLoaded的区别(DOM加载完毕前后调用)

这两个函数的差别就在于调用的时机不同, 一般情况一个页面响应加载的顺序是:域名解析-加载html-加载js和css-加载图片等其他信息。 在日常开发中我们经常需要获取页面的元素进行操作,而在编写代码的时候为了代码易读性我们会将js代码放在一…

浏览器对象详解(BOM)

在进行开发的时很多时候需要使用到浏览器对象,通过学习对浏览器对象有了一个大概了解,这里总结一下。 目录 window navigator screen location document history window window对象充当全局作用域,同时也代表浏览器窗口。 属性&#…