g1er / Andrew

0 stars 0 forks source link

Классы #9

Closed IgorKulishov closed 6 years ago

IgorKulishov commented 6 years ago

Классы JavaScript ES6:

Мы начинаем изучать JavaScript ES6 (это новая версия JavaScript, которая уже поддерживается всеми браузерами). Одним из главных новшеств стало появление классов Class, при том что JavaScript как был так и остался ("под капотом") все тот же не ОО язык основаный на прототипах, однако введение термина Class позволило подсластить язык и позволить программистам с опытам на ОО (привыкшими определять сначала Class-ы, а потом строить на базе классов новые объекты) оказаться в привычном синтаксисе.

Итак мы будем знакомиться с классами и поможет нам в этом учебник на русском языке: Классы представленные https://learn.javascript.ru/es-class

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

Итак приведу небольшой пример в формате ES6:

class User {
  constructor(name, lastname) {
    this.name = name;
    this.lastname = lastname;
  }
  sayHi() {
    alert(this.name + "  " + this.lastname);
  }
}
var user = new User('James', 'Smith');

Как ты заметил:

  1. слово class с маленькой буквы при этом название класса с большой (название класс принято писать с большой буквы, как уже известные тебе встроенные классы Date, Math). Как ты видешь у класса нет параментов (они есть у конструктора);
  2. constructor - неотъемлемая часть класса позволяющая создавать значения новых объектов передавая через аргумент класса;
  3. метод sayHi НЕ имеет слова var или this , перед этим словом ничего не стоит, этот метод будет автоматически создан и будет существовать в новом объекте;
  4. объект создается при помощи слова new перед классом User и с параметрами которые будут авторматически переданы как аргументы конструктора (п.3). И так же самое с конструктором в формате ES5:
    var User = function (name) {
    this.name = name;
    this.sayHi = function() {
      alert(this.name);
    }
    };
    var user = new User('James');

    Вариант с конструктором для примера на ES5 мне кажется ближе по внешнему виду. И еще раз то же самое с определением класса через прототип

    
    function User(name) {
    this.name = name;
    }

User.prototype.sayHi = function() { alert(this.name); };

IgorKulishov commented 6 years ago

Постарайся прочесть электронную кнуги до гетеров и сетеров (getters & setters), кажется написана более разборчиво. Выпиши вопросы один за одним и сброст в комменты.

g1er commented 6 years ago

Новый синтаксис выглядит проще, удобнее. Хотя не такая большая разница. В книге в примерах вместо var ставится let. Это замена var-a или новый оператор? В разделе Class Expression я не разобрался. Я прежде не сталкивался ни с какими expression-ами, поэтому эта тема для меня неизвестная

IgorKulishov commented 6 years ago

1) да совершенно верно в JavaScript ES6 переменные обозначаются A) let - с точки зрения декларирования переменных можно сказать что let пришел на место var, однако let имеет преимущества - он не позволяет дважды декларировать одну и ту же переменную дважды, таким образом предотвращает потенциальные баги в коде. Пример

var A = 1;
var A = 2; //позволит декларировать еще раз
let A = 1; // Error: переменная была уже задекларирована 
let B = 2; 
let B = 3; // Error: переменная была уже задекларирована 

B) const - это еще один метод декларировать переменный, означает константу (новый термин в JavaScript) имеет две особенности: а) если переменная строка или число (не объект), то позволяет присваивать значение только один раз и после этого не позволяет присвоить новое значение;

const B = 1;
const B = 2; // gives Error

b) если переменная объект, то свойствам объекта можно присваивать новые значения

const person = {
  name: 'Wes',
  age: 28
}
person.age = 29
person.height = 176

c) Для того что бы зафиксировать значение переменной определенной как const, существует встроенный метод Object.freeze (это уже поддерживается браузером Chrome - можешь проверить), которая позволит принудительно заморозить свойства и значения объекта декларированного константой

Object.freeze(person);
person.height = 177; // не позволит присвоить значение после Object.freeze
person.weight = 85; // не позволит добавить новое свойство после Object.freeze
person //выдаст только старые объекты и их значения 
IgorKulishov commented 6 years ago

2. Class Expression

Объясняют альтернативный способ определения классов не указывая названия классов после слова class (этот способ определения применяется реже ).

Рассмотрим только 1/2 этого раздела ( до примера с createModel , т.к. некоторые операторы такие как spread syntax синтакс распределения аргументов внутри ф-ции createModel(Model, ...args) мы разберем в будующих заданиях.

Итак в class expression (по аналогии с function expression) мы не указываем название класса после слова class.

let User = class {
  sayHi() { alert('Привет!'); }
};

new User().sayHi();

Небольшое отступление об аналогии с function declaration и function expression (т.к. это похоже с типом определения классов):

Важно понимать что классы в JavaScript это теже ф-ции (конструкторы) только имеющие новые синтакс.

Синтаксис похож на один из двух способов определния ф-ций - через function expression. В JavaScript - два способа определения ф-ция : "выражение ф-ции" (function expression) и "декларирование ф-ции" (function declaration)

При этом function declaration имеет преимущество:

А) Function declarations находит определение ф-ции и выполняет её даже если определение находиться ниже строки вызова:

hoisted(); // logs "foo"

function hoisted() {
  console.log('foo');
}

B) Function expressions ф-ция должна быть сначала определена и потом уже использована (иначе JS не видет ф-цию):

notHoisted(); // TypeError: notHoisted is not a function

var notHoisted = function() {
   console.log('bar');
};

Далее следующий пункт параграфа: Named Class Expression (по аналогии с Named Function Expression):

let SiteGuest = class User {
  // покажет свойства User при вызове изнутри (выглядет странно, но это так работает, это в принципе тоже самое что и слово this которое мы ставим в ES5 в конструкторах - указывает на сам объект):
  sayHi() { alert('Привет!' + User); }
};

new SiteGuest().sayHi(); // Привет
User // ошибка
new User(); // тоже ошибка

Здесь говориться что даже, если мы присвоим имя класса в выражении формата "Class Expression", то обращаться по имени класса все равно можно будет только внутри самого класса (внутри методов как в примере выше) и название класса будет не доступено при обращении снаружи (за пределами) класса. Т.о. обращаться можно только по переменной let SiteGuest, т.к. именно это будет храниться в реестре памяти для обращения снаружи.

IgorKulishov commented 6 years ago

Предлагаю пропустить пункт в книге где объясняется применение Named Class Expressions с примером createModel и прочитать пока следующее задание с getter и setter из следующего задания, после чего можно тоже самое прочитать в книге (по книге будут вопросы больше связанные с операторами, так что лучше читай объяснение сначала из след задания и потом из книги), при этом задавай вопросы по непонятным моментам, в том числе по операторам. Мы сделаем несколько упражнений на операторы JS ES6, так что копи вопросы.

g1er commented 6 years ago

1) Я так и не понял, могу ли я продолжать пользоваться var вместо let, или в ES6 var-a уже нет? Или со временем его планируют убрать совсем? 2) Судя по описанию, между let и const совсем тонкое отличие. Я вижу смысл использовать const только для создания объектов, чтобы их потом заморозить. Или созданные через let объекты тоже можно заморозить? 3) Я так понял, что function declaration это определение функции через оператор function. Теперь понятно. Только не совсем понял, для чего нужен такой класс без имени. В смысле, как его применять, чем он лучше или какие особенности у него, в отличии от традиционного создания классов? Ведь раз такой способ есть, значит есть на него спрос. Хотелось бы понять, что заставляет создавать классы именно через class expression

IgorKulishov commented 6 years ago
  1. Можно использовать var но рекомендуют лучше let
  2. В JS ES6 обычно принято : A) let - переменные B) const - функции
  3. Хороший вопрос. Я подготовлю на него ответ.
IgorKulishov commented 6 years ago
  1. Я не понял твое определение (уточни пож-та):

"function declaration это определение функции через оператор function." - там как бы оператор function в обоих случая

Посмотри мое объяснение выше для справки.

Ответ на вопрос

"для чего нужен такой класс без имени?" (т.е. "Class Expression"):

То ответ с примером приводится в книге: "Наиболее очевидная область применения этой возможности – создание вспомогательного класса прямо при вызове функции." В книге приводится хороший пример , который я немного упростил:

// function declaration:
function createModel(Model, ...args) {
  let model = new Model(...args);

  return model;
}
// class expression используется для класса передаваемного внутрь ф-ции в качестве параметра внутри скобок
let user = createModel(class {
  constructor(name) {
    this.name = name;
  }
  sayHi() {
    alert(this.name);
  }
}, "Вася");

user.sayHi(); // Вася

Как видно "class expression" используется внутри скобок ф-ции где мы передаем класс в качестве параметра

let user = createModel(class {