Object的一些静态方法(2)

开场白

很抱歉,开始讲述知识点之前还是要让你看一段不那么重要的开场白。

今天去了自己最为向往的公司参加了第二轮面试,跟CEO聊天的感觉真的非常好,希望自己能进去吧。但是不管怎么说,日子总得要过吧。如果真的不幸没有办法进入该公司,或许我能做的也就是整理着装,重新踏上求职之旅吧。不过在这之前,还是要每天学点javascript吧?

今天主要讲述下面这两组方法

1. Object.keysObject.getOwnPropertyNames的异同。

2. Object.seal, Object.preventExtensions以及Object.freeze可以在不同程度增强对象的健壮性。

正文

1. Object.keysObject.getOwnPropertyNames的异同

两个方法都是可以用来获取指定对象的自有属性的。那么它们有什么不同呢?
之前已经稍微提及过Object.keys了,它是用来获取一个对象的自有属性。比如:

> var a = {x: 1, y: 2}
undefined
> a
{ x: 1, y: 2 }
> Object.keys(a)
[ 'x', 'y' ]

那它有什么局限呢?更确切地说它只能用来获取对象可枚举的自有属性,我们看看下面的例子。

> Object.getOwnPropertyDescriptor(a, 'x')
{ value: 1, writable: true, enumerable: true, configurable: true }

> Object.defineProperty(a, 'x', {enumerable: false}) // 设置x属性为不可枚举的
{ y: 2 }

> a
{ y: 2 }

> Object.keys(a)
[ 'y' ]

可见,现在我们只能获取到对象a的自有的并且是可枚举的属性。如何获得对象a的自有属性,并且不管它们是否是可枚举的呢?这个时候我们可以考虑用Object.getOwnPropertyNames

> Object.getOwnPropertyNames(a)
[ 'x', 'y' ]

这样就可以获取对象a的所有自有的属性,包括了不可枚举的属性。如果我们需要遍历对象a的所有自有属性,这个方法就能派上用场了。

2. Object.seal, Object.preventExtensions以及Object.freeze可以在不同程度增强对象的健壮性。

这里就有一个问题,什么是对象的可扩展性?我用比较直白的话说就是“是否能够为这个对象添加属性?”。我们可以用Object.isExtensible来判断对象是否是可以扩展的。

> Object.isExtensible(1)
false
> Object.isExtensible({})
true
> Object.isExtensible("lanzhiheng")
false

字符串不可以扩展?你在逗我吗?对的,我们这里用的是字符串的字面量,它是不可以扩展的。做个实验:

> var str = "lanzhiheng"
undefined
> str.age = 12
12
> str.age
undefined

我们试图给str添加一个属性,然而最后查找的时候并没有设置成功,原因是

当我们添加属性的时候,JS会临时创建一个字符串的对象,并且它包装了原来的字符串字面量,所以这里并不会报错。但是当我们执行完str.age = 12之后这个对象自动销毁了,所以这个属性添加是没有作用的。

好啦,回到正题,下面是ES5之后才有的静态方法。我们按顺序来说说。

1. Object.preventExtensions 让对象变成不可扩展的

来看例子:

> var b = {x: 1, y: 2}
undefined
> b.z = 13
13

> Object.preventExtensions(b) // 保护可扩展性
{ x: 1, y: 2, z: 13 }

> b.k = 100
100
> b
{ x: 1, y: 2, z: 13 }

可见,一开始给对象b添加属性是可以的,然而,我们调用了Object.preventExtensions之后这个设置就失败了,在严格模式下甚至还会报错

TypeError: Can't add property x, object is not extensible

2. Object.seal 让对象变成不可扩展的并且把已有的属性设置成不可配置的

这里我们简单把不可配置理解成不可删除,(当然绝不是那么简单而已)。我们来操作一下新对象c

> c = {x: 1, y: 2, z: 3}
{ x: 1, y: 2, z: 3 }

> c.kk = 12  // 添加属性
12

> c
{ x: 1, y: 2, z: 3, kk: 12 }

> delete c.kk // 删除属性
true

> c
{ x: 1, y: 2, z: 3 }

目前为止是很正常的,现在用Object.seal来处理一下好吧。

> Object.seal(c)
{ x: 1, y: 2, z: 3 }

> c.kk = 1000 // 添加属性
1000

> c  // 无效
{ x: 1, y: 2, z: 3 }
> delete c.x // 删除属性
false

> c // 无效
{ x: 1, y: 2, z: 3 }

发现处理之后对c对象进行扩展以及删除属性这些操作都不生效了(严格模式下还会报错),这就是Object.seal方法的作用。可以保护对象的属性以及对象本身, 我们可以方便地用Object.isSealed来判断对象是否具有这类属性。

> Object.isSealed(c)
true

同时,我们也可以用来判断对象是否具有不可扩展且属性不可配置这些特征,即便它没有经过Object.seal处理

> var a = {x: 1, y: 2}
undefined

// 设置对象为不可扩展的
> Object.preventExtensions(a)
{ x: 1, y: 2 }
> Object.isSealed(a)
false

// 设置对应的属性的特性为不可配置的
> Object.defineProperties(a, {x: {configurable: false}, y: {configurable: false}})
{ x: 1, y: 2 }

> Object.isSealed(a)
true

这个方法是不是还不错?另外, 虽然我们无法对对象的已有结构进行修改,但是我们却依然可以修改对象已有的属性的值

> c
{ x: 1, y: 2, z: 3 }
> c.x = 100
100
> c
{ x: 100, y: 2, z: 3 }

要怎样更进一步方便地提高健壮性,把所有属性都弄成不可写的,并且不可配置的呢?这个时候会用到下面要介绍的Object.freeze方法。

3. Object.freeze 让对象变成不可扩展的, 并且把已有的属性设置成不可配置并且不可写

这里不多说明,直接举例子

> var d = {x: 1, y: 2, c: 3}
undefined

> Object.freeze(d)
{ x: 1, y: 2, c: 3 }

> d.kk = 100 // 扩展对象d
100
> d
{ x: 1, y: 2, c: 3 }

> delete d.x // 删除对象d属性
false
> d
{ x: 1, y: 2, c: 3 }

> d.x = 100 // 修改对象d属性的值
100

> d
{ x: 1, y: 2, c: 3 }

可见对象d进行了上面操作依然没有任何改变。同样的, 我们也可以用Object.isFrozen来判断对象是否有对应的特性。

> Object.isFrozen(d)
true

这里就不用复杂的例子了,跟Object.isSealed是差不多的。

当然,如果要对这些进行过保护的特性进行非法操作,在严格模式下是会抛出异常的。

> var dStrict = {x: 1, y: 2}
undefined

> Object.freeze(dStrict)
{ x: 1, y: 2 }

> dStrict.x = 100
TypeError: Cannot assign to read only property 'x' of object '#<Object>'

以上这点写代码的时候需要注意一下。毕竟严格模式跟非严格模式有很多行为都是有所区别的。

最后

终于到了尾声了,今天介绍的方法稍微多了一些,不过都是相关联并且比较方便记忆的,希望读者阅读的时候不会太难受。

Happy Writing & Coding

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

推荐阅读更多精彩内容