前端JavaScript基础训练系列六十五:“constructor”和“prototype”

文章揭示了JavaScript中constructor属性的真相,它并非表示对象是由哪个构造函数“构造”的,而是通过[[Prototype]]链查找。错误理解constructor可能导致误导和不必要的复杂性,应避免依赖其默认行为。
摘要由CSDN通过智能技术生成

把 .constructor 属性指向 Foo 看作是 a 对象由 Foo“构造”非常容易理解,但这只不过 是一种虚假的安全感。a.constructor 只是通过默认的 [[Prototype]] 委托指向 Foo,这和

“构造”毫无关系。相反,对于 .constructor 的错误理解很容易对你自己产生误导。
举例来说,Foo.prototype 的 .constructor 属性只是 Foo 函数在声明时的默认属性。如果 你创建了一个新对象并替换了函数默认的 .prototype 对象引用,那么新对象并不会自动获 得 .constructor 属性。
思考下面的代码:

function Foo() { /* .. */ }
Foo.prototype = { /* .. */ }; // 创建一个新原型对象
var a1 = new Foo();
a1.constructor === Foo; // false! a1.constructor === Object; // true!

Object(…) 并没有“构造”a1,对吧?看起来应该是 Foo()“构造”了它。大部分开发者 都认为是 Foo() 执行了构造工作,但是问题在于,如果你认为“constructor”表示“由… 构造”的话,a1.constructor 应该是 Foo,但是它并不是 Foo !
到底怎么回事? a1 并没有 .constructor 属性,所以它会委托 [[Prototype]] 链上的 Foo. prototype。但是这个对象也没有 .constructor 属性(不过默认的 Foo.prototype 对象有这 个属性!),所以它会继续委托,这次会委托给委托链顶端的 Object.prototype。这个对象 有 .constructor 属性,指向内置的 Object(…) 函数。
错误观点已被摧毁。
当然,你可以给 Foo.prototype 添加一个 .constructor 属性,不过这需要手动添加一个符
合正常行为的不可枚举(参见第 3 章)属性。 举例来说:

function Foo() { /* .. */ }
Foo.prototype = { /* .. */ }; // 创建一个新原型对象
// 需要在 Foo.prototype 上“修复”丢失的 .constructor 属性 // 新对象属性起到 Foo.prototype 的作用
// 关于 defineProperty(..),参见第 3 章 Object.defineProperty( Foo.prototype, "constructor" , {
enumerable: false,
writable: true,
configurable: true,
value: Foo // 让 .constructor 指向 Foo
} );

修复 .constructor 需要很多手动操作。所有这些工作都是源于把“constructor”错误地理
解为“由…构造”,这个误解的代价实在太高了。

实际上,对象的 .constructor 会默认指向一个函数,这个函数可以通过对象的 .prototype 引用。“constructor”和“prototype”这两个词本身的含义可能适用也可能不适用。最好的 办法是记住这一点“constructor 并不表示被构造”。
.constructor 并不是一个不可变属性。它是不可枚举(参见上面的代码)的,但是它的值 是可写的(可以被修改)。此外,你可以给任意 [[Prototype]] 链中的任意对象添加一个名 为 constructor 的属性或者对其进行修改,你可以任意对其赋值。
和 [[Get]] 算法查找 [[Prototype]] 链的机制一样,.constructor 属性引用的目标可能和 你想的完全不同。
现在你应该明白这个属性多么随意了吧?
结论?一些随意的对象属性引用,比如 a1.constructor,实际上是不被信任的,它们不一 定会指向默认的函数引用。此外,很快我们就会看到,稍不留神 a1.constructor 就可能会 指向你意想不到的地方。
a1.constructor 是一个非常不可靠并且不安全的引用。通常来说要尽量避免使用这些引用。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值