2017-10-14 29 views
2

请帮助:) - 我不得不检查性能访问属性 - 工厂函数,连续继承和类,我不明白为什么连续继承失去?毕竟,对连续继承中复制的属性的访问应该是最快的。 我在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(); 
} 
+0

在边缘它是类和CI之间的联系,在Firefox中它是CI的胜利。所以你的问题是关于Webkit的实现细节 –

+0

你可以在问题中包含代码吗? – guest271314

+0

我觉得这个测试不够好。例如,您应该将更复杂的类与更多级别的继承进行比较。例如,假设你有一个10级的类层次结构。在一个版本中,您将所有内容连接到单个对象上,而在另一个版本中,您将会有一个长达10级的原型链。这个较长的原型链可能真的显示出性能的差异。 – trusktr

回答

1

毕竟,获得了继承的串连复制的属性应该是最快的。

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

嗯,这可能是一个很好的推理关于一个天真的引擎实现。但是你没有考虑专门针对继承的对象模型的优化,使(类)实例的方法访问速度非常快。看看https://github.com/v8/v8/wiki/Design%20Elements#fast-property-access,https://blog.ghaiklor.com/optimizations-tricks-in-v8-d284b6c8b183,http://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属性。所有这些属性可能包含相同的函数对象,但我们无法知道(我们不会猜测它 - 这是一种不寻常的模式)。因此,引擎在调用它之前每次都从每个实例中获取函数引用 - 至少它知道每个实例中的哪个(在哪个内存偏移量),因为它们的形状不变。