参考ECMAScript5
属性有2种,数据属性和访问器属性。
数据属性:
拥有4个特性:
Configurable 表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。默认为true,如果将其设置为false,则不能再变回true了,除了writable特性可以设置以外,其余都不可设置
Enumerable 表示能修改通过for-in循环返回属性。默认为true
Writable 表示能否修改属性的值。默认为true
Value 包含这个属性的数据值。默认为underfined
这4个特性是内部值,不能直接访问,只能使用Object.defineProperty()方法进行修改。
eg:
Object.defineProperty(obj,key,{writable:false,value:'abc});
如果在使用其创建新属性时不指定特性值,则默认值都是false,如果是修改已定义的则无此限制
访问器属性:
访问器属性不包含数据值,它们包含一对getter和setter函数,拥有以下4个特性:
前2个特性是一样的,之后的2个特性为get和set
访问器属性不能直接定义,必须使用Object.defineProperty创建访问器属性。
可以使用Object.defineProperties(obj,json)来创建多个属性
我们知道vue有个很好用的特性,即数据双向绑定,这里我试着编写了一个简单的具有双向绑定特性的构造函数:
function CL(obj) { this.template = obj.template try{ this.target = obj.el.charAt(0) === '#'?document.getElementById(obj.el.substr(1)):document.getElementsByClassName(obj.el.substr(1))[0] }catch (err){ console.log(err) } if(typeof obj.data == 'function'){this.data = obj.data} else{ console.log('data must a function') } if(this.data){ let obj = this.data() setObject.call(this,obj,this) } this.target.innerHTML = formatString(this.template,this) Object.freeze(this) } function formatString(str,data) { return str.replace(new RegExp('{{(.+)}}','g'),(match,$1)=>{ if (new RegExp('.','g').test($1)) { var arr = $1.split('.') return data[arr[0]][arr[1]] }else { return data[$1] } }) } function setObject(obj,This) { for (let key in obj) { Object.defineProperties(this,{ _data:{ writable:true, value:(typeof obj[key] == 'object')?new setObject(obj[key],This):obj[key] }, [key]:{ get(){ return this._data }, set(newVal){ this._data = newVal This.target.innerHTML = formatString(This.template,This) } } }) } }
后续会对这段代码进行解释,写的比较随意,如有错误请指正。