Javascript: в чем разница между функцией и классом
С выпуском ECMAScript 6 в июне 2015 года был введен синтаксис классов Javascript.
синтаксис:
class Polygon {
constructor(width, height) {
this.width = width;
this.height = height;
}
}
в основном то же, что:
function Polygon(width, height) {
this.width = width;
this.height = height;
}
Итак, в чем преимущество использования класса вместо традиционной функции? И в каком состоянии я должен использовать class вместо function?
2 ответов
есть некоторые различия между классом и функцией - большинство людей начнут с того, что класс "просто синтаксический сахар", но этот сахар имеет большое значение. Когда парсер JS обрабатывает код JavaScript, парсер сохранит их в разных узлах AST, как показано здесь ClassDeclaration и ClassExpression различные типы узлов в результирующем AST дерево:
https://github.com/estree/estree/blob/master/es2015.md#classes
вы можете видеть, что для этого парсера новая спецификация классов ES6 вводит ряд новых элементов AST в синтаксис:
- ClassBody
- MethodDefinition
- ClassDeclaration
- ClassExpression
- Метасвойства
поскольку синтаксис AST не является стандартным, может быть больше или меньше типов в зависимости от синтаксического анализатора, но что важно заметить, что когда код входит в объявление класса или выражение класса, он будет по-разному интерпретироваться движком JavaScript.
это означает, что объявления класса и функции не могут быть обменены. Вы можете увидеть это, если попытаетесь написать
class notWorking {
return 1; // <-- creates a parser error
};
это связано с тем, что когда анализатор встречает ключевое слово class, он начнет обрабатывать следующий код как ClassBody либо ClassDeclaration, либо ClassExpression, а затем он expexts для поиска MethodDefinitions.
это небольшая проблема, потому что создание частных переменных становится немного более сложным. Объявление функции может точно определить частную переменную следующим образом:
function myClass() {
var privateVar;
}
объявление класса не может быть такого:
class myClass {
var privateVar; // ERROR: should be a method
}
это потому, что синтаксис класса позволяет объявлять только методы внутри тела класса. По крайней мере сейчас.
однако существует предложение по созданию частных полей:
https://github.com/zenparsing/es-private-fields
таким образом, в будущем вы могли бы сказать
class myClass {
#privateVar; // maybe this works in the future?
}
существует отдельный ответ, рассматривающий частные свойства в классах ES6, который предлагает некоторые обходные пути, такие как использование символов:
частные свойства в JavaScript ES6 классы
var property = Symbol(); // private property workaround example
class Something {
constructor(){
this[property] = "test";
}
}
естественно, нет больше различий между классами и функциями. один из них поднимает 1 - в отличие от функций, вы не можете объявить класс в любую точку области:
важное различие между объявлениями функций и классом объявления заключается в том, что объявления функций поднимаются и class деклараций нет. Сначала нужно объявить свой класс, а затем доступ это
объявления классов и объявления функций очень похожи;
function foo1() {} // can be used before declaration
class foo2{} // new foo2(); works only after this declaration
выражения класса работают точно так же, как и функции exressions, например, они могут быть назначены переменной:
var myClass = class foobar {};
больше различия 1
- тело выражения / объявления класса всегда выполняется в строгого режима - нет необходимости указывать это вручную
- классы специальное ключевое слово конструктор - там может быть только один из них, или ошибка. Функции могут иметь несколько определений переменной функции с именем "конструктор"
- классы имеют специальное ключевое слово супер который относится к конструктору родительских классов. Если вы находитесь внутри конструктора вы можете позвонить супер (x, y); для вызова конструктора родительского класса, но внутри метода вы можете вызвать супер.foobar () создать вызов любая функция родительского класса. Такая функциональность недоступна для стандартных функций, хотя вы можете эмулировать ее с помощью некоторых пользовательских взломов.
- внутри тела класса вы можете определить функцию с static ключевое слово, поэтому его можно вызвать, используя только ClassName.FunctionName () -синтаксис.
- объявления и выражения классов могут использовать выходит ключевое слово класс собака расширяется Животное!--80-->
- MethodDeclaration не нуждается в префиксе функции, поэтому вы можете определить функцию " ok "внутри класса" m " следующим образом: класс m { ok () { } }. На самом деле даже не разрешается определять функцию как класс m { функция ok () { } }
однако после того, как анализатор завершил свою работу, экземпляр класса по существу работает так же, как и любой другой объект.
новый синтаксис класса ES6 по существу, более ясный способ выражения объектов традиционным способом ООП, и если вам это нравится, то вы должны использовать его.
EDIT: кроме того, синтаксис класса ES6 имеет еще одно ограничение: он не позволяет функциям-членам использовать лексически связанные с помощью fat arrow. ES7 кажется экспериментальная функция позволяю. Это может быть полезно, например, при привязке методов к обработчикам событий, связанный вопрос здесь.
1 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
class
его ничего, кроме синтаксического сахара над созданием класса логики javascript с помощью function
. если вы используете function
as class
вся функция действует как конструктор, если вы хотите поместить другие функции-члены, вам нужно сделать это в конструкторе, как this.something = ...
или var something = ...
в случае частных членов (если вы не вводите извне, предположим, что вы создаете объект с другими методами / свойствами), но в случае класса вся функция фактически не действует конструктор вы можете явно разделить его с другими функциями-членами и данными.