Javascript: В чем разница между функцией и classом

С выпуском ECMAScript 6 в июне 2015 года был введен синтаксис classов Javascript.

Этот синтаксис:

class Polygon { constructor(width, height) { this.width = width; this.height = height; } } 

в основном такой же, как:

 function Polygon(width, height) { this.width = width; this.height = height; } 

Итак, в чем преимущество использования classа вместо традиционной функции? И в каком состоянии я должен использовать class вместо функции?

Есть некоторые отличия между Class и Function – большинство людей начнут с того, что class будет «просто синтаксическим сахаром», но этот сахар имеет значение совсем немного. Когда парсер JS обрабатывает код JavaScript, парсер будет сохранять их в разных узлах AST, как показано здесь, ClassDeclaration и ClassExpression – это разные типы узлов в полученном дереве AST:

https://github.com/estree/estree/blob/master/es2015.md#classes

Вы можете видеть, что для этого анализатора новая спецификация classов ES6 вводит в новый синтаксис ряд новых элементов AST:

  • ClassBody
  • MethodDefinition
  • ClassDeclaration
  • ClassExpression
  • MetaProperty

Поскольку синтаксис AST не является стандартным, в зависимости от синтаксического анализа может быть больше или меньше типов, но важно заметить, что когда код вводит объявление classа или выражение classа, он будет интерпретироваться по-разному с помощью механизма JavaScript.

Это означает, что объявления classа и функции не могут быть обменены. Вы можете это увидеть, если попытаетесь написать

 class notWorking { return 1; // <-- creates a parser error }; 

Это связано с тем, что когда парсер встречает ключевое слово classа, он начнет рассматривать следующий код как ClassBody как ClassDeclaration, так и ClassExpression, а затем он expexts, чтобы найти MethodDefinitions.

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

 function myClass() { var privateVar; } 

Объявление classа не может иметь этого:

 class myClass { var privateVar; // ERROR: should be a method } 

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

Однако существует предложение о создании частных полей:

https://github.com/zenparsing/es-private-fields

Таким образом, в будущем вы могли бы сказать

 class myClass { #privateVar; // maybe this works in the future? } 

Существует отдельный ответ, рассматривающий частные свойства в classах ES6, что предполагает некоторые обходные пути, такие как использование символов:

Частные объекты в JavaScript ES6 classы

 var property = Symbol(); // private property workaround example class Something { constructor(){ this[property] = "test"; } } 

Естественно, что существуют различия между classами и функциями. Один из них - Подъем 1 - в отличие от функций, вы не можете объявить class в любом месте области:

Важное различие между декларациями функций и объявлениями classов состоит в том, что объявления функций поднимаются, а объявления classов - нет. Сначала вам нужно объявить свой class, а затем получить доступ к нему

Объявления classов и объявления функций очень похожи;

 function foo1() {} // can be used before declaration class foo2{} // new foo2(); works only after this declaration 

Выражения classа работают аналогично эксцессам функции, например, они могут быть назначены переменной:

 var myClass = class foobar {}; 

Больше различий 1

  1. Тело exression / declaration classа всегда выполняется в строгом режиме - не нужно указывать, что вручную
  2. Классы имеют специальный конструктор ключевых слов - может быть только один из них, или возникает ошибка. Функции могут иметь несколько определений переменной функции с именем «конструктор»,
  3. Классы имеют специальное ключевое слово super, которое относится к конструктору родительских classов. Если вы находитесь внутри конструктора, вы можете вызвать super (x, y); для вызова конструктора родительского classа, но внутри метода вы можете вызвать super.foobar () для вызова вызова любой функции родительского classа. Такая функциональность недоступна для стандартных функций, хотя вы можете подражать ей с помощью некоторых пользовательских хакеров.
  4. Внутри classа тела вы можете определить функцию с ключевым словом static, поэтому ее можно вызвать с использованием только ClassName.FunctionName () -syntax.
  5. В объявлениях и выражениях classов могут использоваться ключевые слова extends, например, class Dog extends Animal
  6. МетодDeclaration не нуждается в функции -prefix, поэтому вы можете определить функцию «ok» внутри classа «m» следующим образом: class m {ok () {}} . На самом деле даже не разрешено определять функцию как class m {function ok () {}}

Однако после того, как парсер завершил работу, экземпляр classа, по сути, работает так же, как и любой другой объект.

Новый синтаксис ES6 Class является, по существу, более понятным способом выражения объектов в традиционном ООП, и если вам это нравится, то вы должны его использовать.

EDIT: также синтаксис classа ES6 имеет и другое ограничение: он не позволяет функциям-членам использовать лексически привязанную, используя жирную стрелку. Кажется, что у ES7 есть экспериментальная функция, позволяющая это. Это может быть полезно, например, при связывании методов с обработчиками событий, здесь задан соответствующий вопрос.

1 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

class его ничего, кроме синтаксического сахара над созданием логического classа javascript с использованием function . если вы используете function как class вся функция действует как конструктор, если вы хотите поместить другие функции-члены, вам нужно сделать это в конструкторе типа this.something = ... или var something = ... в случае частных членов (если вы не вводите извне, предположите, что вы создаете объект с другими методами / свойствами), но в случае classа вся функция фактически не выполняет конструктор, вы можете явно разделить его с другими функциями-членами и данными.

  • Как сделать setState внутри обратного вызова: ReactJS
  • Блокировка объявлений наведите курсор
  • Подождите, пока флаг = true
  • Как вставить элемент после другого элемента в JavaScript без использования библиотеки?
  • Есть ли способ перегрузки методов в TypeScript?
  • В чем разница между «$ (this)» и «this»?
  • Как получить IP-адрес клиента с помощью JavaScript?
  • Как реализовать аутентифицированные маршруты в React Router 4?
  • Зачем использовать именованные функциональные выражения?
  • Соединение плоских данных
  • Просмотр Rerender при изменении размера браузера с помощью React
  • Interesting Posts

    Нестандартная оценка (NSE) в dplyr’s filter_ и извлечение данных из MySQL

    Утилита «find» не выводит все файлы при использовании подстановочных знаков

    Как сделать bash не для вывода вывода?

    Служба WAMP MySQL не запускается

    Фильтровать определенные пакеты в @ComponentScan

    JPA нетерпеливый выбор не присоединяется

    Можно ли использовать мобильный телефон в качестве USB-модема?

    Что произойдет, если я активирую свою виртуальную машину Windows XP?

    Как мне установить переменную PATH на моем Mac, чтобы найдены инструменты, установленные в Hombrew?

    Перемещение текста в режиме вставки

    Полиморфизм против переопределения и перегрузки

    Последующий удаленный nohup с tcsh

    Как использовать 3G-соединение в приложении Android вместо Wi-Fi?

    Удаление повторяющихся строк в Notepad ++

    Как я могу заставить Makefile автоматически пересобирать исходные файлы, содержащие модифицированный заголовочный файл? (В C / C ++)

    Давайте будем гением компьютера.