关于JavaScript对象的prototype、class及extensible属性的疑问
嘿,这个问题抓得很准,把JS对象的内部细节和API的区别点出来了,我来一步步给你讲清楚~
关于对象的prototype、class和extensible的疑问解答
1. 先说说你提到的「class属性」
你说的这个其实是JS规范里的**[[Class]]内部属性**,它并不是一个可以直接通过.或者[]访问的对象属性,而是JS引擎用来标识对象类型的内部标记。
举个例子:
- 普通对象的[[Class]]值是
"Object" - 数组的[[Class]]值是
"Array" - 函数的[[Class]]值是
"Function" - 日期对象的[[Class]]值是
"Date"
以前我们常用来判断对象类型的Object.prototype.toString.call(obj),返回的字符串里就包含了这个[[Class]]的值,比如:
Object.prototype.toString.call([]); // 返回 "[object Array]" Object.prototype.toString.call(new Date()); // 返回 "[object Date]"
需要注意的是,ES6之后引入的class语法是语法糖,用来实现面向对象的类,和这个内部的[[Class]]完全不是一回事,别搞混啦~
2. 关于extensible和Object.isExtensible()的区别
这里你混淆了对象内部状态和检查这个状态的API:
- 对象本身有一个内部属性[[Extensible]],它是一个布尔值,决定了这个对象是否可以添加新的属性。默认情况下,新建的对象[[Extensible]]都是
true。 Object.isExtensible(obj)是一个标准API,它的作用就是读取对象的[[Extensible]]状态,返回对应的布尔值。
另外还有几个相关的API可以修改这个状态:
Object.preventExtensions(obj):把对象的[[Extensible]]设置为false,一旦设置就无法再恢复为trueObject.seal(obj):除了设置[[Extensible]]为false,还会把对象所有现有属性的configurable特性设为falseObject.freeze(obj):在seal的基础上,再把所有现有属性的writable特性设为false(针对数据属性)
3. 再补充一下prototype的细节
你已经知道prototype用来指向父对象(原型),这里再补个小细节:只有函数对象才有显式的prototype属性,普通对象的原型是通过Object.getPrototypeOf(obj)来访问的(__proto__是浏览器早年实现的非标准属性,现在虽然被纳入规范,但不推荐使用)。比如:
function Foo() {} console.log(Foo.prototype); // 这是Foo函数的原型对象 const foo = new Foo(); console.log(Object.getPrototypeOf(foo) === Foo.prototype); // true
内容的提问来源于stack exchange,提问作者Ashan Priyadarshana
相关产品推荐
相关产品推荐

