Вот моя попытка выполнить ваш запрос на тот случай, если вы искали альтернативы. Этот метод просто обрабатывает ошибки как допустимые результаты и кодируется аналогично

Мне интересно, есть ли какие-либо преимущества использования одного из них по сравнению с другим, и каким путем я должен идти?

Подход конструктора:

var Class = function () {

    this.calc = function (a, b) {
        return a   b;
    };

};

Подход прототипа:

var Class = function () {};

Class.prototype.calc = function (a, b) {
    return a   b;
};

Мне не нравится, используя прототип, определения методов отделены от класса, и я не знаю, есть ли какая-то конкретная причина, по которой я должен использовать это только первый подход.

Кроме того, есть ли преимущество использования литерала функции для определения «класса» по сравнению с просто определением функции:

var Class = function () {};

vs

function Class () {};

Спасибо!

Этот вопрос был задан ранее и уже имеет ответ. Если эти ответы не полностью отвечают на ваш вопрос, пожалуйста, задайте новый вопрос Глядя на вывод

Методы, которые наследуются через цепочку прототипов, могут быть изменены универсально для всех случаев, например:

function Class () {}
Class.prototype.calc = function (a, b) {
    return a   b;
}

// Create 2 instances:
var ins1 = new Class(),
    ins2 = new Class();

// Test the calc method:
console.log(ins1.calc(1,1), ins2.calc(1,1));
// -> 2, 2

// Change the prototype method
Class.prototype.calc = function () {
    var args = Array.prototype.slice.apply(arguments),
        res = 0, c;

    while (c = args.shift())
        res  = c;

    return res; 
}

// Test the calc method:
console.log(ins1.calc(1,1,1), ins2.calc(1,1,1));
// -> 3, 3

Обратите внимание, как изменение метода применяется к обоим случаи? Это потому, что ins1 и ins2 используют одну и ту же функцию calc(). Чтобы сделать это с открытыми методами, созданными во время построения, вам нужно будет назначить новый метод каждому созданному экземпляру, что является неудобной задачей. Это потому, что ins1 и ins2 будет иметь свои собственные, индивидуально созданные функции calc() функции.

Еще один побочный эффект создания методов внутри конструктора — более низкая производительность. Каждый метод должен создаваться каждый раз, когда запускается функция конструктора. Методы в цепочке прототипов создаются один раз, а затем «наследуются» каждым экземпляром. С другой стороны, публичные методы имеют доступ к «закрытым» переменным, что невозможно при использовании унаследованных методов.

Что касается вашего function Class() {}, что является фактической разницей между ними. Вы все еще можете использовать приведенный выше код Поттера, но просто повторить сравнение и в обратном направлении: var Class = function () {} вопроса, то первый из них «поднимается» до верхней части текущей области перед выполнением. В последнем случае объявление переменной выполняется, но не присваивается. Например:

// Error, fn is called before the function is assigned!
fn();
var fn = function () { alert("test!"); } 

// Works as expected: the fn2 declaration is hoisted above the call
fn2();
function fn2() { alert("test!"); }

Преимущество прототипа — эффективность. Существует один функциональный объект calc(), общий для всех Class объектов (я имею в виду объекты, созданные путем вызова конструктора Class). Другой способ (назначение методов в конструкторе) создает новый объект функции для каждого объекта Class, используя больше памяти и занимая больше времени при вызове конструктора Class. Однако этот подход имеет преимущество: метод calc() имеет доступ к локальным переменным в конструкторе, который вы можете использовать в своих интересах:

function Class() {
    var calcCallCount = 0;

    this.calc = function (a, b) {
          calcCallCount;
        alert("Calc called "   calcCallCount   " times");
        return a   b;
    };
};

Что касается var Class = function() {...} по сравнению с function Class() {...}, я обычно предпочитаю, потому что последний является это означает, что у функции есть имя, которое может быть полезно при отладке. Другое отличие состоит в том, что последняя версия (a Объявление функции ) поднята, что означает, что она доступна везде в пределах области, в которой она определена, а не только после определения. Тем не менее, некоторые люди предпочитают использовать первый ( Это очень просто реализовать. Вы можете использовать: ) везде.

var YourClass = function(){
  var privateField = "somevalue";
  this.publicField = "somevalue";
  this.instanceMethod1 = function(){
     //you may access both private and public field from here:
     //in order to access public field, you must use "this":
     alert(privateField   "; "   this.publicField);
  };
}

YourClass.prototype.instanceMethod2 = function(){
  //you may access only public field 2 from this method, but not private fields:
  alert(this.publicField);
  //error: drawaback of prototype methods:
  alert(privateField);  
};

Преимущества методов-прототипов:

  1. Когда вы определяете методы через прототип, они распределяются между всеми экземплярами YourClass. В результате общий размер таких экземпляров равен & Lt ;, чем при определении методов в конструкторе ;. Существуют тесты, которые показывают, как определение метода с помощью прототипа уменьшает общий размер HTML-страницы и в результате скорость его загрузки.

  2. еще одно преимущество методов, определенных с помощью прототипа, — когда вы используете унаследованные классы, вы можете переопределять такие методы, а в переопределенном методе производного класса вы можете вызывать метод базового класса с тем же именем, но с определенными методами. в конструкторе вы не можете сделать это.

Прежде всего, вы должны использовать литерал объекта следующим образом:

var Class = {
  calc: function (a, b) {
    return a   b;
  }
};

Эта запись более чистая, а также делает очевидным, что в Javascript объекты — это просто хеши, а не что-то из рецепта, как предопределенный класс.

Разница между определениями заключается в том, что если вы добавите метод к прототипу, в памяти будет создан только один метод для всех экземпляров. Поэтому, если у вас есть универсальный метод и объект, который создается / используется в нескольких экземплярах, вы должны добавить метод в прототип.