2013-03-02 11 views
10

Może to wydawać się szczególnie niejasnym tematem, jednak staram się poprawić moje podstawy w całym języku JavaScript (w szczególności jego najlepszych i najbardziej wydajnych praktyk).Dlaczego definiowanie funkcji prototypowych JS jest osobno szybsze niż w słowniku?

Podczas testowania teorii w http://jsperf.com/ wymyśliłem niektórych dziwnych wyników:

Załóżmy, że mamy dwa "identyczne" prototypów, zdefiniowane następująco:

Object1

var Object1 = function() {} 

Object1.prototype.defaults = { 
    radius: 400, 
    up: 1 
} 

Object1.prototype.centerOffset = function() { 
    return this.defaults.radius*this.defaults.up; 
} 

Object2

var Object2 = function() {} 

Object2.prototype = { 
    defaults: { 
     radius: 400, 
     up: 1 
    }, 

    centerOffset: function() { 
     return this.defaults.radius*this.defaults.up; 
    } 
} 

Object1 ma spójne (jeśli marginalne: ~ 3%) przyspieszyć przewagę nad object2 podczas wykonywania następujących prostych czynności:

var o = new Object1(); 
var offset = o.centerOffset(); 

&

var o = new Object2(); 
var offset = o.centerOffset(); 

można uruchomić testy siebie here. Używam Chrome 25 na OS X 10.6.8.

Co chciałbym wiedzieć, jest to:

  • Jaki jest powód (y) dla tej różnicy wydajności?
  • Czy to przedstawienie wskazuje na jakąś najlepszą praktykę w javascript?

Z góry dzięki chłopaki.

EDYCJA: Dzięki za odpowiedzi - jak niektórzy wspomnieli, dalsze testy z mojej strony wydają się sugerować, że ten problem to przeglądarka (lub raczej specyficzny dla Javascriptu kompilator). Testowałem dodatkowo w Safari, IE 10 i Firefox. IE 10 i Firefox dały wyniki tak bliskie, że nie różnią się od siebie. Safari wykonał operacje na Object2 nieco szybciej niż te w Object1 (średnio około 2%). Chciałbym wiedzieć, co jest jednak wartością odstającą (Other), ponieważ różnica w wydajności w tym przypadku wydaje się być znaczna.

+0

To prawdopodobnie tylko wskazówka na dziwactwo V8. – delnan

+0

Miałem odwrotny wynik, uruchamiając firefox –

+0

Fascynujące, więc jego specyficzny kompilator ... Zrobię więcej testów przeglądarki i zgłoś się. –

Odpowiedz

3

Po zadeklarowaniu funkcji prototypowy atrybut jest inicjowany przez obiekt zawierający domyślny konstruktor.

W Object1 dodajesz atrybut do istniejącej funkcji prototypu. W Object2 zastępujesz istniejący prototyp własnym konstruktorem.

Dwa nie są identyczne.

Dlaczego prędkości są różne? Cóż, V8 może dodawać funkcję konstruktora do twojego prototypu object2 za każdym razem, gdy tworzysz instancję.

Albo, co bardziej prawdopodobne, wcześniejsza prototypowa funkcja jest zaimplementowana w kodzie maszynowym, aby była szybsza, a kiedy przypisujesz własny obiekt do prototypu Object2.prototype, funkcja prototypu jest teraz czystym javascript, a zatem wolniejsza.

Szczegóły nie są ważne, ponieważ różni tłumacze będą sobie z tym poradzić w różny sposób, ważne jest, aby zdać sobie sprawę, że Obiekty1 i Obiekt2 nie są dokładnie takie same.

+0

Podoba mi się twoja odpowiedź. Nie rozważałem możliwości optymalizacji implementacji, którą nadpisałem. –

+0

Zaakceptowałem twoją odpowiedź, ponieważ zawiera ona wyjaśnienia na temat tego, o co dokładnie prosiłem. Podejrzewam, że aby naprawdę zrozumieć szczegóły tego, co się tu dzieje, musiałbym odświeżyć moje umiejętności w C++ i spojrzeć na źródło Chromium/V8. –

0

Wydaje mi się, że ma coś takiego, jak dodanie prototypu w Object1 i nadpisanie go w Object2. Aby to sprawdzić, wykonałem drugi przykład wydajności: http://jsperf.com/correct-way-to-declare-prototype-functions/2

Tam dodałem "Object1.prototype = {}" przed przypisaniem funkcji. Wydajność jest teraz mniej więcej taka sama pomiędzy Object1 i Object2 (przynajmniej w chrome).

Powiązane problemy