2016-03-19 4 views
5

С выпуском ECMAScript 6 в июне 2015 года был введен синтаксис классов Javascript.Javascript: В чем разница между функцией и классом

Синтаксис:

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

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

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

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

+0

Это как, 'переменная х = (то)? 1: 0' выгоды от 'var x; if (someThing) {x = 1; } else {x = 0; } 'Может быть читабельнее. –

+3

Этот ответ (хотя и не является точным дубликатом) объясняет различия очень хорошо: http://stackoverflow.com/questions/30783217/why-should-i-use-es6-classes – CodingIntrigue

+2

Что не так с stackoverflow, -5 для просто спрашивать обычный вопрос. Я думаю, этого достаточно, узнал бы сам. Спасибо за респондентов, которые пытались дать объяснение, я ценю это. –

ответ

12

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

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

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

  • ClassBody
  • MethodDefinition
  • ClassDeclaration
  • ClassExpression
  • MetaProperty

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

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

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

Это потому, что когда анализатор встречает класс -ключевое слово, он начнет обрабатывать следующий код как 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, что предполагает некоторые обходные пути, такие как использование символов:

Private properties in JavaScript ES6 classes

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

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

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

Декларации классов и декларации функций очень похожи;

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

Класс выражения работают совершенно аналогично функционировать exressions, например, они могут быть отнесены к переменной:

var myClass = class foobar {}; 

Другие отличия 1

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

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

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

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

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

+0

Спасибо за объяснение и ссылки, помогает много. –

+0

Я также добавил уведомление о отсутствующем синтаксисе сильной стрелки для объявления класса ES6. –

+0

@TeroTolonen: Это вряд ли «особенность», которая отличала бы классы от функций. Вы можете использовать функции стрелок в конструкторе, а не на прототипе. – Bergi

0

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

Смежные вопросы