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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM