• 【JavaScript进阶之旅 ES6篇 第九章】对象密封的四种方式、is()、assign()、取值函数的拷贝


    一、获取getter、setter的函数名

    1、正常方法获取

    const obj = {
    get foo() {},

    set foo(x) {}
    }

    console.log(obj.foo.name); // 会报错

    2、通过Object.getOwnPropertyDescriptor获取

    ● 通过get|set来获取属性名

    const obj = {
    get foo() {},

    set foo(x) {}
    }

    var descriptor = Object.getOwnPropertyDescriptor(obj, ‘foo’);

    console.log(descriptor.get.name); // get foo
    console.log(descriptor.set.name); // set foo

    二、对象密封的四种方式

    1、对象常量

    ● 对象常量:不可修改、不可删除(可以添加属性)
    a. configurable: false
    b. writable: false

    const obj = {};

    Object.defineProperty(obj, ‘a’,{
    configurable: false,
    writable: false,
    });

    obj.b = 1;

    console.log(obj); // {b: 1}

    2、Object.preventExtensions()

    ● 禁用添加属性功能

    const obj = {
    a: 1
    }

    // 将对象密封,禁用对象添加属性功能
    var test = Object.preventExtensions(obj);
    console.log(test === obj); // true

    // 通过点语法添加属性,他的属性描述符都为true
    obj.b = 3;

    // 通过defineProperty添加属性,他的属性描述符都为false
    Object.defineProperty(obj, ‘c’, {
    value: 4
    });

    console.log(obj); // {a: 1}

    ● 严格模式中报错

    ‘use strict’;

    const obj = {};
    Object.preventExtensions(obj);
    obj.b = 1;

    console.log(obj); // 报错

    Object.isExtensible()

    ● 判断对象是否可拓展
    ● 返回值:true|false
    ○ false:不可拓展
    ○ true:可拓展

    console.log(Object.isExtensible()); // false

    3、Object.seal()

    ● 密封对象
    ● 返回值:原对象的引用
    ● 本质是在调用preventExtensions,然后把循环到的属性的描述符configurable设置为false

    Object.isSealed()

    ● 判断该对象是否是密封对象
    ● 返回值:true密封的|false不密封的

    const obj = {};

    Object.seal(obj);

    obj.a = 1;
    console.log(obj); // {}

    console.log(Object.isSealed(obj)); // true

    4、Object.freeze()

    ● 冻结对象
    ● 返回值:原对象的引用

    Object.isFrozen()

    ● 判断该对象是否冻结
    ● 返回值:true是冻结对象|false不是冻结对象

    三、Object.is()

    ● 比较运算符的扩充:判断是否相等

    console.log(NaN === NaN); // false
    console.log(+0 === -0); // true

    console.log(Object.is(NaN, NaN)); // true
    console.log(Object.is(+0, -0); // false

    console.log({} === {}); // false
    console.log(Object.is({}, {})); // false

    四、Object.assign()

    ● 对象的合并
    ● 参数:
    a. tar:目标对象
    b. source:需要合并的对象
    ● 返回值:返回目标对象的引用

    const obj = {a : 1};
    const tar = {};

    const res = Object.assign(tar, obj);
    console.log(res, tar, res === tar); // { a: 1 } { a: 1 } true

    1、合并多个对象

    const obj = {a: 1},
    obj2 = {b: 2},
    obj3 = {c: 3};

    const tar = {};

    Object.assign(tar, obj, obj2, obj3);
    console.log(tar); // { a: 1, b: 2, c: 3 }

    2、会替换已有的属性

    const obj = {a: 1, b: 1},
    obj2 = {b: 2, c: 2},
    obj3 = {c: 3};

    const tar = {};

    Object.assign(tar, obj, obj2, obj3);
    console.log(tar); // { a: 1, b: 2, c: 3 }

    3、参数

    第一个参数

    1. undefined或null没有包装类,无法转换为对象

    Object.assign(null, {a: 1}); // 报错
    Object.assign(undefined, {a: 1}); // 报错

    1. number|string|boolean会转换为对应的包装类

    let res = Object.assign({a: 1}); // {a: 1}

    let res2 = Object.assign(1, {a: 1}); // Number{1, {a: 1}}

    let res3 = Object.assign(‘’, {a: 1}); // String{‘’, {a: 1}}

    let res4 = Object.assign(true, {a: 1}); // Boolean{a: 1}

    第二个参数

    1. 第二个参数传undefined|null不会进行任何处理

    let res = Object.assign({a: 1}, undefined); // {a: 1}

    let res2 = Object.assign({a: 1}, null); // {a: 1}

    1. 第二个参数如果不可可枚举的,不会进行处理

    let res = Object.assign({a: 1}, 1); // {a: 1}

    let res2 = Object.assign({a: 1}, true); // {a: 1}

    1. 第二个参数如果是可枚举的,才会进行拷贝

    let res = Object.assign({a: 1}, ‘1’); // {a: 1, 0: ‘1’}

    let res2 = Object.assign({a: 1}, ‘abc’); // {a: 1, 0: ‘a’, 1: ‘b’, 2: ‘c’}

    第二个参数的本质

    const str = ‘abc’, // 会通过new String()转换为类数组
    bool = true, // 通过new Boolean()转换成[[PrimitiveValue]]的属性,他是不能遍历的
    num = 10; // 同bool

    const res = Object.assign({}, str, bool, num);

    console.log(res); // { ‘0’: ‘a’, ‘1’: ‘b’, ‘2’: ‘c’ }

    4、不可合并继承属性跟不可枚举的属性

    // Object.create创建一个以{foo: 1}为原型的对象
    const obj = Object.create({foo: 1}, {
    bar: {
    value: 2
    },

    baz: {
    value: 3,
    enumerable: true
    }
    });

    const copy = Object.assign({}, obj);
    console.log(copy); // {baz: 3}

    5、原始类型Symbol()值也可以通过assign拷贝

    ● 生成永远不会重复的东西

    let a = Symbol(‘1’),
    b = Symbol(‘1’);

    console.log(a, b); // Symbol(1) Symbol(1)
    console.log(a === b, a == b); // false false

    var test = Object.assign({a: 1}, {
    [Symbol(‘b’)]: 2
    });

    console.log(test); // {a: 1, Symbol(b): 2}

    6、assign是浅拷贝

    ● 只拷贝值,不拷贝地址为浅拷贝

    const obj = {
    a: {
    b: 1
    }
    };

    const obj2 = Object.assign({}, obj);

    obj.a.b = 2;

    console.log(obj); // b跟着修改为2

    7、assign同名属性的替换

    const obj = {
    a: {
    b: 1
    }
    };

    const source = {
    a: {
    c: 2
    }
    }

    const obj2 = Object.assign(obj, source);

    console.log(obj); // 同名属性a跟着修改

    8、assign数组的拷贝

    ● 根据同名属性进行替换

    // 根据数组下标来进行替换
    const arr = Object.assign([1, 2, 3], [4, 5]);

    console.log(arr); // [4, 5, 3]

    9、取值属性get的拷贝

    ● 不会将整个取值函数拷贝

    const source = {
    get foo() {
    return 1;
    }
    };

    const obj = {};

    Object.assign(obj, source);

    console.log(obj); // {foo: 1}

    10、在原型上扩充方法跟属性

    let age = 20;
    function Person() {}

    Object.assign(Person.prototype, {
    eat() {},
    age
    });

    console.log(Person.prototype); // {age: 20, eat: ƒ, constructor: ƒ}

    11、使用assign合并配置默认项

    // 当用户没有配置,那么使用默认配置,用户配置即使用该配置

    const Default = {
    url: {
    Post: ‘www.baidu.com’
    }
    };

    function test(option) {
    option = Object.assign({}, Default, option);
    }

    test(); // {url: {Post: ‘www.baidu.com’}}

    test({
    url: {
    Post: ‘6666’
    }
    }); // {url: {Post: ‘6666’}}

    五、定义对象的多个属性

    1、Object.defineProperties()

    ● 定义一个对象的多个属性
    ● 两个参数
    a. 目标对象
    b. 多个对象

    const obj = {};

    Object.defineProperties(obj, {
    a: {
    value: 1,
    writable: true
    },
    b: {
    value: 2
    }
    });

    console.log(obj); // {a: 1, b: 2}

    2、Object.getOwnPropertyDescriptors()

    ● 获取对象的多个属性的描述符

    console.log(Object.getOwnPropertyDescriptors(obj));
    // {
    // “a”: {
    // “value”: 1,
    // “writable”: true,
    // “enumerable”: false,
    // “configurable”: false
    // },
    // “b”: {
    // “value”: 2,
    // “writable”: false,
    // “enumerable”: false,
    // “configurable”: false
    // }
    // }

    3、set赋值函数的拷贝

    使用Object.assign()是不可以拿到set赋值函数的

    const course = {
    set foo(value) {
    console.log(value);
    }
    };

    const tar = {};

    Object.assign(tar, course);
    console.log(tar); // {foo: undefined}

    set赋值函数的拷贝

    ● 唯一实现方法

    const course = {
    set foo(value) {
    console.log(value);
    }
    };

    const tar = {};

    Object.defineProperties(tar, Object.getOwnPropertyDescriptors(course));

    console.log(Object.getOwnPropertyDescriptor(tar, ‘foo’)); // {get: undefined, enumerable: true, configurable: true, set: ƒ}

    4、浅拷贝对象(克隆对象)

    Object.getPrototypeOf()获取对象的原型

    const obj = {
    a: 1,
    b: {
    c: 2
    }
    }

    const clone = (obj) => Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));

    console.log(clone(obj));
    // {
    // a: 1,
    // b: {
    // c: 2
    // }
    // }

  • 相关阅读:
    计算机毕业设计 基于SpringBoot的智能停车场计费系统的设计与实现 Java实战项目 附源码+文档+视频讲解
    Scala 基础 (四):函数式编程【从基础到高阶应用】
    钢铁行业B2B供应链集采平台:完善供应商管理,健全供应商管理机制
    为什么企业需要视频会议私有部署?
    C语言力扣第32题之最长有效括号。用栈实现
    快应用参数传递
    Linux下的多线程教程
    OpenHarmony 3.1 Beta 样例:使用分布式菜单创建点餐神器
    第六章 图 十、关键路径
    网络安全——自学(黑客)方法
  • 原文地址:https://blog.csdn.net/Lyb__/article/details/125505092