您好,登錄后才能下訂單哦!
實(shí)現(xiàn)的步驟:
1.監(jiān)聽對(duì)象屬性的讀取與變化
Object.defineProperty() 方法會(huì)直接在對(duì)象上定義一個(gè)新的的屬性,或者已經(jīng)存在的屬性并且返回這個(gè)屬性
語法是 Object.defineProperty(obj, prop, descript)
obj: 目標(biāo)對(duì)象
prop: 需要定義或修改的屬性的名字
descript: 將被定義或修改的屬性的描述符
描述:
這個(gè)方法精確添加或修改對(duì)象的屬性,我們添加的屬性是可以枚舉的屬性(Object.keys()/ for...in)
對(duì)象里面存在是屬性描述存在的形式是:
數(shù)據(jù)描述符:擁有可寫入或不可以寫入的屬性(相當(dāng)于口令密碼)
存取描述符:由一對(duì)getter-setter 函數(shù)功能來描述的屬性(方法)
注意:**描述符**必須是兩種形式之一,不能同時(shí)是兩者。
數(shù)據(jù)描述符和存取描述符均具有以下可選鍵值:
1.configurable:當(dāng)且僅當(dāng)該屬性的 configurable 為 true 時(shí),該屬性描述符才能夠被改變,也能夠被刪除。默認(rèn)為 false
2.enumerable:當(dāng)且僅當(dāng)該屬性的 enumerable 為 true 時(shí),該屬性才能夠出現(xiàn)在對(duì)象的枚舉屬性中。默認(rèn)為 false
數(shù)據(jù)描述符:
1.value:該屬性對(duì)應(yīng)的值??梢允侨魏斡行У?JavaScript 值(數(shù)值,對(duì)象,函數(shù)等)。默認(rèn)為 undefined。
2.writable:當(dāng)且僅當(dāng)該屬性的 writable 為 true 時(shí),該屬性才能被賦值運(yùn)算符改變。默認(rèn)為 false。
存取描述符同時(shí)具有以下可選鍵值:
1.get:一個(gè)給屬性提供 getter 的方法,如果沒有 getter 則為 undefined。該方法返回值被用作屬性值。默認(rèn)為 undefined。
2.set:一個(gè)給屬性提供 setter 的方法,如果沒有 setter 則為 undefined。該方法將接受唯一參數(shù),并將該參數(shù)的新值分配給該屬性。默認(rèn)為 undefined。
示例:
創(chuàng)建屬性
var o = {}; Object.defineProperty(o, "a", {value : 37, writable : true, enumerable : true, configurable : true}); console.log(o.a); Object.defineProperty(o, "b", {get : function(){ /*console.log( bValue)*/ return value }, set : function(newValue){ bValue = newValue; }, enumerable : true, configurable : true}); o.b = 38;
修改屬性
當(dāng)屬性特性(property attribute) writable 設(shè)置為false時(shí),表示 non-writable,屬性不能被修改。
var o = {}; // 創(chuàng)建一個(gè)新對(duì)象 Object.defineProperty(o, "a", { value : 37, writable : false }); console.log(o.a); // 打印 37 o.a = 25; // 沒有錯(cuò)誤拋出(在嚴(yán)格模式下會(huì)拋出,即使之前已經(jīng)有相同的值) console.log(o.a); // 打印 37, 賦值不起作用。
一般的setter 和 getters
var pattern = { get: function () { return 'I alway return this string,whatever you have assigned'; }, set: function () { this.myname = 'this is my name string'; } }; function TestDefineSetAndGet() { Object.defineProperty(this, 'myproperty', pattern); } var instance = new TestDefineSetAndGet(); instance.myproperty = 'test'; // 'I alway return this string,whatever you have assigned' console.log(instance.myproperty); // 'this is my name string' console.log(instance.myname);
解題
function Observer(property) { this.data = {}; this.recursion(data); } Observer.prototype.recursion = function(obj) { var val = null; for (key in obj) { if(obj.hasOwnProperty(key)) { val = obj[val]; if(typeof val === 'object' && !!val) { new Observer(val); } this.access(key, val); } } } Observer.prototype.access = function(key, val) { Object.defineProperty(this.data, key, { enumerable: true, configurable: true, get: function () { console.log('你訪問了' + key); return val }, set: function (newVal) { console.log('你設(shè)置了' + key); console.log('新的' + key + ' = ' + newVal) if (newVal === val) return; val = newVal } }) } let app1 = new Observer({ name: 'youngwind', age: 25 }); let app2 = new Observer({ university: 'bupt', major: 'computer' }); // 要實(shí)現(xiàn)的結(jié)果如下: app1.data.name // 你訪問了 name app1.data.age = 100; // 你設(shè)置了 age,新的值為100 app2.data.university // 你訪問了 university app2.data.major = 'science' // 你設(shè)置了 major,新的值為 science
多層級(jí)對(duì)象
當(dāng)傳入的對(duì)象是
let app1 = new Observer({ user: { name: "liangshaofeng", age: "24" }, address: { city: "beijing" } });
遞歸解決問題!!
function Observer(data) { this.data = data; this.recursion(this.data); } Observer.prototype.recursion = function(obj) { var val = null; for (key in obj) { if(obj.hasOwnProperty(key)) { val = obj[key]; if(typeof val === 'object' && !!val) { new Observer(val); } this.access(key, val); } } } Observer.prototype.access = function(key, val) { Object.defineProperty(this.data, key, { enumerable: true, configurable: true, get: function () { console.log('你訪問了' + key); return val }, set: function (newVal) { console.log('你設(shè)置了' + key); console.log('新的' + key + ' = ' + newVal) if (newVal === val) return; val = newVal } }) } let app1 = new Observer({ user: { name: "liangshaofeng", age: "24" }, address: { city: "beijing" } }); app1.data.user.name // 你訪問了 name app1.data.user.age = 100; // 你設(shè)置了 age,新的值為100
增加事件系統(tǒng)
// 事件系統(tǒng) function Event() { this.events = {}; } Event.prototype.emit = function(attr, val, newVal) { this.events[attr] && this.events[attr].forEach(function(item){ item(val, newVal) }) } Event.prototype.on = function(attr, callback){ if(this.events[attr]){ this.events[attr].push(callback); }else{ this.events[attr] = [callback]; } } function Observer(data) { this.data = data; this.recursion(this.data); this.eventsBus = new Event(); } Observer.prototype.recursion = function(obj) { var val = null; for (key in obj) { if(obj.hasOwnProperty(key)) { val = obj[key]; if(typeof val === 'object' && !!val) { new Observer(val); } this.access(key, val); } } } Observer.prototype.access = function(key, val) { var self = this; Object.defineProperty(this.data, key, { enumerable: true, configurable: true, get: function () { console.log('你訪問了' + key); return val }, set: function (newVal) { if (typeof newVal === 'object' && !!newVal) { new Observer(newVal); } console.log('你設(shè)置了' + key); console.log('新的' + key + ' = ' + newVal) self.eventsBus.emit(key, val, newVal); if (newVal === val) return; val = newVal } }) } Observer.prototype.$watch = function(attr, callback){ this.eventsBus.on(attr, callback); } let app1 = new Observer({ user: { name: "liangshaofeng", age: "24" }, address: { city: "beijing" } }); app1.data.user.name // 你訪問了 name app1.data.user.age = 100; // 你設(shè)置了 age,新的值為100 app1.data.user.name = { lastName: 'liang', firstName: 'shaofeng' }; app1.data.user.name.lastName; // 這里還需要輸出 '你訪問了 lastName ' app1.data.user.name.firstName = 'lalala'; // 這里還需要輸出 '你設(shè)置了firstName, 新的值為 lalala' var app1 = new Observer({ name: 'liujianhuan', age: 25, company: 'Qihoo 360', address: 'Chaoyang, Beijing' }) app1.$watch('age', function(oldVal, newVal){ console.log(`我的年齡變了,原來是: ${oldVal}歲,現(xiàn)在是:${newVal}歲了`) }) app1.$watch('age', function(oldVal, newVal){ console.log(`我的年齡真的變了誒,竟然年輕了${oldVal - newVal}歲`) }) app1.data.age = 20;
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。