lakeiedward's lakeiedward's
首页
标签
  • UI组件库

    • vue-luckyui (opens new window)
    • vue-luckyui文档 (opens new window)
  • 若依页面分层工具

    • ry-layer-page (opens new window)
    • ry-layer-page文档 (opens new window)
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 书单
    • 关于
掘金 (opens new window)
GitHub (opens new window)

lakeiedward

首页
标签
  • UI组件库

    • vue-luckyui (opens new window)
    • vue-luckyui文档 (opens new window)
  • 若依页面分层工具

    • ry-layer-page (opens new window)
    • ry-layer-page文档 (opens new window)
  • 本站

    • 分类
    • 标签
    • 归档
  • 我的

    • 收藏
    • 书单
    • 关于
掘金 (opens new window)
GitHub (opens new window)
  • 「Object.defineProperty」 深入浅出

    • Object.defineProperty是什么?
      • 语法
        • 示例
          • 返回值
          • 添加新的属性
          • get和set
          • 描作符存在异常的情况
          • 继承
        • 与Object.defineProperties的区别
          • Object.defineProperties语法
          • 区别
        • 经典面试题
        lakeiedward
        2022-12-02
        前端技术
        目录

        「Object.defineProperty」 深入浅出

        # Object.defineProperty是什么?

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

        # 语法

        Object.defineProperty(obj, prop, descriptor)
        
        1

        参数

        • obj

          要定义属性的对象。

        • prop

          要定义或修改的属性的名称。

        • descriptor

          要定义或修改的属性描述符。

        返回值

        • 被传递给函数的对象。

        # 示例

        # 返回值

         let obj1 = {
           name: "张三",
         };
         Object.defineProperty(obj1, "name", {
           value: "李四",
         });
         console.log(obj1);//{name: '李四'}
        
        1
        2
        3
        4
        5
        6
        7

        # 添加新的属性

        • configurable 可配置的
        • writable 可写的
        • enumerable 可枚举的

        这仨属性是默认是false的 让我们先来演示一遍。

        let obj1 = {
          name: "张三",
        };
        Object.defineProperty(obj1, "age", {
          value: 24,
          configurable: false,
          writable: false,
          enumerable: false,
        });
        console.log(obj1); //{name: '张三', age: 24}
        //修改属性
        obj1.age = 26;
        console.log(obj1); //{name: '张三', age: 24}
        //删除属性
        delete obj1.age;
        console.log(obj1); //{name: '张三', age: 24}
        //for in 遍历
        for (let i in obj1) {
          console.log(obj1[i]); //只打印了张三
        }
        //通过Object.key()来获取键 获取不到
        console.log(Object.keys(obj1)); //['name']
        
        //如果我们就是想获取里面的属性名怎么办呢  可以通过getOwnPropertyNames来获取自身的属性
        console.log(Object.getOwnPropertyNames(obj1)); //['name', 'age']
        
        //或者我们用来判断自身有没有age这个属性 可以通过hasOwnProperty来判断是否存在
        console.log(obj1.hasOwnProperty("age")); //true
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28

        这仨设置为true重复上面操作,发现都是你想要的结果了。

        # get和set

        因为get和set的劫持 增加了操作的灵活性,可以在get、set方法里进行一些操作。

        let obj1 = {
          name: "张三",
        };
        let value = null;
        Object.defineProperty(obj1, "name", {
          get() {
            console.log("get!");
            return value;
          },
          set(newVal) {
            console.log("set!");
            value = newVal;
          },
        });
        obj1.name;//get!
        obj1.name = "李四";// 'set!'
        console.log(obj1.name); //李四
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17

        下面的例子展示了如何实现一个自存档对象。当设置temperature 属性时,archive 数组会收到日志条目。

        function Archiver() {
          var temperature = null;
          var archive = [];
          Object.defineProperty(this, "temperature", {
            get() {
              return temperature;
            },
            set(value) {
              temperature = value;
              archive.push(temperature);
            },
          });
          this.getArchive = function () {
            return archive;
          };
        }
        var arc = new Archiver();
        arc.temperature = 11;
        arc.temperature = 12;
        console.log(arc.getArchive()); // [11, 12]
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20

        # 描作符存在异常的情况

        如果一个描述符同时拥有value 或 writable 和 get 或 set 键,则会产生一个异常。

        • 也就说value或writable出现的地方,get或set都不能出现
        • get或set出现的地方,value或writable都不能出现
        • 否则就会抛出一个异常
        let obj1 = {};
        Object.defineProperty(obj1, "name", {
          value: "张三",
          get() {},
        });
        //Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute
        
        1
        2
        3
        4
        5
        6

        # 继承

        一个不可写的属性被继承的话 继承过来之后还是不可写!

        function Person() {}
        Person.prototype.name = "张三";
        Object.defineProperty(Person.prototype, "age", {
          writable: false,
          value: 8,
        });
        let p1 = new Person();
        p1.name = "李四";
        p1.age = 10;
        p1.hobby = "Games";
        console.log(p1); //{name: '李四', hobby: 'Games'}
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11

        # 与Object.defineProperties的区别

        # Object.defineProperties语法

        该方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象,和Object.defineProperty类似,但参数不同

        Object.defineProperties(obj, props)
        
        1

        # 区别

        Object.defineProperties可以操作一个对象新增或修改多个属性

        let sample1 = {};
        Object.defineProperties(sample1, {
          prop1: {
            value: "Jerry",
            configurable: false,
            writable: false,
            enumerable: false,
          },
          prop2: {
            value: "Tom",
            configurable: false,
            writable: false,
            enumerable: false,
          },
        });
        sample1.prop1 = "Nacy";
        sample1.prop2 = "Nacy";
        console.log(sample1.prop1); //Jerry
        console.log(sample1.prop2); //Tom
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19

        # 经典面试题

        请在控制台打印'今天吃🍔'

        if (a === 1 && a === 2 && a === 3) {
          console.log("success");
        }
        
        1
        2
        3
        答案
        let i = 1;
        Object.defineProperty(window, "a", {
          get() {
            return i++;
          },
        });
        
        每次调用a的时候都会走到get方法里面,返回i++
        
        if (a === 1 && a === 2 && a === 3) {
          console.log("今天吃🍔");
        }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        #JS
        上次更新: 2022/12/21, 14:57:33
        Theme by Vdoing | Copyright © 2017-2023 lakeiedward | blog 皖ICP备2023006581号-1
        • 跟随系统
        • 浅色模式
        • 深色模式
        • 阅读模式