最近 Chrome/V8 版本中的对象描述符 getter/setter 性能

IT技术 javascript google-chrome v8
2021-02-27 14:51:31

给定的

var obj = {};

var _a = 1;

obj._a = 1;

obj.aGetter = function() {
  return _a;
}

obj.aSetter = function(val) {
  _a = val;
}

Object.defineProperty(obj, 'a', {
  enumerable: true,
  get: function () {
    return _a;  
  },
  set: function(val) {
    _a = val;
  }     
});

使用 getter/setter 函数

obj.aSetter(2);
obj.aGetter();

与直接访问属性相比,Chrome/V8 的性能会有所下降(约 3 倍):

obj._a = 2;
obj._a;

这是可以理解的。并使用描述符 getter/setter

obj.a = 2;
obj.a;

将导致Chrome(41 到最新)性能下降约 30 倍- 几乎与Proxy. 虽然 Firefox 和旧版 Chrome 使用描述符 getter/setter,但性能没有明显下降。

最近的 Chrome/V8 版本中描述符 getter/setter 性能的确切问题是什么?这是一个可以监控的已知问题吗?

测量是使用 Benchmark.js(jsPerf 引擎)完成的。我无法提供 jsPerf 测试的链接来可视化差异,因为 jsPerf 的反 DDoS 措施已被严重搞砸,但我确信存在可以证明一点的现有措施。

1个回答

性能变化与此 Chromium 问题相关(感谢@VyacheslavEgorov)。

为避免性能问题,应改用原型。这是为什么可以使用单例类将对象实例化一次的少数原因之一。

使用 ES5:

var _a = 1;

function Obj() {}

Object.defineProperty(Obj.prototype, 'a', {
  enumerable: true,
  get: function () {
    return _a;  
  },
  set: function(val) {
    _a = val;
  }     
});

var obj = new Obj();
// or
var obj = Object.create(Obj.prototype);

或者使用 ES6 语法糖:

class Obj {
  constructor() {
    this._a = 1;
  }

  get a() {
    return this._a;
  }

  set a(val) {
    this._a = val;
  }     
}

let obj = new Obj();
哇,这一个简单的步骤 - 将吸气剂放入原型 - 使一切变得不同,这有点令人难以置信。
2021-05-13 14:51:31