可枚举属性有什么作用?用在什么场景下,什么业务下?
var God = {
extends(name, obj){
/*
* 我们约定对象中必须有 data和methdos2个属性
* 并且data是函数,methods是对象
* */
if('data' in obj && 'methods' in obj && typeof obj.data=='function' && typeof obj.methods=='object'){
var getData = obj.data();
if (typeof getData == 'object'){
Object.assign(obj.methods, getData);
this[name] = obj;
}
}
}
};
var news = {
data(){
return {id:101, title:'新闻标题'};
},
methods:{
show(){
alert(this.id);
}
}
};
// 然后我们可以这样访问
God.extends('name',news);
God.name.methods.show();
看我们前面的代码,God
是一个母对象,意思就说我们协作开发,一般由项目组长或技术经理来开发God
这个类。
news
就是我们的业务对象,由我们的队友来开发,一旦我们开发完成之后,我们只需要关注这个类有什么数据,这些数据怎么去调用。
我们的God
来进行适配,把这个news
对象整合到我们的业务中。
上面的代码我就实现了,只要使用God.extends('name',news);
整合进来,我们就可以使用God.name
访问原本news
对象定义的属性或方法。
methods:{
show(){
alert(this.id);
}
}
注意:news对象中,我们是使用this.id
获取的news对象里data()
中的数据。
我们知道如果你不作任何处理,是不能这样使用的,现在能这样使用是因为,我们在God
中通过Object.assign()
方法作了处理。
思考题
God
里面如果有一些属性,比如version:'1.0'
,那么如果我们在news
(子对象里)如何通过以下代码来得到呢?
alert(this.$global.version)
开始:
var God = {
version:'1.0',
extends(name, obj){
// 调用初始化函数
this.init();
/*
* 我们约定对象中必须有 data和methdos2个属性
* 并且data是函数,methods是对象
* */
if('data' in obj && 'methods' in obj && typeof obj.data=='function' && typeof obj.methods=='object'){
var getData = obj.data();
if (typeof getData == 'object'){
Object.assign(obj.methods, getData, this);
this[name] = obj;
}
}
},
init(){
var keys = Object.keys(this); // 列举出this当前是所有属性
this.$global = {};
keys.forEach((key)=>{
this.$global[key] = this[key];
});
}
};
var news = {
data(){
return {id:101, title:'新闻标题'};
},
methods:{
show(){
alert(this.$global.version);
// alert(this.id);
}
}
};
// 然后我们可以这样访问
God.extends('name',news);
God.name.methods.show();
分析:God
中定义了一个init()
方法,完成属性遍历赋值给this.$global
。然后在extends()
里调用,在Object.assign()
的时候把this
也传了进去。
这样news
中就可以通过this.$global
拿到God
对象version
属性的值。
问题来了
刚才我们的举动把母对象一些“子对象不能用或者不需要用的”属性也给合并进去了。
怎么解决,上代码:
var God = {
version:'1.0',
extends(name, obj){
// 调用初始化函数
this.init();
/*
* 我们约定对象中必须有 data和methdos2个属性
* 并且data是函数,methods是对象
* */
if('data' in obj && 'methods' in obj && typeof obj.data=='function' && typeof obj.methods=='object'){
var getData = obj.data();
if (typeof getData == 'object'){
Object.assign(obj.methods, getData, this);
this[name] = obj;
}
}
},
init(){
// 把God对象的这2个属性的enumerable设置为false
Object.defineProperty(this,'init',{enumerable:false});
Object.defineProperty(this,'extends',{enumerable:false});
var keys = Object.keys(this); // 列举出this当前是所有属性
this.$global = {};
keys.forEach((key)=>{
this.$global[key] = this[key];
});
}
};
var news = {
data(){
return {id:101, title:'新闻标题'};
},
methods:{
show(){
alert(Object.keys(this.$global));
// alert(this.id);
}
}
};
// 然后我们可以这样访问
God.extends('name',news);
God.name.methods.show();
分析:我们通过Object.defineProperty
来设置那些属性不可枚举
// 把God对象的这2个属性的enumerable设置为false
Object.defineProperty(this,'init',{enumerable:false});
Object.defineProperty(this,'extends',{enumerable:false});
上代码我们把init
和extends
都设置了false。
我们测试看看:
alert(Object.keys(this.$global));
只打印出version
。如果不写:
//Object.defineProperty(this,'init',{enumerable:false});
//Object.defineProperty(this,'extends',{enumerable:false});
打印出God
的所有子对象(属性)。