都2022年了你不会还没搞懂JS Object API吧

简介: JS Object在我们平时的工作中用得并不多,但是也是我们前端必须掌握的一个知识点。今天请跟随笔者的步伐再来温习一遍。

image.png

文章里的每个案例都是我亲自编写并验证的,建议阅读文章时,可以在浏览器执行案例,会更有利于理解。

Object.create(proto,[propertiesObject])

Object.create() 方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__,返回一个新对象,带着指定的原型对象和属性。

注意如果proto参数不是null或非原始包装对象,则抛出一个TypeError异常。

propertiesObject是一个对象,key为属性名,value是一个对象,是该属性的描述符,默认值valueundefinedwritable、enumerable、configurable默认值都是false

const obj = Object.create({msg: '我是原型'}, {name: {
  value: undefined,
  writable: false,
  configurable: false,
  enumerable: false
}})

除了指定value、writable、enumerable、configurable外我们还可以指定get/set方法,如果指定了get/set方法就不能再定义value/writable了,因为它们的意义是一样的。

Object.getOwnPropertyDescriptor(obj, property)

Object.getOwnPropertyDescriptor(obj, property) 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)。

{
  value: "randy", // 属性值
  writable: true, // 是否能修改
  enumerable: true, // 是否枚举 就是能否遍历出来
  configurable: false, // 该属性描述符是否可以被改变并且该属性是否可以被删除
},

writablefalse时不能修改该属性的值。obj.name = 'xxx'Object.defineProperty(obj, "name", {value: 'demi'})都不可以。

enumerablefalse 时,不能进行遍历。

configurablefalse时,属性不能被删除。并且enumerable、configurable不能被修改。writable能改变,但是只能由true改为falsevalue能不能改变由writable决定。

Object.getOwnPropertyDescriptors(obj)

Object.getOwnPropertyDescriptors(obj) 方法用来获取一个对象的所有自身属性的描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)。

Object.defineProperty(obj, property, propertiesObject)

Object.defineProperty(obj, property, propertiesObject) 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

Object.defineProperties(obj, propertiesObject)

Object.defineProperties(obj, propertiesObject) 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

Object.entries(obj)

Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,其排列与用 for...in循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。

Object.keys(obj)

Object.keys(obj) 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。

Object.values(obj)

Object.values()方法返回一个给定对象自身可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 (区别在于 for-in 循环枚举原型链中的属性)。

Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames(obj) 方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性,但不包括Symbol值作为名称的属性和原型链上的属性)组成的数组。

Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols(obj) 方法返回一个给定对象自身的所有Symbol属性的数组。并且不管该Symbol属性是否是可枚举,都能遍历出来。

obj.hasOwnProperty(prop)

obj.hasOwnProperty(prop) 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。

这个方法可以用来检测一个对象是否含有特定的自身属性;和 in 运算符不同,该方法会忽略掉那些从原型链上继承到的属性。

obj.propertyIsEnumerable(prop)

obj.propertyIsEnumerable(prop) 方法返回一个布尔值,表示指定的属性是否可枚举。

Object.getPrototypeOf(obj)

Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。

obj1.isPrototypeOf(obj2)

isPrototypeOf() 方法用于测试一个对象是否是另一个对象的原型。

isPrototypeOf() 与 instanceof运算符不同。isPrototypeOf()是直接判断,而instanceof会通过原型链层层递归判断。

Object.setPrototypeOf(obj, prototype)

Object.setPrototypeOf(obj, prototype)方法设置一个指定的对象的原型 ( 即内部[[Prototype]]属性)`。

实例1

const proto = { msg: "原型" };

const obj = Object.create(proto, {
  // value的默认值是undefined,writable、enumerable、configurable、默认值都是false
  name: {
    // value: "randy", // 属性值
    // writable: true, // 是否能修改
    // enumerable: true, // 是否枚举 就是能否遍历出来
    // configurable: true, // 该属性描述符是否可以被改变并且该属性是否可以被删除
  },
  [Symbol("a")]: {
    // value: "symboltest",
    // writable: true,
    // enumerable: true,
    // configurable: true,
  },
});

// 这种赋值方式 writable、enumerable、configurable、默认值都是true
obj.age = 24;

console.log(obj); // {age: 24, name: undefined, Symbol(a): undefined}
// Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。
console.log(Object.getOwnPropertyDescriptor(obj, "name")); // {configurable: false,enumerable: false,value: undefined,writable: false}
// Object.getOwnPropertyDescriptors() 方法用来获取一个对象的所有自身属性的描述符。
// age: {value: 24, writable: true, enumerable: true, configurable: true}
// name: {value: undefined, writable: false, enumerable: false, configurable: false}
// Symbol(a): {value: undefined, writable: false, enumerable: false, configurable: false}
console.log(Object.getOwnPropertyDescriptors(obj));

// writable为false的情况下 修改无效
obj.name = "demi";
// configurable 为false的情况下 删除无效
// delete obj.name;

// Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
// configurable 为false的情况下 会报错
// Object.defineProperty(obj, "name", {
//   writable: true,
// });

// Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
// configurable 为false的情况下 会报错
// Object.defineProperties(obj, {
//   name: {
//     writable: true,
//   }
// });

// enumerable为true的情况下 才能进行遍历
Object.keys(obj).forEach((key) => {
  console.log("key:", key); // age
});
Object.values(obj).forEach((value) => {
  console.log("value:", value); // 24
});
Object.entries(obj).forEach((entry) => {
  console.log("entry:", entry); // [age, 24];
});
// 该方法例外 能遍历不可枚举属性 但是不包括Symbol 属性
Object.getOwnPropertyNames(obj).forEach((name) => {
  console.log("name:", name); // name age
});
// 并且不管该`Symbol`属性是否是可枚举,都能遍历出来。
Object.getOwnPropertySymbols(obj).forEach((symbolKey) => {
  console.log("symbol:", symbolKey); // Symbol(a)
});

// 是否拥有某属性
console.log(obj.hasOwnProperty("name")); // true
console.log(obj.hasOwnProperty("msg")); // false

// 是否可枚举
console.log(obj.propertyIsEnumerable("name")); // false

// 获取原型
console.log(Object.getPrototypeOf(obj)); // {msg: '原型'}

// 某对象是否是某对象的原型
console.log(proto.isPrototypeOf(obj)); // true

// 设置更新原型
Object.setPrototypeOf(obj, null);
console.log(Object.getPrototypeOf(obj)); // null

console.log(obj); // {age: 24, name: undefined, Symbol(a): undefined}

Object.seal(obj)

Object.seal(obj)方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。

也就是将configurable置为了false。只能修改已有属性和遍历。不能修改描述符和删除属性。

Object.isSealed(obj)

Object.isSealed(obj)方法判断一个对象是否被密封。

Object.isExtensible(obj)

Object.isExtensible() 方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

实例2

const obj6 = { name: "demi" };
// {name: {value: 'demi', writable: true, enumerable: true, configurable: true}}
console.log(
  "getOwnPropertyDescriptors: ",
  Object.getOwnPropertyDescriptors(obj6)
);
console.log("isSealed: ", Object.isSealed(obj6)); // false
// 对对象进行密封
Object.seal(obj6);
console.log("isSealed: ", Object.isSealed(obj6)); // true
// {name: {value: 'demi', writable: true, enumerable: true, configurable: false}}
console.log(
  "getOwnPropertyDescriptors: ",
  Object.getOwnPropertyDescriptors(obj6)
);
// configurable置为了false 所以不能修改该对象已有属性的可枚举性、可配置性,也不能删除已有属性
// 可写性writable只能由true变为false
// Object.defineProperty(obj6, "name", {
//   writable: false,
//   enumerable: false,
//   configurable: false,
// });
delete obj6.name; // 不能删除值
obj6.phone = "17673485272"; // 不能添加新属性
obj6.name = "randy"; // 能修改以前是可写的值

console.log("seal: ", obj6); // {name: 'randy'}

// false
console.log(
  "isExtensible: ",
  Object.isExtensible(obj6),
  "密封的对象不能扩展"
);

Object.freeze(obj)

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。

也就是将configurablewritable置为了false。只能遍历。

Object.isFrozen(obj)

Object.isFrozen(obj)方法判断一个对象是否被冻结。

实例3

const obj5 = { name: "demi" };
// {name: {value: 'demi', writable: true, enumerable: true, configurable: true}}
console.log(
  "getOwnPropertyDescriptors: ",
  Object.getOwnPropertyDescriptors(obj5)
);
console.log("isFrozen: ", Object.isFrozen(obj5)); // false
// 冻结
Object.freeze(obj5);
console.log("isFrozen: ", Object.isFrozen(obj5)); // true
// {name: {value: 'demi', writable: false, enumerable: true, configurable: false}}
console.log(
  "getOwnPropertyDescriptors: ",
  Object.getOwnPropertyDescriptors(obj5)
);
obj5.age = 25; // 不能添加属性
obj5.name = "randy"; // 不能修改属性
delete obj5.name; // 不能删除属性
// configurable置为了false 不能修改该对象已有属性的可枚举性、可配置性、可写性,也不能删除已有属性
// Object.defineProperty(obj5, "name", {
//   writable: false,
//   enumerable: false,
//   configurable: false,
// });
console.log("freeze: ", obj5); // {name: 'demi'}

// false
console.log(
  "isExtensible: ",
  Object.isExtensible(obj5),
  "冻结的对象不能扩展"
);

Object.assign(target, ...sources)

这个方法在笔者前面的文章赋值拷贝、浅拷贝、深拷贝已经介绍过了,该方法是一个浅拷贝方法,并且会改变原对象。

Object.assign(target, ...sources) 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。

如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。

实例4

const obj2 = { name: "demi", phone: "17673485272" };
const obj3 = { name: "tom", address: "上海" };
const obj4 = { name: "jack", age: 24 };
console.log(Object.assign(obj2, obj3, obj4)); // {name: 'jack', phone: '17673485272', address: '上海', age: 24}
console.log(obj2); // {name: 'jack', phone: '17673485272', address: '上海', age: 24}

Object.preventExtensions(obj)

Object.preventExtensions()方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。

该方法只是控制对象不能再添加新属性,并不会像密封、冻结一样修改属性描述符。

实例5

const obj7 = { name: "amy" };
// {name: {value: 'amy', writable: true, enumerable: true, configurable: true}}
console.log(
  "getOwnPropertyDescriptors: ",
  Object.getOwnPropertyDescriptors(obj7)
);
Object.preventExtensions(obj7);
// {name: {value: 'amy', writable: true, enumerable: true, configurable: true}}
console.log(
  "getOwnPropertyDescriptors: ",
  Object.getOwnPropertyDescriptors(obj7)
);

obj7.age = 24; // 不能新增
obj7.name = "amy2"; //能修改
// delete obj7.name; //能删除

console.log(
  "preventExtensions isExtensible: ",
  Object.isExtensible(obj7),
  "阻止对象扩展后,对象不能扩展"
); // false

console.log("preventExtensions: ", obj7); // {name: 'amy2'}

Object.fromEntries(entries)

Object.fromEntries(entries) 方法把键值对列表转换为一个对象。

实例6

const entries = new Map([
  ['name', 'randy'],
  ['age', 24]
]);

const obj8 = Object.fromEntries(entries);

console.log(obj8); // { name: "randy", age: 24 }

系列文章

都2022年了你不会还没搞懂JS数据类型吧

都2022年了你不会还没搞懂JS原型和继承吧

都2022年了你不会还没搞懂JS赋值拷贝、浅拷贝、深拷贝吧

都2022年了你不会还没搞懂对象数组的遍历吧

都2022年了你不会还没搞懂this吧

都2022年了你不会还没搞懂JS Object API吧

都2022年了你不会还没搞懂js垃圾回收和内存泄露吧

都2022年你不会还没搞懂js执行上下文和事件循环机制吧

都2022年了你不会还没搞懂js中的事件吧

都2020年了你不会还没搞懂js异步编程吧

参考文章

MDN Object章节

后记

感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!

相关文章
|
8天前
|
JSON JavaScript API
深入浅出Node.js:从零开始构建RESTful API
【10月更文挑战第39天】 在数字化时代的浪潮中,API(应用程序编程接口)已成为连接不同软件应用的桥梁。本文将带领读者从零基础出发,逐步深入Node.js的世界,最终实现一个功能完备的RESTful API。通过实践,我们将探索如何利用Node.js的异步特性和强大的生态系统来构建高效、可扩展的服务。准备好迎接代码和概念的碰撞,一起解锁后端开发的新篇章。
|
17天前
|
设计模式 JavaScript 前端开发
js中new和object.creat区别
【10月更文挑战第29天】`new` 关键字和 `Object.create()` 方法在创建对象的方式、原型链继承、属性初始化以及适用场景等方面都存在差异。在实际开发中,需要根据具体的需求和设计模式来选择合适的方法来创建对象。
|
19天前
|
JavaScript 中间件 API
Node.js进阶:Koa框架下的RESTful API设计与实现
【10月更文挑战第28天】本文介绍了如何在Koa框架下设计与实现RESTful API。首先概述了Koa框架的特点,接着讲解了RESTful API的设计原则,包括无状态和统一接口。最后,通过一个简单的博客系统示例,详细展示了如何使用Koa和koa-router实现常见的CRUD操作,包括获取、创建、更新和删除文章。
36 4
|
12天前
|
JavaScript 前端开发 NoSQL
深入浅出:使用Node.js构建RESTful API
【10月更文挑战第35天】在数字时代的浪潮中,后端技术如同海洋中稳固的灯塔,为前端应用提供数据和逻辑支撑。本文旨在通过浅显易懂的方式,带领读者了解如何利用Node.js这一强大的后端平台,搭建一个高效、可靠的RESTful API。我们将从基础概念入手,逐步深入到代码实践,最终实现一个简单的API示例。这不仅是对技术的探索,也是对知识传递方式的一次创新尝试。让我们一起启航,探索Node.js的奥秘,解锁后端开发的无限可能。
|
1月前
|
JavaScript 前端开发 大数据
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
在JavaScript中,Object.assign()方法或展开语法(...)来合并对象,Object.freeze()方法来冻结对象,防止对象被修改
18 0
|
1月前
|
JSON JavaScript 前端开发
使用JavaScript和Node.js构建简单的RESTful API服务器
【10月更文挑战第12天】使用JavaScript和Node.js构建简单的RESTful API服务器
17 0
|
15天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
55 4
|
1月前
|
Java
Java Object 类详解
在 Java 中,`Object` 类是所有类的根类,每个 Java 类都直接或间接继承自 `Object`。作为所有类的超类,`Object` 定义了若干基本方法,如 `equals`、`hashCode`、`toString` 等,这些方法在所有对象中均可使用。通过重写这些方法,可以实现基于内容的比较、生成有意义的字符串表示以及确保哈希码的一致性。此外,`Object` 还提供了 `clone`、`getClass`、`notify`、`notifyAll` 和 `wait` 等方法,支持对象克隆、反射机制及线程同步。理解和重写这些方法有助于提升 Java 代码的可读性和可维护性。
|
3月前
|
Java
【Java基础面试二十】、介绍一下Object类中的方法
这篇文章介绍了Java中Object类的常用方法,包括`getClass()`、`equals()`、`hashCode()`、`toString()`、`wait()`、`notify()`、`notifyAll()`和`clone()`,并提到了不推荐使用的`finalize()`方法。
【Java基础面试二十】、介绍一下Object类中的方法
|
2月前
|
Python
类与面向对象编程(Object-Oriented Programming, OOP)
类与面向对象编程(Object-Oriented Programming, OOP)
下一篇
无影云桌面