您的位置:首页 > 移动开发 > Objective-C

有关于mvvm中的Object.defineProperty方法的一些理解

2019-03-20 09:33 405 查看
Object.defineProperty(obj, prop, descriptor)

通过此方法为对象设置属性的时候,对象的属性值会包含一个get和set方法。
set方法中做一些处理,执行页面的刷新和回调

当修改对象值的时候会触发相应的函数调用;
参数一obj、需要定义属性的对象;
参数二 prop、属性名字;
参数三 desciptor、对象属性的修饰内容;

返回值

被传递给函数的对象。

在ES6中,由于 Symbol类型的特殊性,用Symbol类型的值来做对象的key与常规的定义或修改不同,而Object.defineProperty 是定义key为Symbol的属性的方法之一。

描述

该方法允许精确添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的,能够在属性枚举期间呈现出来(

for...in
Object.keys
方法), 这些属性的值可以被改变,也可以被删除。这个方法允许修改默认的额外选项(或配置)。默认情况下,使用
Object.defineProperty()
添加的属性值是不可修改的。

属性描述符

对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一;不能同时是两者。

数据描述符和存取描述符均具有以下可选键值:

configurable
当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。
enumerable
当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为 false。

数据描述符同时具有以下可选键值:

value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
writable
当且仅当该属性的writable为true时,value才能被赋值运算符改变。默认为 false。

存取描述符同时具有以下可选键值:

get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。
默认为 undefined。
set
一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
默认为 undefined。

描述符可同时具有的键值

configurable
数据描述符 yes
存取描述符 yes
enumerable
数据描述符 yes
存取描述符 yes
value
数据描述符 yes
存取描述符 no
writable
数据描述符 yes
存取描述符 no
get
数据描述符 no
存取描述符 yes
set
数据描述符 no
存取描述符 yes

如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。
记住,这些选项不一定是自身属性,如果是继承来的也要考虑。为了确认保留这些默认值,你可能要在这之前冻结 Object.prototype,明确指定所有的选项,或者通过 Object.create(null)将__proto__属性指向null。

// 使用 __proto__
var obj = {};
var descriptor = Object.create(null); // 没有继承的属性
// 默认没有 enumerable,没有 configurable,没有 writable
descriptor.value = 'static';
Object.defineProperty(obj, 'key', descriptor);

// 显式
Object.defineProperty(obj, "key", {
enumerable: false,
configurable: false,
writable: false,
value: "static"
});

// 循环使用同一对象
function withValue(value) {
var d = withValue.d || (
withValue.d = {
enumerable: false,
writable: false,
configurable: false,
value: null
}
);
d.value = value;
return d;
}
// ... 并且 ...
Object.defineProperty(obj, "key", withValue("static"));

// 如果 freeze 可用, 防止代码添加或删除对象原型的属性
// (value, get, set, enumerable, writable, configurable)
(Object.freeze||Object)(Object.prototype);

Object.defineProperty在实际开发中的一些应用:

在实际开发过程中,例如es6中新增的const声明一个常量,就可以用到Object.defineProperty来定义,把writable的属性值定义为false,即可写属性为假,把常量封存在CONST命名空间中,但是我们仍然可以通过修改writable为true,所以configurable设置为false,不能修改属性值,

模拟:
如下代码Const.a相当于es6中的const a=2;Const.a是不可以修改的常量。

var CONST = {};
Object.defineProperty(CONST, 'a', {
value: 2,
writable: false,
configurable: false,
enumerable: true //可枚举
});
console.log(CONST.a); //2
CONST.a = 3;
console.log(CONST.a); //2

面向对象编程

js中的几乎所有事务都是基于对象的:数组,字符串,数字类型,日期,函数等,

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: