const student = {
name: 'Billy',
getName() {
return this.name;
},
sleep() {}
};
const lecturer = {
name: 'Sergey',
getName() {
return this.name;
},
talk() {}
};
const student = {
name: 'Billy',
getName() {
return this.name;
},
sleep() {}
};
const lecturer = {
name: 'Sergey',
getName() {
return this.name;
},
talk() {}
};
const person = {
getName() {
return this.name;
}
};
const person = {
getName() {
return this.name;
}
};
const student = { name: 'Billy' };
const lecturer = { name: 'Sergey' };
Object.setPrototypeOf(student, person);
Object.setPrototypeOf(lecturer, person);
student.getName(); // Billy
lecturer.getName(); // Sergey
const person = {
getName() {
return this.name;
}
};
const student = Object.create(person, {
name: { value: 'Billy' }
});
const person = {
getName() {
return this.name;
}
};
const student = {
name: 'Billy',
getName() {
return 'Student ' + super.getName();
}
};
Object.setPrototypeOf(student, person);
student.getName(); // Student Billy
const billy = {
name: 'Billy',
getName() {
return this.name;
}
};
const willy = {
name: 'Willy',
getName() {
return this.name;
}
};
function createStudent(name) {
return {
name,
getName() {
return this.name;
}
};
}
const billy = createStudent('Billy');
const studentProto = {
getName() {
return this.name;
}
};
function createStudent(name) {
const student = { name };
Object.setPrototypeOf(student, studentProto);
return student;
}
const studentProto = {
getName() {}
};
function createStudent(name) {
return Object.create(studentProto, {
name: {
value: name
}
});
}
const studentProto = {
getName() {}
};
function createStudent(name) {
return Object.create(studentProto, {
name: {
value: name,
enumerable: true,
writable: true
}
});
}
const studentProto = {
getName() {}
};
function createStudent(name) {
const student = Object.create(studentProto);
student.name = name;
return student;
}
const studentProto = {
getName() {}
};
function createStudent(name) {
const student = Object.create(studentProto);
return Object.assign(student, { name });
}
const personProto = {
getName() {}
};
const studentProto = Object.create(personProto);
function createStudent(name) {
const student = Object.create(studentProto);
return Object.assign(student, { name });
}
const personProto = {
getName() {}
};
const studentProto = Object.create(personProto);
studentProto.getName = function () {
return 'Student ' + this.name;
}
function createStudent(name) {
const student = Object.create(studentProto);
return Object.assign(student, { name });
}
const personProto = {
getName() {}
};
const studentProto = Object.create(personProto);
studentProto.getName = function () {
return 'Student ' + super.getName(); Error
}
function createStudent(name) {
const student = Object.create(studentProto);
return Object.assign(student, { name });
}
const personProto = {
getName() {}
};
const studentProto = {
getName() {
return 'Student ' + super.getName();
}
};
Object.setPrototypeOf(studentProto, personProto);
function createStudent(name) {
// ...
}
const { createServer } = require('http');
const server = createServer((req, res) => {
res.end('Hello, World!');
})
server.listen(8080);
Favor object composition over class inheritance
const studentProto = {
getName() {}
};
const developerProto = {
getSalary() {}
};
const proto = Object.assign({}, studentProto, developerProto);
function create({ name, salary }) {
const instance = Object.create(proto);
return Object.assign(instance, { name, salary });
}
Object.assign не переносит свойства полей, неперечисляемые поля, а также set/get
const objTo = {};
const properties = Object.getOwnPropertyNames(objFrom);
for (const property of properties) {
Object.defineProperty(
objTo,
property,
Object.getOwnPropertyDescriptor(objFrom, property);
);
}
function createStudent(name) {
this.name = name;
}
const billy = new createStudent('Billy');
Функция, вызванная оператором new, работает как конструктор объектов
this внутри конструкторов ссылается на создаваемый объект
function createStudent(name) {
// const this = {};
this.name = name;
// return this;
}
const billy = new createStudent('Billy');
function Student(name) {
// const this = {};
this.name = name;
// return this;
}
const billy = new Student('Billy');
Чтобы отличить функции-конструкторы от простых функций принято именовать их с заглавной буквы
function Student(name) {
this.name = name;
}
const billy = Student('Billy');
'use strict';
function Student(name) {
this.name = name;
}
const billy = Student('Billy');
function Student(name) {
this.name = name;
return {
name: 'Willy'
};
}
const billy = new Student('Billy');
console.info(billy.name); // Willy
function Student(name) {
this.name = name;
return 1703;
}
const billy = new Student('Billy');
console.info(billy.name); // Billy
function Student(name) {
this.name = name;
}
Student.prototype = {
getName() {}
}
const billy = new Student('Billy');
billy.getName(); // Billy
function Student(name) {
// const this = {};
// Object.setPrototypeOf(this, Student.prototype);
this.name = name;
// return this;
}
Student.prototype = {
getName() {}
}
const billy = new Student('Billy');
billy.getName(); // Billy
function Student(name) {
this.name = name;
}
Student.prototype.constructor === Student; // true
function Student(name) {
// const this = {};
// Object.setPrototypeOf(this, Student.prototype);
this.name = name;
// return this;
}
Object.assign(Student.prototype, {
getName() {}
});
const billy = new Student('Billy');
billy.getName(); // Billy
function Student(name) {
// const this = {};
// Object.setPrototypeOf(this, Student.prototype);
this.name = name;
// return this;
}
Student.prototype = {
constructor: Student,
getName() {}
};
const billy = new Student('Billy');
billy.getName(); // Billy
const obj = {};
const obj = new Object();
function Object() {}
Object.prototype = {
constructor: Object,
hasOwnProperty() {},
toString() {}
};
function Person() {}
Object.assign(Person.prototype, {
getName() {}
});
function Student(name) {
this.name = name;
}
Object.assign(Student.prototype, {
getCourse() {}
});
Object.setPrototypeOf(Student.prototype, Person.prototype);
class Student {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
typeof Student; // function
Student.prototype.hasOwnProperty('getName'); // true
«Классы» нельзя использовать без new
«Классы» не всплывают
const student = new Student();
function Student() {}
const lecturer = new Lecturer(); Error
class Lecturer {}
ReferenceError: Lecturer is not defined
class Student {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName() {
return this.firstName + ' ' + this.lastName;
}
}
class User {
constructor(role, name) {
this.name = name;
this.role = role;
}
static createAdmin(name) {
return new User('admin', name);
}
static createGuest(name) {
return new User('guest', name);
}
}
User.createAdmin('Billy');
Все методы не перечислимы
Все методы поддерживают super
Все методы работают в строгом режиме
class Person {
constructor(name) {
this.name = name;
}
}
class Student extends Person {
constructor(name, course) {
super(name);
this.course = course;
}
}
const billy = new Student('Billy', 4);
class Student extends Person {
constructor(name, course) {
this.course = course;
super(name);
}
}
const billy = new Student('Billy', 4); Error
ReferenceError: Must call super constructor in derived class before accessing or returning from derived constructor
Наследоваться можно либо от другого конструктора («класса»), либо от null
class Student extends null {}
class Student {}
const billy = new Student();
Student.prototype.isPrototypeOf(billy); // true
class Student {}
const billy = new Student();
billy instanceof Student; // true
class Student extends Person {}
const billy = new Student();
billy instanceof Student; // true
billy instanceof Person; // true
billy.[[Prototype]] === Person.prototype; // false
// Может, там null?
billy.[[Prototype]] === null; // false
// Идём дальше по цепочке
billy.[[Prototype]].[[Prototype]] === Person.prototype; // true
// Возвращаем true
TC39 (Technical Committee 39)
Microsoft, Google, IBM, Intel, Yahoo, Facebook, Airbnb, Netflix, PayPal, Hewlett Packard
Переодически встречаются и рассматривают предложения (proposals)
Заметки со встреч размещаются на Github, а решения принимаются большинством голосов
Идея может быть предложена командой TC39 или любым человеком зарегистрированным как контрибутор
Выбирается ответственный за предложение из TC39. Подготавливается подробное описание с примерами. Пишутся полифилы.
Подготавливается описание на языке спецификации ECMAScript. Пишутся две реализации (одна из них для транспилера).
Описание финализируется и проходит ревью других членов TC39. Пишутся две полноценные реализации.
Пишутся тесты Test262. Реализации проходят все тесты. Редакторы ECMAScript подписыват спецификацию.
Раз в год в июле обновлённая спецификация становится новым стандартом
class Student {
#name = null;
constructor(value) {
this.#name = value;
}
getName() {
return 'Student ' + this.#name;
}
}
class Student {
@enumerable(true)
getName() {
return this.name;
}
}
function enumerable(value) {
return (target, propertyName, descriptors) => {
// target === Student.prototype
descriptors.enumerable = value;
};
}
@debug
class Student {}
function debug(Class) {
return (...args) => {
console.trace(Class.name, args);
return new Class(...args);
};
}
npm install -g babel-cli
babel-node --plugins transform-decorators script.js
class C {
static f() { ... }
g() {
C.f();
}
}
class C {
static f() { ... }
g() {
class.f();
}
}
module.exports = class {
static f() { ... }
g() {
class.f();
}
}
Speaking JavaScript
Chapter 17. Objects and Inheritance.
Layer 3: Constructors—Factories for Instances
Speaking JavaScript
Chapter 17. Objects and Inheritance
Layer 4: Inheritance Between Constructors
Exploring ES6
15. Classes
Eric Elliott
Common Misconceptions About Inheritance in JavaScript
Лекции 2015 года
Про this
Современный учебник Javascript
ООП в прототипном стиле
Современный учебник Javascript
Современные возможности ES-2015
Классы
Dr. Axel Rauschmayer
The TC39 process for ECMAScript features