zoukankan      html  css  js  c++  java
  • js 数据监听--对象的变化

    Object.defineProperty第三个参数descriptor的说明。
    数据描述符和存取描述符均具有以下可选键值:

    定义了 value 或 writable , 一定不能有 get 或 set, 反之亦然, 否则报错.

    configurable
    当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。
    enumerable
    当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为 false。
    数据描述符同时具有以下可选键值:

    value
    该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。

    可以将属性函数化。

    eg:

    var student = {
        age: 14,
        sayHi: function (name){
          console.log('hi~' + name);
        }
      }
    Object.defineProperty(student,'age',{
        configurable: true,
        enumerable: true,
    	value(){
    		return 1;
        },
    })
    student.age   // ƒ value(){  return 1; }
    student.age() // 1
    
    

    writable
    当且仅当该属性的writable为true时,value才能被赋值运算符改变。默认为 false。
    存取描述符同时具有以下可选键值:

    get
    一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。
    默认为 undefined。
    set
    一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
    默认为 undefined。

    class Observer {
        constructor(data) {
            this.data = data;
            this.filterObj(data);
        }
        static isObject(obj) {
            if (Object.prototype.toString.call(obj) === "[object Object]") {
                return true;
            }
            return false;
    
        }
        filterObj(data) {
            if (!Observer.isObject(data)) return;
            for (const key in data) {
                // 过滤原型链上的属性。
                if (data.hasOwnProperty(key)) {
                    const value = data[key];
                    if (Observer.isObject(data[key])) {
                        new Observer(data[key]);
                    };
                    this.watch(key, value);
                }
            }
        }
        watch(k, v) {
            Object.defineProperty(this.data, k, {
                enumerable: true,
                configurable: true,
                get: function () {
                    console.log(`${k},被访问。`)
                    return v;
                },
                set: function (newV) {
                    console.log(`${k},属性值发生变化。`)
                    console.log(`新的值为:${JSON.stringify(newV)}。`)
                    if (Observer.isObject(newV)) {
                        new Observer(newV);
                    }
                    v = newV;
                },
            })
        }
    }
    let data = {
        time: '2048',
        user: {
            name: 'naruto',
            equipment: {
                arms: 'kuwu',
                ArmGuard: 'long',
            }
        },
    };
    
    const app = new Observer(data);
    

    /*
    Array.prototype重写method
    getOwnPropertyDescriptor方法可以查看原生js的push等方法是否可以重写。
    MDN:
    Object.getOwnPropertyDescriptor(obj, prop)通过方法可查看自有属性对应的属性描述符。
    (自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
    Object.getOwnPropertyDescriptor(Array.prototype, "push");
    {value: ƒ push(), writable: true, enumerable: false, configurable: true}
     */
    Object.defineProperty(Array.prototype, "push", {
        configurable: true,
        enumerable: false,
        writable: true,
        value: function () {
            const arg = [].slice.call(arguments);
            // console.log('');
            const len = this.length;
            for (let i = 0; i < arg.length; i++) {
                this[len + i] = arg[i]
            }
            return this.length;
        }
    });
    
    // Array.prototype.push = function () {
    //     ...
    // }
    
    /*
    MDN:
    Array.isArray(Array.prototype); // true;
    Array.prototype[0]; // undefined
    鲜为人知的事实:Array.prototype 本身也是一个 Array。
    Array拥有的静态方法:from isArray of。
    
    Array.prototype.constructor
    所有的数组实例都继承了这个属性,它的值就是 Array,表明了所有的数组都是由 Array 构造出来的。
    Array.prototype.length
    上面说了,因为 Array.prototype 也是个数组,所以它也有 length 属性,这个值为 0,因为它是个空数组。
    
    look like this:
    Array.prototype.first = function() {};
    Array.prototype.mapping = function() {};
    Array.prototype["mapping"];
     */
    
    

    操作对象中的Getter

    Object.defineProperty(Array.prototype,'fn',{
    	configurable:true,
    	enumerable:true,
    	get(){
    		const test = function(){};
    		test.f1 = ()=>{
    			console.log(this)
    		};
    		return test;
    	}
    });
    [1,2,3].fn.f1()  //[1, 2, 3]
    
    Array.prototype.__defineGetter__('fn',function(){
    	//const a = {};
    	//const a = function(){};
    	a.f1 = ()=>{
    		console.log(this);
    	};
    	return a;
    });
    [1,2,3].fn.f1()  //[1, 2, 3]
    
    var a = {};
    a.__defineGetter__('name',function(){
    	return 'wfc';
    });
    a.name //'wfc
    
  • 相关阅读:
    Java String字符串补0或空格
    oracle查看当前用户权限
    plsql developer 导出导入存储过程和函数
    扩展jQuery easyui datagrid增加动态改变列编辑的类型
    jQueryEasyUI Messager基本使用
    combox源码解析
    Solr -- Solr Facet 2
    Solr -- Solr Facet 1
    nginx -- 安装配置Nginx
    DOS
  • 原文地址:https://www.cnblogs.com/hideonbush/p/10710536.html
Copyright © 2011-2022 走看看