实现的步骤:
1.监听对象属性的读取与变化
Object.defineProperty() 方法会直接在对象上定义一个新的的属性,或者已经存在的属性并且返回这个属性
语法是 Object.defineProperty(obj, prop, descript)
obj: 目标对象
prop: 需要定义或修改的属性的名字
descript: 将被定义或修改的属性的描述符
描述:
这个方法精确添加或修改对象的属性,我们添加的属性是可以枚举的属性(Object.keys()/ for...in)
对象里面存在是属性描述存在的形式是:
数据描述符:拥有可写入或不可以写入的属性(相当于口令密码)
存取描述符:由一对getter-setter 函数功能来描述的属性(方法)
注意:**描述符**必须是两种形式之一,不能同时是两者。
数据描述符和存取描述符均具有以下可选键值:
1.configurable:当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false
2.enumerable:当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false
数据描述符:
1.value:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
2.writable:当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。
存取描述符同时具有以下可选键值:
1.get:一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。
2.set:一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。
示例:
创建属性
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;
修改属性
当属性特性(property attribute) writable 设置为false时,表示 non-writable,属性不能被修改。
var o = {}; // 创建一个新对象
Object.defineProperty(o, "a", { value : 37,
 writable : false });
console.log(o.a); // 打印 37
o.a = 25; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值)
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('你设置了' + 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'
});
// 要实现的结果如下:
app1.data.name // 你访问了 name
app1.data.age = 100; // 你设置了 age,新的值为100
app2.data.university // 你访问了 university
app2.data.major = 'science' // 你设置了 major,新的值为 science
多层级对象
当传入的对象是
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('你设置了' + 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; // 你设置了 age,新的值为100
增加事件系统
// 事件系统
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('你设置了' + 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; // 你设置了 age,新的值为100
app1.data.user.name = {
 lastName: 'liang',
 firstName: 'shaofeng'
 };
 app1.data.user.name.lastName;
 // 这里还需要输出 '你访问了 lastName '
 app1.data.user.name.firstName = 'lalala';
 // 这里还需要输出 '你设置了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}岁,现在是:${newVal}岁了`)
})
app1.$watch('age', function(oldVal, newVal){
 console.log(`我的年龄真的变了诶,竟然年轻了${oldVal - newVal}岁`)
})
app1.data.age = 20;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。