• 对object.defineproperty 的深入理解


    如面试官问你vue中双向数据绑定实现原理是啥? 一句话其实vue中的v-model 底层就是用到就是 object.defineproperty 
    然后继续问你object.defineproperty 是 这么使用和自己这么实现一个双向绑定?
    然后你可沉默一会。。。。 开始一下的装逼之路
     
    首先 我们看看这这么使用和有哪些属性
    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
    Object.defineProperty(obj, prop, descriptor)
    obj
    要定义属性的对象。
    prop
    要定义或修改的属性的名称或 Symbol 。
    descriptor
    要定义或修改的属性描述符。
    descriptor 中有那属性注意看:
    configurable
    当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
    默认为 false
    enumerable
    当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。
    默认为 false

    数据描述符还具有以下可选键值:

    value
    该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
    默认为 undefined
    writable
    当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。
    默认为 false

    存取描述符还具有以下可选键值:

    get
    属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
    默认为 undefined
    set
    属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。
    默认为 undefined
    下面是demo ,有助于更好的理解
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Object.defineProperty实现双向绑定</title>
    </head>
    <body>
      <h1 id='h1'></h1>
      <input type="text" id="inp" onkeyup="inputChange(event)">
      <input type="button" value="加" onclick="btnAdd()" />
    </body>
    <script>
      //数据源
      let vm = {
        value: 0
      }
      //用于管理watcher的Dep对象
      let Dep = function () {
        this.list = [];
        this.add = watcher => this.list.push(watcher),
          this.notify = newValue => {
            this.list.forEach(fn => {
              fn(newValue)
            })
          }
      };
      // 模拟compile,通过对Html的解析生成一系列订阅者(watcher)
      function renderInput(newValue) {
        let el = document.getElementById('inp');
        if (el) {
          el.value = newValue
        }
      }
      function renderTitle(newValue) {
        let el = document.getElementById('h1');
        if (el) {
          el.innerHTML = newValue
        }
      }
      //将解析出来的watcher存入Dep中待用
      let dep = new Dep();
      dep.add(renderInput);
      dep.add(renderTitle)
      console.log(dep);
      console.log(Dep);
      //核心方法
      function initMVVM(vm) {
        console.log(Object.keys(vm));
        Object.keys(vm).forEach(key => {
          observer(vm, key, vm[key])
        })
      }
      function observer(vm, key, value) {
        Object.defineProperty(vm, key, {
          enumerable: true,
          configurable: true,
          get: function () {
            console.log('Get');
            return value
          },
          set: function (newValue) {
            if (value !== newValue) {
              value = newValue
              console.log('Update')
              //将变动通知给相关的订阅者
              dep.notify(newValue)
            }
          }
        })
      }
      //页面引用的方法
      function inputChange(ev) {
        let value = Number.parseInt(ev.target.value);
        vm.value = (Number.isNaN(value)) ? 0 : value;
      }
      function btnAdd() { // 点击添加1
        vm.value = vm.value + 1;
      }
      //初始化数据源
      initMVVM(vm)
      //初始化页面
      dep.notify(vm.value);
    </script>
    </html>
     

    object.defineProperty中的set和get的区别

    1,get和set是方法,因为是方法,所以可以进行判断

    2,get是得到,一般是要返回的;set是设置,不用返回

    3,如果调用对象内部的属性,约定的命名方式是_age

     你学废了吗?

  • 相关阅读:
    [转载]Oracle Golden Gate
    git操作命令
    logger.error完整打印错误堆栈信息
    短网址算法
    YYYY-mm-dd HH:MM:SS大小写解释
    quarz时间配置
    Freemarket语法
    Java NIO:IO与NIO的区别
    idea常用到的命令
    linux 常用命令
  • 原文地址:https://www.cnblogs.com/youguo2/p/14116013.html
Copyright © 2020-2023  润新知