如何让对象属性不可配置或枚举

一、什么是属性描述符?

MDN:

对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。

数据描述符是一个拥有可写或不可写值的属性。

存取描述符是由一对 getter-setter 函数功能来描述的属性。

描述符必须是两种形式之一;不能同时是两者。

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

value 与属性相关的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。 

writable true 当且仅当可能用赋值运算符改变与属性相关的值。默认为 false。

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

get

一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。方法将返回用作属性的值。默认为 undefined。 set 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将收到作为唯一参数的新值分配给属性。默认为 undefined。

以上是摘自MDN的解释,看起来是很晦涩的,具体什么意思呢: 首先我们从以上解释知道该匿名参数对象有个很好听的名字叫属性描述符,属性描述符又分成两大块:数据描述符以及存取描述符(其实只是一个外号,给指定的属性集合起个外号)。

数据描述符包括两个属性 :value属性以及writable属性,第一个属性用来声明当前欲修饰的属性的值,第二个属性用来声明当前对象是否可写即是否可以修改

存取描述符就包括get与set属性用来声明欲修饰的象属性的getter及setter

属性描述符内部,数据描述符与存取描述符只能存在其中之一,但是不论使用哪个描述符都可以同时设置configurable属性以及enumerable属性。

configurable属性用来声明欲修饰的属性是否能够配置,仅有当其值为true时,被修饰的属性才有可能能够被删除,或者重新配置。

enumerable属性用来声明欲修饰属性是否可以被枚举。

知道了什么是属性描述符,我们就可以开始着手创建一些对象并开始配置其属性

顺便给大家推荐一个裙,它的前面是 537,中间是631,最后就是 707。想要学习前端的小伙伴可以加入我们一起学习,互相帮助。群里每天晚上都有大神免费直播上课,如果不是想学习的小伙伴就不要加啦。(537-631-707)

二、创建属性不可配置不可枚举的对象

//使用默认值配置

(function(){

varobj = {};//声明一个空对象

Object.defineProperty(obj,"key",{

value:"static"

//没有设置 enumerable 使用默认值 false

//没有 configurable 使用默认值 false

//没有 writable 使用默认值 false

});

console.log(obj.key);//输出 “static”

obj.key ="new"//尝试修改其值,修改将失败,因为 writable 为 false

console.log(obj.key);//输出 “static”

obj.a =1;//动态添加一个属性

for(variteminobj){//遍历所有 obj 的可枚举属性

console.log(item);

}//只输出一个 “a” 因为 “key”的 enumerable为 false

})();

//显示配置 等价于上面

(function(){

varobj = {};

Object.defineProperty(obj,"key",{

enumerable:false,

configurable:false,

writable:false,

value:"static"

})

})();

//等价配置

(function(){

varo = {};

o.a =1;

//等价于

Object.defineProperty(o,"a",{value:1,

writable:true,

configurable:true,

enumerable:true});

Object.defineProperty(o,"a",{value:1});

//等价于

Object.defineProperty(o,"a",{value:1,

writable:false,

configurable:false,

enumerable:false});

})();

三、Enumerable 特性

属性特性enumerable决定属性是否能被for...in循环或Object.keys方法遍历得到

(function(){

varo = {};

Object.defineProperty(o,"a",{value:1,enumerable:true});

Object.defineProperty(o,"b",{value:2,enumerable:false});

Object.defineProperty(o,"c",{value:2});//enumerable default to false

o.d =4;//如果直接赋值的方式创建对象的属性,则这个属性的 enumerable 为 true

for(varitemino){//遍历所有可枚举属性包括继承的属性

console.log(item);

}

console.log(Object.keys(o));//获取 o 对象的所有可遍历属性不包括继承的属性

console.log(o.propertyIsEnumerable('a'));//true

console.log(o.propertyIsEnumerable('b'));//false

console.log(o.propertyIsEnumerable('c'));//false

})();

输出结果如下:

四、Configurable 特性

(function(){

varo = {};

Object.defineProperty(o,"a",{get:function(){return1;},

configurable:false} );

//enumerable 默认为 false,

//value 默认为 undefined,

//writable 默认为 false,

//set 默认为 undefined

//抛出异常,因为最开始定义了 configurable 为 false,故后期无法对其进行再配置

Object.defineProperty(o,"a",{configurable:true} );

//抛出异常,因为最开始定义了 configurable 为 false,故后期无法对其进行再配置,enumerable 的原值为 false

Object.defineProperty(o,"a",{enumerable:true} );

//抛出异常,因为最开始定义了 configurable 为 false,set的原值为 undefined

Object.defineProperty(o,"a",{set:function(val){}} );

//抛出异常,因为最开始定义了 configurable 为 false,故无法进行覆盖,尽管想用一样的来覆盖

Object.defineProperty(o,"a",{get:function(){return1}});

//抛出异常,因为最开始定义了 configurable 为 false,故无法将其进行重新配置把属性描述符从存取描述符改为数据描述符

Object.defineProperty(o,"a",{value:12});

console.log(o.a);//输出1

deleteo.a;//想要删除属性,将失败

console.log(o.a);//输出1

})();

五、提高及扩展

1.属性描述符中容易被误导的地方之writable与configurable

(function(){

varo = {};

Object.defineProperties(o,{

"a": {

value:1,

writable:true,//可写

configurable:false//不可配置

//enumerable 默认为 false 不可枚举

},

"b":{

get:function(){

returnthis.a;

},

configurable:false

}

});

console.log(o.a);//1

o.a =2;//修改值成功,writable 为 true

console.log(o.a);//2

Object.defineProperty(o,"a",{value:3});//同样为修改值成功

console.log(o.a);//3

//将其属性 b 的属性描述符从存取描述符重新配置为数据描述符

Object.defineProperty(o,"b",{value:3});//抛出异常,因为 configurable 为 false

})();

2.通过上面的学习,我们都知道传递属性描述符参数时,是定义一个匿名的对象,里面包含属性描述符内容,若每定义一次便要创建一个匿名对象传入,将会造成内存浪费。故优化如下:

(function(){

varobj = {};

//回收同一对象,即减少内存浪费

functionwithValue(value){

vard = withValue.d ||(

withValue.d = {

enumerable:false,

configurable:false,

writable:false,

value:null

}

);

d.value = value;

returnd;

}

Object.defineProperty(obj,"key",withValue("static"))

})();

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 一、什么是属性描述符? MDN: 对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。 数据描述符是...
    强哥科技兴阅读 885评论 0 0
  • 概述 JavaScript提供了一个内部数据结构,用来描述一个对象的属性的行为,控制它的行为。这被称为“属性描述对...
    zjh111阅读 723评论 0 0
  • 概述 JavaScript提供了一个内部数据结构,用来描述一个对象的属性的行为,控制它的行为。这被称为“属性描述对...
    许先生__阅读 475评论 0 1
  • 尽管javascript里有大量内建引用对象,很可能你还说会频繁创建自己的对象。当你在这么做的时候,记得javas...
    WanLum阅读 521评论 1 3
  • (注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!)(注2:更多内容请查看我的目录。) ...
    love丁酥酥阅读 1,836评论 4 7