Какие методы можно использовать для определения класса в JavaScript и каковы их компромиссы?

Я предпочитаю использовать ООП в крупномасштабных проектах, подобных тому, над которым я сейчас работаю. Мне нужно создать несколько классов в JavaScript, но, если я не ошибаюсь, есть как минимум несколько способов сделать это. Каков будет синтаксис и почему это должно быть сделано именно так?

Я бы хотел избежать использования сторонних библиотек - по крайней мере, на первых порах. В поисках других ответов я нашел статью Объектно-ориентированное программирование с помощью JavaScript, часть I. Наследование - Doc JavaScript, в которой обсуждается объектно-ориентированное программирование на JavaScript. Есть ли лучший способ наследования?

примечание: это дубликат stackoverflow.com/questions/355848

Jason S 23.12.2008 18:32

Лично мне нравится объявлять члены класса внутри тела функции. Я использую технику «исправления этого», чтобы создать замыкание, чтобы заставить его вести себя как класс. В моем блоге есть подробный пример: ncombo.wordpress.com/2012/12/30/…

Jon 30.12.2012 14:21

Я перенес большую часть функциональных возможностей C++ ООП на JavaScript с простым и естественным синтаксисом. Смотрите мой ответ здесь: stackoverflow.com/a/18239463/1115652

user1115652 14.08.2013 22:54

В JavaScript нет классов. Но если вы хотите смоделировать поведение класса в JS, вы можете. См. Подробности в: symfony-world.blogspot.com/2013/10/…

ducin 24.10.2013 01:53

Простой подход к определению класса Javascript с использованием объектов javascript: wapgee.com/story/i/203

Ilyas karim 21.05.2017 18:04

Обратите внимание, что с 2015 года этот вопрос решается напрямую с помощью собственных возможностей класса. См. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

patrickgamer 06.08.2017 14:56

@karim Ссылка на статью, которую вы упомянули в своем вопросе, не работает.

Sander Vanden Hautte 28.02.2018 11:30
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
691
8
330 461
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

Ответ принят как подходящий

Вот способ сделать это без использования каких-либо внешних библиотек:

// Define a class like this
function Person(name, gender){

   // Add object properties like this
   this.name = name;
   this.gender = gender;
}

// Add methods like this.  All Person objects will be able to invoke this
Person.prototype.speak = function(){
    alert("Howdy, my name is" + this.name);
};

// Instantiate new objects with 'new'
var person = new Person("Bob", "M");

// Invoke methods like this
person.speak(); // alerts "Howdy, my name is Bob"

Настоящий ответ намного сложнее. Например, в JavaScript нет такого понятия, как классы. JavaScript использует схему наследования на основе prototype.

Кроме того, существует множество популярных библиотек JavaScript, которые имеют свой собственный стиль аппроксимации функциональных возможностей классов в JavaScript. Вы захотите проверить как минимум Опытный образец и jQuery.

Решение, какое из них является «лучшим», - отличный способ начать священную войну против Stack Overflow. Если вы приступаете к большему проекту с большим количеством JavaScript, определенно стоит изучить популярную библиотеку и делать это по-своему. Я сторонник прототипов, но Stack Overflow, похоже, склоняется к jQuery.

Поскольку существует только «один способ сделать это», без каких-либо зависимостей от внешних библиотек, способ, которым я написал, в значительной степени соответствует.

Но он работает не так, как язык X, где я узнал единственный верный способ, которым должна работать штука, которая используется для создания экземпляров объектов :(

Erik Reppen 16.10.2013 06:23

Согласно developer.mozilla.org/en-US/docs/Web/JavaScript/… свойства также должны быть добавлены к прототипу ("Person.prototype.name = '';")

DaveD 31.03.2014 22:54

@DaveD - может быть, но, похоже, больше не ..?

Kieren Johnstone 17.06.2014 11:34

@ kieren-johnstone Похоже, они удалили это

DaveD 18.06.2014 21:26

Прототип часто упускают из виду из-за методов ... Обратите внимание на большую разницу в производительности. Создание прототипов свойств объекта - не такая уж важная задача, и сложнее понять, когда вам следует / не следует этого делать. jsperf.com/asdffafaal/2

BRogers 23.06.2014 23:01

jQuery даже не дает возможности создать классовую функциональность ??? (Все классы, которые он имеет, являются классами CSS) Вы должны удалить его из этой части ответа.

Bergi 12.07.2014 13:53

Со второй половины 2015 года был выпущен новый стандарт EcmaScript 6, поэтому я предлагаю сделать это по-новому (намного чище и проще) es6-features.org/#ClassDefinition

DevWL 24.03.2016 09:08

Ваша ссылка "склоняться к jQuery" не работает.

adamdport 25.04.2016 18:49

Если вы стремитесь к простоте, вы можете полностью отказаться от ключевого слова «new» и просто использовать фабричные методы. Иногда я предпочитаю это, потому что мне нравится использовать JSON для создания объектов.

function getSomeObj(var1, var2){
  var obj = {
     instancevar1: var1,
     instancevar2: var2,
     someMethod: function(param)
     {  
          //stuff; 
     }
  };
  return obj;
}

var myobj = getSomeObj("var1", "var2");
myobj.someMethod("bla");

Однако я не уверен, насколько сильно снизится производительность для больших объектов.

Строка obj.instancevar1 = var1 не нужна, поскольку внутренний объект будет иметь доступ к параметрам getSomeObj ().

Triptych 23.12.2008 02:28

Ух ты. У меня болит мозг, но в этом есть определенная элегантность. Полагаю, часть «obj.instancevar1 = var1» - это начало своего рода конструктора?

Karim 23.12.2008 02:28

Только что видел комментарий Триптиха. Я понимаю. Итак, вы можете просто сделать что-то вроде instancevar1: var1, где создается экземпляр внутреннего объекта.

Karim 23.12.2008 02:29

Точно ... когда вы используете {} для определения объекта, он имеет доступ к переменным, которые в настоящее время находятся в области видимости.

Sam 23.12.2008 02:32

Кроме того, нет ключевого слова private, поэтому даже вне getSomeObj () вы можете получить / установить instancevar1. Как только вы получите закрытие и ключевое слово «this», вы станете золотым. Javascript - довольно красивый и гибкий язык.

Sam 23.12.2008 02:37

При таком подходе вы теряете возможность наследования, и, поскольку вы не используете obj.prototype.something, вы определяете функции каждый раз, когда используете объект = больше памяти и медленнее.

some 23.12.2008 07:10

Это очень полезно. Похоже, что это больше похоже на естественный поток JavaScript, если вы принимаете его как есть, который затем настраивает вас для создания и связывания объектов теперь, когда фабрика отправляет их!

klewis 02.06.2018 00:18

JavaScript - это объектно-ориентированный, но он радикально отличается от других языков ООП, таких как Java, C# или C++. Не пытайтесь так понять это. Выбросьте старые знания и начните заново. JavaScript требует другого мышления.

Я бы посоветовал получить хорошее руководство или что-то по этому поводу. Я сам нашел Руководства по ExtJS лучшим для меня, хотя я не использовал фреймворк до или после его прочтения. Но он дает хорошее объяснение того, что есть что в мире JavaScript. Извините, похоже, что этот контент был удален. Вот вместо этого ссылка на archive.org копия. Работает сегодня. :П

Объектно-ориентированный? Я думал, что это функциональный.

Peter Mortensen 03.08.2013 10:28

Ссылка "ExtJS Tutorials" не работает.

Peter Mortensen 03.08.2013 10:28

Я думаю, было бы более пояснительно объяснить, что функции в javascript являются объектами, а правила javascript с ограниченными скобками делают каждый функциональный блок инкапсулированным.

mibbit 17.09.2018 04:31

Самый простой способ:

function Foo(a) {
  var that=this;

  function privateMethod() { .. }

  // public methods
  that.add = function(b) {
    return a + b;
  };
  that.avg = function(b) {
    return that.add(b) / 2; // calling another public method
  };
}

var x = new Foo(10);
alert(x.add(2)); // 12
alert(x.avg(20)); // 15

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

Обновлено: это определенно не лучший способ, просто простой способ. Жду и хороших ответов!

Конструкция that = this здесь не нужна. Кроме того, методы add () и avg () будут скопированы для каждого «экземпляра» класса Foo, а не будут совместно использоваться ими.

Triptych 23.12.2008 02:36

Это необходимо (вроде как) в таком случае, но не в том простом случае, который вы указали.

Triptych 23.12.2008 19:35

Я думаю, вам следует прочитать Прототипное наследование в JavaScript и Классическое наследование в JavaScript Дугласа Крокфорда.

Примеры с его страницы:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

Эффект? Это позволит вам более элегантно добавлять методы:

function Parenizor(value) {
    this.setValue(value);
}

Parenizor.method('setValue', function (value) {
    this.value = value;
    return this;
});

Также рекомендую его видео: Продвинутый JavaScript.

Больше видео вы можете найти на его странице: http://javascript.crockford.com/ В книге Джона Рейзига вы можете найти множество примеров с веб-сайта Дугласа Крокфора.

Это только я? Как, черт возьми, это элегантнее? Я бы назвал определения функций фактическим 'strings', так как называет многие вещи, но элегантность не входит в их число ...

fgysin reinstate Monica 16.01.2013 16:28

@JAB, но отражение - это исключение, а не правило. С помощью вышеуказанного метода вы должны объявите все свои методы со строками.

Kirk Woll 22.12.2013 21:05

Лучший способ определить класс в JavaScript - не определять класс.

Шутки в сторону.

Существует несколько разновидностей объектной ориентации, некоторые из них:

  • объектно-ориентированный объект на основе классов (впервые представленный Smalltalk)
  • объектно-ориентированный объект на основе прототипов (впервые представленный Self)
  • многометодный объектно-ориентированный объект (я думаю, впервые представленный CommonLoops)
  • объектно-ориентированный объект на основе предикатов (без понятия)

И, вероятно, другие, о которых я не знаю.

JavaScript реализует объектно-ориентированный объект на основе прототипов. В объектно-ориентированном методе на основе прототипов новые объекты создаются путем копирования других объектов (вместо создания экземпляров из шаблона класса), а методы живут непосредственно в объектах, а не в классах. Наследование осуществляется через делегирование: если объект не имеет метода или свойства, он просматривается по его прототипу (-ам) (то есть по объекту, из которого он был клонирован), затем по прототипам прототипа и так далее.

Другими словами: классов нет.

На самом деле в JavaScript есть хорошая доработка этой модели: конструкторы. Вы можете не только создавать объекты, копируя существующие, вы также можете создавать их, так сказать, «из воздуха». Если вы вызываете функцию с ключевым словом new, эта функция становится конструктором, а ключевое слово this будет указывать не на текущий объект, а на вновь созданный «пустой» объект. Итак, вы можете настроить объект как хотите. Таким образом, конструкторы JavaScript могут взять на себя одну из ролей классов в традиционном объектно-ориентированном пространстве на основе классов: служить шаблоном или схемой для новых объектов.

Итак, JavaScript - очень мощный язык, поэтому при желании довольно легко реализовать объектно-ориентированную систему в JavaScript на основе классов. Однако вы должны делать это только в том случае, если вам это действительно нужно, а не только потому, что это делает Java.

«Если вы вызываете функцию с ключевым словом new, эта функция становится конструктором, и ключевое слово this будет указывать не на текущий объект, а на вновь созданный« пустой »объект. Если вы вызываете функцию без ключевого слова new, это будет относиться к контексту вызова, по умолчанию глобальному объекту (окну). В строгом режиме по умолчанию используется значение undefined. call, apply и bind принимает контекст вызова в качестве первого параметра. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Elias Hasle 03.05.2019 11:18

Поскольку я не соглашусь с планом фабрики YUI / Crockford и потому, что мне нравится сохранять все самодостаточными и расширяемыми, это мой вариант:

function Person(params)
{
  this.name = params.name || defaultnamevalue;
  this.role = params.role || defaultrolevalue;

  if (typeof(this.speak)=='undefined') //guarantees one time prototyping
  {
    Person.prototype.speak = function() {/* do whatever */};
  }
}

var Robert = new Person({name:'Bob'});

где в идеале тип теста - это что-то вроде прототипа первого метода

Мне это нравится. Я чаще всего использую стандартный синтаксис JS, потому что мне не нравится идея копирования функций в каждый экземпляр объекта. Я всегда скучал по красоте автономного решения, и это неплохо его решает.

Lukasz Korzybski 03.02.2011 17:50

Не уверен, но я понял, что определение функции-прототипа внутри области (что-то вроде закрытия) функции приводит к утечке памяти, поскольку сборщик мусора не может попасть туда в экземпляре этих классов.

Sanne 27.07.2014 01:51

MooTools (Мои объектно-ориентированные инструменты) основан на идее классы. Вы даже можете расширить и реализовать с помощью наследования.

После освоения он создает невероятно многоразовый мощный javascript.

var Animal = function(options) {
    var name = options.name;
    var animal = {};

    animal.getName = function() {
        return name;
    };

    var somePrivateMethod = function() {

    };

    return animal;
};

// usage
var cat = Animal({name: 'tiger'});

Это очень элегантный способ создать пригодную для использования структуру объекта без необходимости чего-либо импортировать. Я использовал систему классов Resig, но, возможно, она мне больше понравится. Спасибо.

Tim Scollick 03.09.2013 19:55

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

Justin 14.10.2013 21:29

Я предпочитаю использовать {SUPER: SYSTEM} Дэниела X. Мура. Это дисциплина, которая обеспечивает такие преимущества, как истинные переменные экземпляра, наследование на основе признаков, иерархии классов и параметры конфигурации. В приведенном ниже примере показано использование истинных переменных экземпляра, что, по моему мнению, является самым большим преимуществом. Если вам не нужны переменные экземпляра и вас устраивают только общедоступные или частные переменные, возможно, существуют более простые системы.

function Person(I) {
  I = I || {};

  Object.reverseMerge(I, {
    name: "McLovin",
    age: 25,
    homeState: "Hawaii"
  });

  return {
    introduce: function() {
      return "Hi I'm " + I.name + " and I'm " + I.age;
    }
  };
}

var fogel = Person({
  age: "old enough"
});
fogel.introduce(); // "Hi I'm McLovin and I'm old enough"

Вау, это само по себе не очень полезно, но взгляните на добавление подкласса:

function Ninja(I) {
  I = I || {};

  Object.reverseMerge(I, {
    belt: "black"
  });

  // Ninja is a subclass of person
  return Object.extend(Person(I), {
    greetChallenger: function() {
      return "In all my " + I.age + " years as a ninja, I've never met a challenger as worthy as you...";
    }
  });
}

var resig = Ninja({name: "John Resig"});

resig.introduce(); // "Hi I'm John Resig and I'm 25"

Еще одно преимущество - возможность наследования на основе модулей и признаков.

// The Bindable module
function Bindable() {

  var eventCallbacks = {};

  return {
    bind: function(event, callback) {
      eventCallbacks[event] = eventCallbacks[event] || [];

      eventCallbacks[event].push(callback);
    },

    trigger: function(event) {
      var callbacks = eventCallbacks[event];

      if (callbacks && callbacks.length) {
        var self = this;
        callbacks.forEach(function(callback) {
          callback(self);
        });
      }
    },
  };
}

Пример того, что класс person включает привязываемый модуль.

function Person(I) {
  I = I || {};

  Object.reverseMerge(I, {
    name: "McLovin",
    age: 25,
    homeState: "Hawaii"
  });

  var self = {
    introduce: function() {
      return "Hi I'm " + I.name + " and I'm " + I.age;
    }
  };

  // Including the Bindable module
  Object.extend(self, Bindable());

  return self;
}

var person = Person();
person.bind("eat", function() {
  alert(person.introduce() + " and I'm eating!");
});

person.trigger("eat"); // Blasts the alert!

Раскрытие информации: я Дэниел Икс Мур, а это мой {SUPER: SYSTEM}. Это лучший способ определить класс в JavaScript.

@DanielXMoore «Переменные экземпляра совместно используются отдельными экземплярами класса» Это не переменные экземпляра, это статические переменные / переменные класса.

JAB 02.07.2013 23:05

@JAB Это неверно, статические переменные / переменные класса совместно используются экземплярами все класса. У каждого экземпляра есть свои собственные переменные экземпляра.

Daniel X Moore 02.07.2013 23:34

(Другими словами, используя обычное значение термина «переменная экземпляра», независимо от того, является ли переменная единицей, ортогональна уровню доступности переменной.)

JAB 02.07.2013 23:55

Вы почти походили на супергероя за то, что претендовали на лучший xD

Dadan 14.09.2016 13:23

Простой подход к определению класса Javascript с использованием объектов javascript: wapgee.com/story/i/203

Ilyas karim 21.05.2017 18:04

Ниже приведены способы создания объектов в javascript, которые я использовал до сих пор.

Пример 1:

obj = new Object();
obj.name = 'test';
obj.sayHello = function() {
    console.info('Hello '+ this.name);
}

Пример 2:

obj = {};
obj.name = 'test';
obj.sayHello = function() {
    console.info('Hello '+ this.name);
}
obj.sayHello();

Пример 3:

var obj = function(nameParam) {
    this.name = nameParam;
}
obj.prototype.sayHello = function() {
    console.info('Hello '+ this.name);
}

Пример 4: Фактические преимущества Object.create (). пожалуйста, обратитесь [эта ссылка]

var Obj = {
    init: function(nameParam) {
        this.name = nameParam;
    },
    sayHello: function() {
        console.info('Hello '+ this.name);
    }
};
var usrObj = Object.create(Obj);  // <== one level of inheritance

usrObj.init('Bob');
usrObj.sayHello();

Пример 5 (настроенный объект Крокфорда Object.create):

Object.build = function(o) {
   var initArgs = Array.prototype.slice.call(arguments,1)
   function F() {
      if ((typeof o.init === 'function') && initArgs.length) {
         o.init.apply(this,initArgs)
      }
   }
   F.prototype = o
   return new F()
}
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}}  // For example

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.info('Hello '+ this.name);
    }
};
var bob = Object.build(userB, 'Bob');  // Different from your code
bob.sayHello();


To keep answer updated with ES6/ ES2015

Класс определяется так:

class Person {
    constructor(strName, numAge) {
        this.name = strName;
        this.age = numAge;
    }

    toString() {
        return '((Class::Person) named ' + this.name + ' & of age ' + this.age + ')';
    }
}

let objPerson = new Person("Bob",33);
console.info(objPerson.toString());

@Justin: Пожалуйста, дайте мне знать, что недействительно?

Amol M Kulkarni 12.08.2015 10:24

Изучая эти обозначения, я также наткнулся на this.set (). Например: this.set ('порт', 3000). Я предполагаю, что это используется для установки свойства порта для объекта. Если да, то почему мы не используем напрямую: {порт: 3000}. Есть ли документация, по которой я могу получить более подробную информацию.

adityah 24.06.2017 00:22

Вероятно, вы захотите создать шрифт с помощью шаблона складывания:

    // Here is the constructor section.
    var myType = function () {
        var N = {}, // Enclosed (private) members are here.
            X = this; // Exposed (public) members are here.

        (function ENCLOSED_FIELDS() {
            N.toggle = false;
            N.text = '';
        }());

        (function EXPOSED_FIELDS() {
            X.count = 0;
            X.numbers = [1, 2, 3];
        }());

        // The properties below have access to the enclosed fields.
        // Careful with functions exposed within the closure of the
        // constructor, each new instance will have it's own copy.
        (function EXPOSED_PROPERTIES_WITHIN_CONSTRUCTOR() {
            Object.defineProperty(X, 'toggle', {
                get: function () {
                    var before = N.toggle;
                    N.toggle = !N.toggle;
                    return before;
                }
            });

            Object.defineProperty(X, 'text', {
                get: function () {
                    return N.text;
                },
                set: function (value) {
                    N.text = value;
                }
            });
        }());
    };

    // Here is the prototype section.
    (function PROTOTYPE() {
        var P = myType.prototype;

        (function EXPOSED_PROPERTIES_WITHIN_PROTOTYPE() {
            Object.defineProperty(P, 'numberLength', {
                get: function () {
                    return this.numbers.length;
                }
            });
        }());

        (function EXPOSED_METHODS() {
            P.incrementNumbersByCount = function () {
                var i;
                for (i = 0; i < this.numbers.length; i++) {
                    this.numbers[i] += this.count;
                }
            };
            P.tweak = function () {
                if (this.toggle) {
                    this.count++;
                }
                this.text = 'tweaked';
            };
        }());
    }());

Этот код даст вам тип под названием мой тип. У него будут внутренние частные поля, называемые переключать и текст. Он также будет иметь следующие открытые элементы: поля считать и числа; свойства переключать, текст и numberLength; методы incrementNumbersByCount и поправить.

Схема складывания подробно описана здесь: Шаблон складывания Javascript

Классы ES2015

В спецификации ES2015 вы можете использовать синтаксис класса, который просто сахар по сравнению с системой-прототипом.

class Person {
  constructor(name) {
    this.name = name;
  }
  toString() {
    return `My name is ${ this.name }.`;
  }
}

class Employee extends Person {
  constructor(name, hours) {
    super(name);
    this.hours = hours;
  }
  toString() {
    return `${ super.toString() } I work ${ this.hours } hours.`;
  }
}

Преимущества

Основное преимущество заключается в том, что инструментам статического анализа легче ориентироваться на этот синтаксис. Другим, пришедшим из языков на основе классов, также проще использовать этот язык в качестве многоязычного.

Предостережения

Остерегайтесь его текущих ограничений. Чтобы получить частные свойства, нужно прибегнуть к с использованием символов или WeakMaps. В будущих выпусках классы, скорее всего, будут расширены за счет включения этих недостающих функций.

Служба поддержки

Поддержка браузера на данный момент не очень хорош (поддерживается почти всеми, кроме IE), но теперь вы можете использовать эти функции с транспилером, таким как Вавилон.

Ресурсы

Объектные классы с наследованием

var baseObject = 
{
     // Replication / Constructor function
     new : function(){
         return Object.create(this);   
     },

    aProperty : null,
    aMethod : function(param){
      alert("Heres your " + param + "!");
    },
}


newObject = baseObject.new();
newObject.aProperty = "Hello";

anotherObject = Object.create(baseObject); 
anotherObject.aProperty = "There";

console.info(newObject.aProperty) // "Hello"
console.info(anotherObject.aProperty) // "There"
console.info(baseObject.aProperty) // null

Просто, мило, и все готово.

var Student = (function () {
    function Student(firstname, lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.fullname = firstname + " " + lastname;
    }

    Student.prototype.sayMyName = function () {
        return this.fullname;
    };

    return Student;
}());

var user = new Student("Jane", "User");
var user_fullname = user.sayMyName();

Так TypeScript компилирует класс с конструктором в JavaScript.

Используйте гольф для отвечать @ liammclennan.

var Animal = function (args) {
  return {
    name: args.name,

    getName: function () {
      return this.name; // member access
    },

    callGetName: function () {
      return this.getName(); // method call
    }
  };
};

var cat = Animal({ name: 'tiger' });
console.info(cat.callGetName());

База

function Base(kind) {
    this.kind = kind;
}

Класс

// Shared var
var _greeting;

(function _init() {
    Class.prototype = new Base();
    Class.prototype.constructor = Class;
    Class.prototype.log = function() { _log.apply(this, arguments); }
    _greeting = "Good afternoon!";
})();

function Class(name, kind) {
    Base.call(this, kind);
    this.name = name;
}

// Shared function
function _log() {
    console.info(_greeting + " Me name is " + this.name + " and I'm a " + this.kind);
}

Действие

var c = new Class("Joe", "Object");
c.log(); // "Good afternoon! Me name is Joe and I'm a Object"

На примере Триптиха это может быть еще проще:

    // Define a class and instantiate it
    var ThePerson = new function Person(name, gender) {
        // Add class data members
        this.name = name;
        this.gender = gender;
        // Add class methods
        this.hello = function () { alert('Hello, this is ' + this.name); }
    }("Bob", "M"); // this instantiates the 'new' object

    // Use the object
    ThePerson.hello(); // alerts "Hello, this is Bob"

Это создает только один экземпляр объекта, но все же полезно, если вы хотите инкапсулировать набор имен для переменных и методов в классе. Обычно для конструктора не было бы аргументов «Bob, M», например, если бы методы были вызовами системы с ее собственными данными, такой как база данных или сеть.

Я все еще слишком новичок в JS, чтобы понять, почему здесь не используется prototype.

//new way using this and new
function Persons(name) {
  this.name = name;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}

var gee=new Persons("gee");
gee.greeting();

var gray=new Persons("gray");
gray.greeting();

//old way
function createPerson(name){
 var obj = {};
 obj.name=name;
 obj.greeting = function(){
 console.info("hello I am"+obj.name);
 }; 
  return obj;
}

var gita=createPerson('Gita');
gita.greeting();

отлично, что действительно немного похоже на синтаксис класса. почти дерьмо @ user1115652 предлагает: «Я перенес большую часть функциональных возможностей C++ ООП на JavaScript с помощью простого и естественного синтаксиса. См. мой ответ здесь: stackoverflow.com/a/18239463/1115652»

SL5net 28.06.2020 09:42

Другие вопросы по теме