Статьи

JavaScript: возвращать или не возвращать, вот в чем вопрос!

Вы хотите обсудить эту статью? Пинг мне в твиттере !

При разработке API Babylon.js я недавно обнаружил, что некоторые API могут потребовать более свободного владения .

образ

Свободно API , как указано на этой статье Википедии является реализация объектно — ориентированного API , который направлен на обеспечение более читаемый код. Например, jQuery является отличным примером того, что позволяет делать свободный API:

 $('<div></div>')
     .html("Fluent API are cool!")
     .addClass("header")
     .appendTo("body");

Свободный API позволяет связывать вызовы функций, возвращая этот объект.

Мы можем легко создать свободный API, как это:

var MyClass = function(a) {
    this.a = a;
}

MyClass.prototype.foo = function(b) {
    // Do some complex work   
    this.a += Math.cos(b);
    return this;
}

Как видите, хитрость заключается в возвращении объекта this (в данном случае ссылки на текущий экземпляр), чтобы цепочка могла продолжаться.

Если вы не знаете, как работает ключевое слово « this» в JavaScript, я рекомендую прочитать эту замечательную статью Майка Веста .

Затем мы можем цепочки вызовов:

var obj = new MyClass(5);
obj.foo(1).foo(2).foo(3);

Прежде чем попытаться сделать то же самое с babylon.js, я хотел быть уверен, что это не вызовет проблем с производительностью.

Итак, я сделал тест!

var count = 10000000;

var MyClass = function(a) {
    this.a = a;
}

MyClass.prototype.foo = function(b) {
    // Do some complex work   
    this.a += Math.cos(b);
    return this;
}

MyClass.prototype.foo2 = function (b) {
    // Do some complex work   
    this.a += Math.cos(b);
}

var start = new Date().getTime();
var obj = new MyClass(5);
obj.foo(1).foo(2).foo(3);
for (var index = 0; index < count; index++) {
    obj.foo(1).foo(2).foo(3);
}
var end = new Date().getTime();

var start2 = new Date().getTime();
var obj2 = new MyClass(5);
for (var index = 0; index < count; index++) {
    obj2.foo2(1);
    obj2.foo2(2);
    obj2.foo2(3);
}
var end2 = new Date().getTime();

var div = document.getElementById("results");

div.innerHTML += obj.a + ": With return this: " + (end - start) + "ms<BR>";
div.innerHTML += obj2.a + ": Without return this: " + (end2 - start2) + "ms";

Как вы можете видеть,
foo и
foo2 делают одно и то же. Единственная разница в том, что
foo может быть цепочкой, а
foo2 — нет.

Очевидно, что цепочка вызовов отличается между:

obj.foo(1).foo(2).foo(3);

и

obj2.foo2(1);
obj2.foo2(2);
obj2.foo2(3);

Учитывая этот код, я запустил его в Chrome, Firefox и IE, чтобы определить, нужно ли мне беспокоиться о производительности.

образ

И вот результаты, которые я получил:

  • В Chrome обычный API работает на 6% медленнее, чем свободный API
  • В Firefox оба API почти работают с одинаковой скоростью (свободный API на 1% медленнее)
  • В IE оба API работают почти с одинаковой скоростью (свободный API на 2% медленнее)

Дело в том, что я добавил в функцию операцию ( Math.cos ), чтобы имитировать какую-то обработку, выполняемую функцией.

Если я удаляю все и просто сохраняю оператор return , во всех браузерах нет разницы (на самом деле, всего одна или две миллисекунды на 10 000 000 попыток).Мужской знак рукой с пальца вверх.  Изолированная концепция

Итак, мой вывод: это пошло!

Свободный API великолепен, он генерирует более читаемый код, и вы можете использовать его без проблем или потери производительности !