为什么变异的[[原型]]一个对象的糟糕表现?

什么是变异的[[原型]]

在 JavaScript 中,每个对象都有一个 [[原型]] 属性,它指向另一个对象。这个被指向的对象就是该对象的原型,也可以称之为父对象或者超类。

当我们访问一个对象的属性时,如果该对象本身没有这个属性,JavaScript 就会沿着原型链往上查找,直到找到该属性或者到达原型链的顶端(即 Object.prototype)。

所谓“变异的[[原型]]”,指的是在运行时改变某个对象的原型链,即将该对象的 [[原型]] 属性指向另一个对象。

例如,我们可以通过以下代码将一个空对象 {} 的原型指向 Array.prototype

----- --- - ---
------------- - ----------------

变异的[[原型]]的糟糕表现

虽然变异的[[原型]]看起来似乎很有用,但实际上却会带来一些严重的问题。下面我们来看看这些问题是什么。

问题一:性能问题

每次访问一个对象的属性时,JavaScript 都需要沿着原型链往上查找,直到找到该属性或者到达原型链的顶端。这个过程是比较耗费时间的,因为要递归地遍历所有的原型链。

如果我们使用变异的[[原型]],那么每次访问该对象的属性时,JavaScript 都需要遍历新的原型链。这个过程比起之前要长得多,因为它需要先查找新的原型对象,才能继续查找原来的原型对象。这对性能会有很大的影响。

问题二:不可靠的行为

由于 JavaScript 引擎不支持变异的[[原型]],因此这种行为是不被标准所支持的。不同的引擎可能会有不同的实现方式,这样一来就会导致代码的行为不可靠。

例如,在某些浏览器中,将一个对象的原型指向 null 后再将其恢复成原来的原型对象时,该对象上的方法可能会出现错误或者失效。

----- --- - ---
------------- - ----- -- - --- ----- ----
---------------------------- -- ---------- ------------ -- --- - --------
------------- - ----------------- -- -- --- ---- ----------------
---------------------------- -- -------- --------

问题三:安全问题

变异的[[原型]]也可能会带来安全问题。如果某个对象的原型被修改成了一个恶意的对象,那么在查询该对象的属性时,就可能会调用到这个对象的恶意方法,从而导致安全问题。

例如,以下代码将一个普通的对象的原型修改成了 Function.prototype,并调用了该对象的 constructor 方法,可以看到这个方法输出了一个函数对象:

----- --- - - ----- ------- --
------------- - -------------------
----------------------------- -- --------- ---------- - ------- ----- --

这个函数对象不仅可以访问全局变量,还可以执行任意 JavaScript 代码,因此可能会对系统造成严重的安全威胁。

如何避免使用变异的[[原型]]

鉴于变异的[[原型]]会带来许多问题,我们应该尽量避免使用它。下面是一些替代方案:

  • 使用 Object.create() 来创建一个新的对象,并将其原型指

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/14698