前言
整理 JavaScript 中类(ES5)的实现方法, 以及相关知识。原封不动地记录了我觉得比较重要的概念,明白了这些概念也就理解了 JavaScript 中类的实现方式。
内容主要来自:
- JavaScript 高级程序设计(第3版)
- ES6 标准入门(第3版)
- MDN
本文仅整理、记录、学习。
一、理解对象
1. 属性的类型(就是属性描述符)
ECMA-262 第 5 版在定义只有在内部才用的特性(attribute)时,描述了属性(property)的各种特征。ECMA-262 定义这个特性是为了实现 JavaScript 引擎用的,因此在 JavaScript 中不能直接访问它们。为了表示特性是内部值,该规范把它们放在了两对儿方括号中,例如
[[Enumerable]]
。
ECMAScript 中有两种属性:
-
数据属性:包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有 4 个描述其行为的特征。
[[Configurable]]
:表示能否通过delete
删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。默认值为true
。[[Enumerable]]
:表示能否通过for-in
循环返回属性。默认值为true
。[[Writable]]
:表示能否修改属性值。默认值为true
。[[Value]]
:包含这个属性的数据值。读取属性的时候,从这个位置读;写入属性的时候,把新值保存在这个位置。默认值为undefined
。
-
访问器属性:不包含数据值;它们包含一对儿
getter
和setter
函数(不过,这两个函数都不是必须的)。在读取访问器属性时,会调用getter
函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter
函数并传入新值,这个函数负责决定如何处理数据。访问器属性有如下 4 个特性。[[Configurable]]
[[Enumerable]]
[[Get]]
:读取属性时调用的函数。默认值为undefined
。[[Set]]
:写入属性时调用的函数。默认值为undefined
。
⚠️ 以上说的默认值是当直接在对象上定义属性时的默认值。
当我们直接在对象上定义属性的时候,它们的 [[Configurable]]
、 [[Enumerable]]
和 [[Writable]]
特性都被设置为 true
,而 [[Value]]
特性被设置为指定的值。
例如:
var obj = {
name: 'Nicholas'
};
Object.getOwnPropertyDescriptor(obj, 'name');
// {
// configurable: true
// enumerable: true
// value: "Nicholas"
// writable: true
// }
2. 属性描述符(MDN)
在 Javascript 中, 属性 由一个字符串类型的“名字” (name)和一个“属性描述符”(property descriptor)对象构成。
引自:MDN
对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。
❗️tips:阅读以下内容时注意区分加粗字体。
这两种描述符都是对象。它们共享以下可选键值(默认值是指在使用 Object.defineProperty()
定义属性时的默认值):
configurable
:当且仅当该属性的configurable
键值为true
时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
默认为false
。enumerable
:当且仅当该属性的enumerable
键值为true
时,该属性才会出现在对象的枚举属性中。
默认为