访问属性的性能 - 工厂函数与连接继承与类

时间:2017-10-14 21:05:14

标签: javascript performance inheritance

请帮助:) - 我必须检查访问属性的性能 - 工厂函数,连接继承和类,我不明白为什么连接继承失败?毕竟,对Concatenative继承中复制的属性的访问应该是最快的。 我在Chrome和Safari上运行测试,CI总是丢失。 https://jsperf.com/factory-function-vs-concatenative-inheritance-get

此测试的代码:

const alien = {
    sayHello () {
      return `Hello, my name is ${ this.name }`;
    }
  };
  //Delegate prototype
  const createAlienFF = (name) => { 
     return Object.assign(Object.create(alien), {
       name
    });
  }
   //Delegate prototype - creating objects
  var tabFF = [];
  for(var i = 0; i < 1000; i++ ) {
     tabFF[i] = createAlienFF('Clark' + i);
  }

  //Concatenative inheritance
  const createAlienCI = (name) => { 
     return Object.assign( 
      {}, 
      alien, 
      {name: name}
    );
  }
  //Concatenative inheritance - creating objects
  var tabCI = [];
  for(var i = 0; i < 1000; i++ ) {
     tabCI[i] =  createAlienCI("Clark" + i );
  }

  //Class
  class Alien {
    constructor(name) {
      this.name = name
    }
    sayHello() {
      return `Hello, my name is ${ this.name }`;
    }
  }
  //Class - creating objects
  var tabClass = [];
  for(var i = 0; i < 1000; i++ ) {
     tabClass[i] = new Alien("Clark" + i );
  }
  //Tests
  //1 - Delegate prototype
  for(var i = 0; i < 1000; i++ ) {
    tabFF[i].sayHello();
  }

 //2 - Concatenative inheritance
 for(var i = 0; i < 1000; i++ ) {
  tabCI[i].sayHello();
 }

//3 - Class
for(var i = 0; i < 1000; i++ ) {
  tabClass[i].sayHello();
}

1 个答案:

答案 0 :(得分:1)

  

毕竟,访问Concatenative继承中复制的属性应该是最快的。

你为什么这么认为?因为它是一个直接的属性访问,不需要遍历原型链?

嗯,这可能是关于天真引擎实施的一个很好的推理。但是你没有考虑专门针对继承而定制的对象模型的优化,使得(类)实例上的方法访问速度极快。请查看https://github.com/v8/v8/wiki/Design%20Elements#fast-property-accesshttps://blog.ghaiklor.com/optimizations-tricks-in-v8-d284b6c8b183http://richardartoul.github.io/jekyll/update/2015/04/26/hidden-classes.html和伟大的http://mrale.ph/blog/2012/06/03/explaining-js-vms-in-js-inline-caches.html。要点:V8优化了对“已知形状”对象的方法访问,即在您的情况下继承自alienAlien.prototype的对象(它们共享相同的隐藏类 )。它知道猜测在你的循环中,只使用那个形状的对象,并且可以推断它们都调用完全相同的sayHello函数。这是从中获取代码的恒定位置,甚至可以进行进一步的优化,例如内联。另一方面,createAlienCI工厂创建的对象也都共享相同的形状,但每个对象都包含其单独的sayHello属性。所有这些属性可能包含相同的函数对象,但我们无法知道(我们不会猜测它 - 这是一个不寻常的模式)。因此,引擎每次调用它之前都会从每个实例中获取函数引用 - 至少它知道每个实例中的哪个(在哪个内存偏移处)看起来因为它们的形状不变。

相关问题