在 JavaScript 中,每个对象都有一个内部属性 [[Prototype]]
,该属性指向其原型对象。原型对象是另一个对象,它包含共享属性和方法,这些属性和方法可以从该对象的实例继承。
当我们创建一个构造函数时,它将自动具有一个名为 prototype
的属性,该属性指向一个空对象。我们可以通过向这个原型对象添加属性和方法来使所有该构造函数的实例继承这些属性和方法。
然而,在 JavaScript 中,一旦对象被创建,就无法更改其原型。这意味着,如果我们尝试更改构造函数的原型,那么构造函数已经创建的所有实例都将无法访问这些新的属性和方法。
例如,考虑以下代码:
-- -------------------- ---- ------- -------- ------------ - --------- - ----- - ---------------------- - ---------- - ------------------- -- ---- -- --------------- - ----- ---- - --- --------------- ------------- -- -- ------- -- ---- -- ----- ---------------- - - ------ ---------- - ---------------- -- ---- -- --------------- - -- ----- ---- - --- --------------- ------------- -- -- --------------- ----
在上面的示例中,我们定义了一个 Person
构造函数,并将 greet
方法添加到其原型上。我们创建了一个 john
实例并调用了 greet
方法,它输出了预期的结果。
接着我们尝试更改 Person.prototype
为一个新的对象,并将其包含一个名为 sayHi
的方法。然而,当我们尝试使用该构造函数创建一个新的实例 jane
并调用 sayHi
方法时,会抛出 TypeError
异常,因为 Person.prototype
已经被更改了。
这是因为在 JavaScript 中,每个实例都有一个指向其构造函数的原型的内部指针。当我们使用 new
运算符创建一个新的实例时,它将复制构造函数的原型,并将其作为新实例的原型。这意味着即使我们更改了构造函数的原型,也不会影响先前创建的实例,因为它们仍然引用先前的原型。
虽然无法更改构造函数的原型,但是可以通过其他方式扩展其功能。例如,我们可以定义一个新的构造函数,将旧的构造函数作为其原型,并添加新的属性和方法:
-- -------------------- ---- ------- -------- ------------- ------ - ----------------- ------ ---------- - ------ - ----------------- - -------------------------------- ----------------------------- - -------- ----------------------- - ---------- - ------------------------- -- ----------- -- ----- --- - --- -------------- ----- ------------ -- -- ------- -- ---- -- ---- ------------ -- -- ---- -- ---------
在上面的示例中,我们定义了一个新的 Student
构造函数,它继承自 Person
。我们使用 Object.create
方法创建了一个新对象,该对象将 Person.prototype
作为其原型,并将其分配为 Student.prototype
。然后,我们添加了一个新的 study
方法,该方法仅适用于 Student
实例。
通过这种方式,我们可以在不更改构造函数原型的情况下扩展其功能,并创建具有不同行为的新构造函数。
总之,在 JavaScript 中,无法更改构造函数原型,因为每个实例都引用其原型。但是,我们可以使用其他模式来扩展构造函数的功能,并创建具有不同行为的新构造函数。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/28162