zoukankan      html  css  js  c++  java
  • vue-vm架构体系

    虚拟dom+es5的小方法Object.defineProperty
    es5 的Object.defineProperty() 用来给一个对象定义一个属性。vue的双向绑定原理就是基于defineProperty的访问器属性实现的。
    obj: object类型,需要定义属性的对象
    key: string类型,属性的名称
    descriptor: object类型, 一个描述符,也是重点关注的参数

    descriptor 参数
    第三个参数是一个对象有六个键值。分别是: configurable(boolean, 默认true), enumerable(boolean, 默认true), writable(boolean, 默认true), value(any, 默认undefined), get(function, 默认undefined), set(function, 默认undefined) 。其中writable, value任意一个和get, set任一一个都不可以同时存在。为什么呢? 关于红宝书上的介绍,一上来就是一段教科书的描述,比较晦涩。将defineProperty方法定义的属性分为两种类型:数据属性和访问器属性。 所以descriptor参数的不同决定了相应的属性的类型。 故descriptor有两种方式

    描述数据属性(平时用obj.name = '123', 其实就是默认用这种方式定义的):

    {
        configurable: false, // 默认为true, 描述能否被改变,比如delete或者修改成访问器属性
        enumerable: false, // 默认为true, 描述能否被 in 枚举,比如for-in
        writable: false, // 默认true, 描述是否能被更改
        value: [1, 2, 3], // 默认undefined, 就是属性的值
    }
    

    描述访问器属性

    {
        configurable: false, // 默认为true, 描述能否被改变,比如delete或者修改成访问器属性
        enumerable: false, // 默认为true, 描述能否被 in 枚举,比如for-in
        get: function() {  return this.name }, // 默认undefined, getter函数
        set: function(newVal) { this.name = newVal }, // 默认undefined, setter函数
    }
    

    运行时

    var obj = {};
    Object.defineProperty(obj, 'name', {
        configurable: false, // 默认为true, 描述能否被改变,比如delete或者修改成访问器属性
        enumerable: false, // 默认为true, 描述能否被for-in枚举
        writable: false, // 默认true, 描述是否能被更改
        value: 'wython' // 默认undefined, 就是属性的值
    });
    

    可以看到是定义了一个属性name.这种方式和obj.name = 'wython'; 其实没啥区别。在这里面我把configrable, enumerable, writable改成false。 所以如果参数去改值,或者遍历, 都是不行的。

    for(const i in obj) { console.log(i) }  // 结果: undefined
    delete obj.name; // 无效
    obj.name = 'Another wython'; // 无效
    

    尝试下访问器属性的定义方式

    Object.defineProperty(obj, '_name', {
        configurable: true,
        enumerable: true,
        get: function() { return this.name },
        set: function(newVal) {
            // 我们可以尝试更改name的值,因为是不可更改所以是无效的
            this.name = newVal;
        }
    })
    // 验证
    obj._name  = 1; // 无效,原因是访问器属性监听的是不可更改的name属性
    

    所以说访问器属性监听的是另一个属性,如果监听的是自身,会报堆栈溢出的错误。

    比如:

    Object.defineProperty(obj, '_self', {
        configurable: true,
        enumerable: true,
        get: function() { return this._self },
        set: function(newVal) {
            // 我们可以尝试更改name的值,因为是不可更改所以是无效的
            this._self = newVal;
        }
    })
    obj._self;
    
  • 相关阅读:
    [译]在Python中如何使用额enumerate 和 zip 来迭代两个列表和它们的index?
    [译]如何去除Git的unstaged的文件提示“old mode 100755 new mode 100644”?
    [译]在SQL查询中如何映射(替换)查询的结果?
    [总结]《敏捷软件开发: 原则、模式与实践》一次编程实践
    [书摘]《敏捷软件开发: 原则、模式与实践》第一部分:敏捷开发
    [译]Python
    [问题解决]Python locale error: unsupported locale setting
    [持续补充]开发过程中常见bug查找思路
    [译]如何比较同一分支上的不同commit的代码区别?
    [整理]如何切换到远程分支
  • 原文地址:https://www.cnblogs.com/sansancn/p/11215524.html
Copyright © 2011-2022 走看看