logologo
  • WebUI
  • JavaScript
  • TypeScript
  • C++
  • ··
    • C
    • Rust
    • Python
    • Cangjie
    • SQL
    • Design
    概述
    常见的数据结构
    ecmascript相关
    enumerable
    Object 内部实现
    sameValue 算法
    unicode
    语法设计
    声明
    表达式
    模块
    语句
    严格模式
    类型系统
    Array
    typedArray
    Map
    Number
    Object
    Set
    String
    结构化
    基本的组织元素
    动态性
    并发性
    范式
    函数式
    函数的行为
    闭包
    函数
    从运算式语言到函数式语言
    语言的多范式

    Last Updated: 11/30/2025, 3:14:53 PM

    Previous pageNumberNext pageSet

    #Object

    图标说明
    - 💥 (sideEffect,该方法有副作用)
    - 🗝️ (support String key,该方法的键名支持`String`数据类型)
    - 🔑 (support Symbol key,该方法的键名支持`Symbol`数据类型)
    - ⛓️ (use prototype chain ,该方法使用了原型链条)
        - 遍历原型对象及祖先原型对象时,需要顺着原型链向上

    #实例的创建和状态

    实例的创建

    // 函数式
    Object(any); // Object === Object.prototype.constructor
    // 面向对象
    new Object(any); // 返回any值对应的包装对象。使用 [new + 类型对象] 这样的面向对象范式
    Object.create(null, propDescriptors) // 使用 [对象.属性] 这样的面向对象范式
    // 字面量
    const object = {}; // 最常用
    // object.constructor === Object // true

    实例的内部属性决定其状态

    ecma外部方法内部属性属性描述符表现说明
    --[[Extensible]]为true-可以扩展新属性
    5Object.preventExtensions(instance💥)[[Extensible]]为false-不能扩展新属性
    5Object.seal(instance💥)[[Extensible]]为false,
    [[sealed]]为true
    全部属性描述符改为configurable:false不能扩展新属性、不能删除属性、不能重新定义属性
    总结,若可写仍然可写,其他都不行
    5Object.freeze(instance💥)[[Extensible]]为false,
    [[frozen]]为true
    全部属性描述符改为configurable:false
    writable:false
    不能扩展新属性,实例及其属性只读
    test
    import { describe,test,expect } from "@rstest/core";
    const {
      preventExtensions, seal, freeze,
      isExtensible, isSealed, isFrozen,
      getOwnPropertyDescriptor,
    } = Object;
    
    /**
     * 实验目标
     * - 实例的内部属性的检测
     * 实验结论
     * - 状态`[[extensible]] === true`: isExtensible 为 true
     * - 状态`[[sealed]] === true`: isExtensible 为 false,isSealed 为 true,isFrozen 为 false
     * - 状态`[[frozen]] === true`: isExtensible 为 false,isSealed 和 isFrozen 为 true
     */
    
    describe("实例状态的检测方法", () => {
      
      test("[[extensible]] === true", () => {
        const object = { k: "v" };
        expect(isExtensible(object)).toBeTruthy();
        expect(isSealed(object)).not.toBeTruthy();
        expect(isFrozen(object)).not.toBeTruthy();
      });
      
      test("[[extensible]] === false", () => {
        const object = { k: "v" };
        preventExtensions(object);
        expect(isExtensible(object)).not.toBeTruthy();
        expect(isSealed(object)).not.toBeTruthy();
        expect(isFrozen(object)).not.toBeTruthy();
      });
      
      test("[[sealed]] === true", () => {
        const object = { k: "v" };
        seal(object);
        expect(isExtensible(object)).not.toBeTruthy();
        expect(isSealed(object)).toBeTruthy();
        expect(isFrozen(object)).not.toBeTruthy();
      });
      
      test("[[frozen]] === true", () => {
        const object = { k: "v" };
        freeze(object);
        expect(isExtensible(object)).not.toBeTruthy();
        expect(isSealed(object)).toBeTruthy();
        expect(isFrozen(object)).toBeTruthy();
      });
    });
    
    /**
     * 实验目标
     * - 实例内部属性决定了属性描述符
     * 实验结论
     * - 状态`[[extensible]] === true`: 默认态,允许在实例上添加新属性
     * - 状态`[[extensible]] === false`: 阻止在实例上添加新属性,不改变存量属性们的属性描述符
     * - 状态`[[sealed]] === true`: 阻止在实例上添加新属性,修改存量属性们的 configurable 为 false,
     * - 状态`[[frozen]] === true`: 阻止在实例上添加新属性,修改存量属性们的 configurable 和 writable 为 false,
     */
    describe("实例状态的属性标识符", () => {
      
      test("[[extensible]] === true", () => {
        const object = { k: "v" };
        const propDescriptor = getOwnPropertyDescriptor(object, "k");
        const assert = {configurable: true, writable: true,};
        expect(propDescriptor).toMatchObject(assert);
      });
      
      test("[[extensible]] === false", () => {
        const object = { k: "v" };
        preventExtensions(object);
        const propDescriptor = getOwnPropertyDescriptor(object, "k");
        const assert = {configurable: true, writable: true,};
        expect(propDescriptor).toMatchObject(assert);
      });
      
      test("[[sealed]] === true", () => {
        const object = { k: "v" };
        seal(object);
        const propDescriptor = getOwnPropertyDescriptor(object, "k");
        const assert = {configurable: false, writable: true,};
        expect(propDescriptor).toMatchObject(assert);
      });
      
      test("[[frozen]] === true", () => {
        const object = { k: "v" };
        freeze(object);
        const propDescriptor = getOwnPropertyDescriptor(object, "k");
        const assert = {configurable: false, writable: false,};
        expect(propDescriptor).toMatchObject(assert);
      });
    });

    #属性和属性描述符

    实例属性的特性由属性描述符(集)控制

    属性描述符键可删除/重新定义值可修改键值可被检索
    configurable✅
    writable✅
    enumerable✅
    test
    import { describe,test,expect } from "@rstest/core";
    const {
      preventExtensions, seal, freeze,
      isExtensible, isSealed, isFrozen,
      getOwnPropertyDescriptor, getOwnPropertyDescriptors,
    } = Object;
    
    /**
     * configurable - 是否可配置
     * - 重新定义属性
     * - 删除属性
     */
    describe("属性描述符对属性的影响: configurable", () => {
        const object = {k: "v"}; // configurable: true, writable: true, enumerable: true,
    
        test("configurable:false", () => {
            Object.defineProperty(object, "k", { configurable: false });
    
            expect(() => {
                Object.defineProperty(object, "k", { configurable: true });
            }).toThrow();
            expect(() => {
                delete object.k;
            }).toThrow();
        });
    });
    
    /**
     * writable - 是否可写
     * - 修改属性值
     */
    describe("属性描述符对属性的影响: writable", () => {
        const object = {k: "v"}; // configurable: true, writable: true, enumerable: true,
        test("writable:false", () => {
            Object.defineProperty(object, "k", { writable: false });
            expect(() => {
                object.k = "newV";
            }).toThrow();
            expect(object.k).toBe("v");
        });
    });
    
    /**
     * enumerable - 是否可枚举
     * - for...in/of 语法
     * - Object.keys()等接口
     * - Object.getOwnPropertyNames() 这是特例
     */
    
    describe("属性描述符对属性的影响: enumerable", () => {
        const object = {k: "v"}; // configurable: true, writable: true, enumerable: true,
        test("enumerable:false", () => {
            Object.defineProperty(object, "k", { enumerable: false });
            for(const key in object) {
                // 不会遍历到 k
                expect(key).not.toBe("k");
            }
            expect(Object.keys(object)).toHaveLength(0);
            expect(Object.getOwnPropertyNames(object)).toHaveLength(1); // 无视不可枚举属性
        });
    });

    参数含属性描述符(数据结构)的方法

    ecmaapidescribe
    5🗝️🔑 Object.create(proto[,propDescriptors])创建实例,参数为原型对象和属性描述符集
    5🗝️🔑 Object.defineProperty(instance💥,propName,propDescriptor)(重新)定义属性
    5🗝️🔑 Object.defineProperties(instance💥,propDescriptors)(重新)定义属性集
    5🗝️🔑 Object.getOwnPropertyDescriptor(instance,propName)查询自身的属性描述符
    2017🗝️🔑 Object.getOwnPropertyDescriptors(instance)查询自身的属性描述符集
    1🗝️🔑 Object.prototype.propertyIsEnumerable(propName)自身可枚举属性

    #原型链相关

    原型对象及原型链条相关方法

    ecmaapidescribe
    2015⛓️ Object.getPrototypeOf(instance)获取实例的原型对象
    2015⛓️ Object.setPrototypeOf(instance💥,proto)设置原型对象,会破坏 JS 引擎的优化(例如 V8)导致性能不佳。
    推荐 create 来创建新对象
    2015⛓️ Object.prototype.isPrototypeOf(instance,proto)判断原型对象。相当于proto === Object.prototype.getPrototypeOf(instance)

    #方法-工具

    数据结构转换

    ecmaapidescribe
    2017🗝️ Object.entries(instance)
    Object转为Entries
    2017🗝️🔑 Object.fromEntries(instance)Entries转为Object
    2024Object.groupBy(items,callback)进行分组

    属性操作

    ecmaapidescribe
    2015🔑 Object.getOwnPropertySymbols(instance)获取自身symbol类型的键名数组
    不可枚举属性也会返回
    5🗝️ Object.getOwnPropertyNames(instance)获取自身 String类型的键名数组
    不可枚举属性也返回
    2015🗝️🔑 Object.hasOwn(instance,propName)判断自身属性中有无该属性键名
    3Object.prototype.hasOwnProperty(instance,propName)已废除,推荐Object.hasOwn
    2015🗝️🔑 Object.assign(instance💥, ...sources)分配属性给实例。
    sources列表自右向左逐个读取,然后覆盖实例上原有的属性。
    source的属性是自有的、可枚举的,也可以是 null或undefined
    2017🗝️ Object.keys(instance)返回键名数组
    2017🗝️ Object.values(instance)返回键值数组

    #其他

    ecmaapidescribe
    2015Object.is(value1,value2)“同值相等”(SameValue)判断
    见SameValue
    1Object.prototype.toLocaleString()对象的本地化字符串表示
    参考国际化
    1Object.prototype.toString()对象的字符串表示。内部属性值[[Class]]用于描述一个值的类型[object 类型]。
    用法:Object.prototype.toString.call(any).slice(8,-1) // type
    1Object.prototype.valueOf()取基本类型值