【这些年我似是非懂的 Javascript】Day 27 - 物件 # Part 3 # 特性描述器

今天要主要来分享一下特性描述器。

特性描述器 (property descriptor)

在 ES5 之前 JS 无法让你判定该物件特性的"特徵",
意思是说你没办法知道他是不是 read-only 之类的。
至於以前怎麽知道他是不是...
书中没有特别提道,
感觉只能用猜的或是直接尝试(我自己猜的)。

但是在 ES5 增加了一个功能叫做特性描述器 (property descriptor)。

const obj = {
    a: 17
};

Object.getOwnPropertyDescriptor(obj,"a");
/*
{
    value: 17,
    writable: true,
    enumerable: true,
    configurable: true
}
*/

由上述的范例可以看到他除了 value 之外,他还有三个特徵。

  • 可写入的 (Writable)
  • 可列举的 (Enumerable)
  • 可配置的 (Configurable)

那我们该如何修改这特徵?
可以使用 Object.defineProperty(..) 新增或是修改现有的特性。
要注意的是如果是修改现有的特性的话他要是可配置的(configurable)。

const obj = {}; // 给个空物件

Object.defineProperty(obj,"a",{
    value: 17,
    writable: true,
    enumerable: true,
    configurable: true
});

obj.a; // 17  出现啦~

接着我们针对这三个特徵来一一说明。

可写入的 (Writable)

这部分很简单,这边就是单纯你可以决定你能否变更一个特性的值。

const obj = {}; // 给个空物件

Object.defineProperty(obj,"a",{
    value: 17,
    writable: false,
    enumerable: true,
    configurable: true
});

obj.a = 123;
obj.a; // 17  Ops 还是原本的 17

如果你不是在严格模式下,你的更改值这动作会直接被吃掉,他也不会跟你说更改失败,
但是反之你如果在严格模式下,他会直接喷爆你给你个 TypeError 并且很贴心的跟你说这是个不可写入的特性。

可列举的 (Enumerable)

这个马上之後会提到这边先提一点点,这部分主要会影响到的是 for .. in 回圈 等等之类的。

来个范例

const obj = {
    name: 'robin'
}

Object.defineProperty(obj,"age",{
    value: 16,
    writable: true,
    enumerable: true,
    configurable: true
});

for(let targetProp in obj){
    console.log(targetProp);
};
// name
// age

Object.defineProperty(obj,"age",{
    value: 16,
    writable: true,
    enumerable: false, // 把 age 改成不可列举
    configurable: true
});


for(let targetProp in obj){
    console.log(targetProp);
};
// name
// 啊... 看不到 age 了

可配置的 (Configurable)

可配置就是刚刚提到的Object.defineProperty(..),能不能修改就是看这个啦。

const obj = {
    a: 17
}

Object.defineProperty(obj,"a",{
    value: 16,
    writable: true,
    enumerable: true,
    configurable: false // 设定不可改
});

Object.defineProperty(obj,"a",{
    value: 18,
    writable: true,
    enumerable: true,
    configurable: true // 设定可改
}); // TypeError 

这边不管你是不是严格模式都会喷你 TypeError,那如果从 false 想把它改回来怎麽办...?
答案是你没有回头路xDD
那如果我直接删掉它这个特性呢?

const obj = {
    a: 17
}

delete obj.a;
obj.a; // undefined  不见了

Object.defineProperty(obj,"a",{
    value: 16,
    writable: true,
    enumerable: true,
    configurable: false // 设定不可改
});

obj.a; // 16
delete obj.a;
obj.a; // 16  砍不掉啊啊啊啊

以上是今天的内容,
也认识到了特性描述器这神奇的东东。
感谢您的收看我们明天见~


参考来源:

你所不知道的 JS|范畴与 Closures,this 与物件原型 (You Don't Know JS: this & Object Prototypes))


<<:  RxJS 条件/布林类型 Operators (1) - isEmpty / defaultIfEmpty / find / finxIndex / every

>>:  [Day26]用SEED来体验漏洞吧

IT 铁人赛 k8s 入门30天 -- day10 K8s Ingress explained

前言 今天将会讲解 Ingress 这个元件 包括用途, 用法还有实际案例 什麽是 Ingress ...

[13th][Day5] 建立一个 daemon container

除了 交互式的 container(interactive container) 也能建立长期运行的...

Day27 ( 游戏设计 ) 老鼠走迷宫

老鼠走迷宫 教学原文参考:老鼠走迷宫 这篇文章会介绍如何使用「创建角色」、「角色是否碰到其他角色」、...

Day 11: QwikLabs

前情提要 Day 1: 介绍这30天的计画 Day 2-8: 刷题 Day 9-10: 面试找工作分...

[Day 28] 实作 Multi-Channel Notifications

铁人赛已逐渐进入尾声,前面二十多天,我们一步步扩充加强 Ktor 功能,也整合了 ORM, Redi...