用途:
1. 可以声明不能做任何修改的对象
2. 数据双向绑定
属性设置:
value:值,默认是undefined
writable:是否是只读property,默认是false
enumerable:是否可以被枚举(for
in),默认false
configurable:是否可以被删除,默认false
get:返回property的值得方法,默认是undefined(不能和value、writable同时使用)
set:为property设置值的方法,默认是undefined(不能和value、writable同时使用)
例:
var test =
{
init:function(){
Object.defineProperty(myobj= {},'age', {
value: 18,
writable: true,
enumerable: true,
configurable: true
});
}
}
test.init();
此处声明的myobj对象属于顶层属性,不属于test的属性,即使test的声明在函数作用域内也是如此
即相当于声明为window.myobj
数据双向绑定:
value、configurable、enumerable、writable不能与set同时设置
let obj = {};
let newV;
Object.defineProperty( obj, 'name',
{
set:
function(v){
newV
= v;
//同步更新数据
document.getElementByIdx_x_x_x_x_x_x_x('name')
= v;
},
get:
function(){
return
newV || 0;
}
} );
为对象声明多个属性的方法:
Object.defineProperties (myobj=
{}, {
'name':
{
value:
'canon',
writable:
true,
enumerable:
false,
configurable:
true
},
'age':
{
value:
18,
writable:
true,
enumerable:
true,
configurable:
true
}
});
另外几个与之相关可能会用到的方法
Object.getOwnPropertyDescriptor(obj,property)
获取defineProperty方法设置的property特性
var props =
Object.getOwnPropertyDescriptor(myobj, 'age');
console.log(props)
//{value: 24,
writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyNames(obj)
获取所有的属性名,不包括prototy中的属性,返回一个数组
console.log(Object.getOwnPropertyNames(myobj));
//['name',"age"]
Object.keys(obj)
获取所有的可枚举的属性,返回一个数组
console.log(Object.keys(myobj));
//["age"]
Object.preventExtensions(obj)
锁住对象属性,使其不能够拓展,即不能增加新的属性
但是属性的值仍可更改,也可删除属性
返回该对象
Object.isExtensible(obj)
判断对象是否可以被拓展,返回布尔值
Object.seal(obj)
用于把对象密封,即让对象既不可拓展也不可删除属性(把每个属性的configurable设为false)
但属性值仍然可修改
Object.isSealed(obj)
判断对象是否被密封,返回布尔值
Object.freeze(obj)
冻结对象,在seal的基础上,属性值也不可修改(每个属性的wirtable也被设为false)
Object.isFrozen(obj)
判断对象是否被冻结,返回布尔值
其他:
//脏检查
我们说Angularjs(这里特指AngularJS 1.x.x版本,不代表AngularJS
2.x.x版本)双向数据绑定的技术实现是脏检查,大致的原理就是,
Angularjs内部会维护一个序列,将所有需要监控的属性放在这个序列中,当发生某些特定事件时(注意,
这里并不是定时的而是由某些特殊事件触发的),Angularjs会调用 $digest
方法,这个方法内部做的逻辑就是遍历所有的watcher,
对被监控的属性做对比,对比其在方法调用前后属性值有没有发生变化,如果发生变化,则调用对应的handler。
网上有许多剖析Angularjs双向数据绑定实现原理的文章,比如 这篇 ,再比如 这篇 ,等等。
这种方式的缺点很明显,遍历轮训watcher是非常消耗性能的,特别是当单页的监控数量达到一个数量级的时候。
//观察机制(已废弃,用Object.proxy代替)
博主之前有一篇转载翻译的文章, Object.observe()带来的数据绑定变革 ,说的就是使用ECMAScript7中的
Object.observe 方法对对象
(或者其属性)进行监控观察,一旦其发生变化时,将会执行相应的handler。
这是目前监控属性数据变更最完美的一种方法,语言(浏览器)原生支持,没有什么比这个更好了。唯一的遗憾就是目前支持广度还不行,有待全面推广。
//封装属性访问器
国产mvvm框架vue.js实现数据双向绑定的原理就是属性访问器。
它使用了ECMAScript5.1(ECMA-262)中定义的标准属性 Object.defineProperty
方法。针对国内行情,
部分还不支持 Object.defineProperty
低级浏览器采用VBScript作了完美兼容,不像其他的mvvm框架已经逐渐放弃对低端浏览器的支持。