Техника симулирования класса и наследственности в JavaScript
1. Класс в Javascript
Javascript это на самом деле мир функций и объектов. Первоначально он разработан просто, без четкого принципа о классе. Возможно создатели Javascript и не могли подумать что в один день, этот язык будет использоваться так распространенно.
Объект в Javascript сущность с несколькими парами "Ключ/Значение", и вы можете получить доступ в значения через объект и ключ.
object-example1.js
var tom = {
name: "Tom",
country: "USA"
};
// Access:
console.log( tom.name ); // Tom
console.log( tom.country ); // USA
console.log( tom["name"] ); // Tom
console.log( tom["country"] ); // USA
Вы можете добавить новый "Ключ/Значение" в готовый объект или удалить его определенную пару "Ключ/Значение".
object-example2.js
var tom = {
name: "Tom",
country: "USA"
};
// Delete property - country
delete tom["country"]; // Same as: delete tom.country;
// Add property - gender
tom["gender"] = "Male"; // Same as: tom.gender = "Male";
// Access:
console.log( tom.name ); // Tom
console.log( tom["name"] ); // Tom
console.log( tom["country"] ); // undefined
console.log( tom.country ); // undefined
console.log( tom["gender"] ); // Male
console.log( tom.gender ); // Male
Класс это современная концепция в таких языках, как Java, C#,... Класс это дизайн, который помогает быстро создавать объекты с одинаковой структурой. Первая версия Javascript не имеет данную концепцию.
Javascript становится все более и более важным, поэтому его необходимо обновить. Дизайнеры Javascript пытаются смоделировать концепцию Класс, основываясь на готовые концепции в Javascript. Синтаксис симулирования класса представлен в ES3, ES5, но только дойдя до ES6 мы получаем современный синтаксис и удовлетворяем всех.
Сначала, для упрощения рассмотри современный синтаксис представленный в ECMAScript 6 чтобы создать класс Rectangle (Прямоугольник), с 2-мя свойствами (property) width (ширина) и height (длина). Данный класс имеет метод getArea() возвращает площадь данного прямоугольника.
es6-class-example.js
// ECMAScript 6 class:
class Rectangle {
constructor (width , height) {
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
// ------------- TEST -------------------
var rect = new Rectangle(10, 5);
var area = rect.getArea();
console.log("Width: " + rect.width);
console.log("Height: " + rect.height);
console.log("Area: " + area);
Создать подкласс класс очень просто с ES6:
es6-inheritance-example.js
class Shape {
constructor( x, y) {
this.setLocation(x, y);
}
setLocation(x, y) {
this.x = x;
this.y = y;
}
}
// Subclass:
class Circle extends Shape {
constructor(x, y, radius) {
// Call Shape's constructor via super
super(x, y);
this.radius = radius;
}
getArea() {
return Math.PI * this.radius * this.radius;
}
}
// ----- TEST ----
var circle = new Circle(0, 2, 5);
console.log( circle.getArea() );
ES6 представил современный синтаксис для создания класса и подклассов, но техника на самом деле не поменялась. Синтаксис у ES6 скрыл все неясные понятия у Javascript когда он пытается симулировать класс. В данной статье мы обсудим с вами способ, который используется ES3 & ES5 для сиумилрования класса и наследственность.
2. Класс и наследственность в ES3
ES3 использует ключевое слово function для определения "конструктор объекта". Вы создаете новый объект, когда вы вызываете данную функцию с помощью оператора new:
// ECMAScript 3 class.
function Rectangle(width, height) {
this.width = width;
this.height = height;
}
// Create an Object:
var rect = new Rectangle(10, 5);
Изображение ниже иллюстрирует действие выполненное исполняющей машиной Javascript:
- Объект 'rect' создан (он является обычным объектом, ничего особенного)
- Добавить свойство (property) __proto__ объекту 'rect', это скрытое свойство.
- Переменная this будет направлена на адрес объекта 'rect'.
- Добавить свойство (property) width объекту 'rect'.
- Добавить свойство (property) height объекту 'rect'.
Концепция prototype будет представлена в ES3. Рассмотрим какова его цель?
// ECMAScript 3 class.
function Rectangle(width, height) {
this.width = width;
this.height = height;
}
Rectangle.prototype.bgColor = "red";
Rectangle.prototype.borderColor = "blue";
// Create an Object:
var rect = new Rectangle(10, 5);
console.log(rect); // Rectangle { width: 10, height: 5 }
console.log(rect.__proto__); // Rectangle { bgColor: 'red',borderColor: 'blue' }
console.log(rect.__proto__.bgColor); // red
console.log(rect.__proto__.borderColor); // blue
// (Read the explanation**)
console.log(rect.bgColor); // red
console.log(rect.borderColor); // blue
Что происходит когда машина выполняющая Javascript встречает выражение myObject.myProperty?
Ответ: Он проверяет имеет ли объект myObject свойство (property) myProperty или нет, если есть то он получает доступ в данное свойство, наоборот он получает доступ в myObject.__proto__.myProperty.
es3-proto-example3.js
var rect = {
__proto__ : { bgColor : "red", borderColor : "blue" },
width: 10,
height: 5
}
console.log(rect.width); // 10
console.log(rect.__proto__.bgColor); // red
console.log(rect.bgColor); // red
new AFunction(args) vs AFunction.call(anObj, args)
Наследственность
Для ES3 вы можете симулировать наследственный класс другого класса разными способами, но это не просто как вы это делаете в ES6, и довольно непонятен многим программистам.
Для простоты, я дам пример наследственности, и анализ правила работы исполняющей машины Javascript в данном случае.
- Класс Animal имеет 2 свойтсва (property) name & gender.
- Класс Cat наследует от класса Animal, имеет 1 свойство color.
es3-inheritance-example1.js
function Animal(n, g) {
this.name = n;
this.gender = g;
}
function Cat(n, g, c) {
Animal.call(this, n, g);
this.color = c;
}
var tom = new Cat("Male", "Tom", "Black");
// Cat { gender: 'Male', name: 'Tom', color: 'Black' }
console.log(tom);
Наследственность и роль прототипа (ES3)
es3-inheritance-example2.js
// Class: Animal
function Animal(n, g) {
this.name = n;
this.gender = g;
}
Animal.prototype.sleep = function() {
console.log("Animal sleeping..");
}
Animal.prototype.move = function() {
console.log("Animal moving..");
}
// Class: Cat
function Cat(n, g, c) {
Animal.call(this, n, g); // IMPORTANT!!
this.color = c;
}
// IMPORTANT!!
var TempFunc = function() {}; // Temporary class.
TempFunc.prototype = Animal.prototype;
Cat.prototype = new TempFunc();
// ------------------
Cat.prototype.cry = function() {
console.log("Meo meo");
}
// Override 'move' method of Animal.
Cat.prototype.move = function() {
console.log("Cat moving..");
}
var tom = new Cat("Male", "Tom", "Black");
// Cat { gender: 'Male', name: 'Tom', color: 'Black' }
console.log(tom);
tom.move(); // Cat moving..
tom.sleep(); // Animal sleeping..
tom.cry(); // Meo meo
3. Класс и наследственность в ES5
Object.create(srcObject)
Метод Object.create(srcObject) создает новый объект newObject, при этом newObject.__proto__ является копией у srcObject.
method-object-create-example.js
var john = {
name: "John",
gender: "Male"
};
var other = Object.create(john);
console.log(other.__proto__); // { name: 'John', gender: 'Male' }
Наследственность (ES5 + Object.create)
Использование метода Object.create(srcObject) у ES5 помогает вам легче симулировать класс и наследственность по сравнению с ES3.
es5-inheritance-example1.js
// Class: Animal
function Animal(n, g) {
this.name = n;
this.gender = g;
}
Animal.prototype.sleep = function() {
console.log("Animal sleeping..");
}
Animal.prototype.move = function() {
console.log("Animal moving..");
}
// Class: Cat
function Cat(n, g, c) {
Animal.call(this, n, g); // IMPORTANT!!
this.color = c;
}
Cat.prototype = Object.create(Animal.prototype); // IMPORTANT!!
Cat.prototype.cry = function() {
console.log("Meo meo");
}
// Override 'move' method of Animal.
Cat.prototype.move = function() {
console.log("Cat moving..");
}
var tom = new Cat("Male", "Tom", "Black");
// Cat { gender: 'Male', name: 'Tom', color: 'Black' }
console.log(tom);
tom.move(); // Cat moving..
tom.sleep(); // Animal sleeping..
tom.cry(); // Meo meo
Pуководства ECMAScript, Javascript
- Введение в Javascript и ECMAScript
- Быстрый старт с Javascript
- Диалоговое окно Alert, Confirm, Prompt в Javascript
- Быстрый запуск с JavaScript
- Переменные (Variable) в JavaScript
- Битовые операции
- Массивы (Array) в JavaScript
- Циклы в JavaScript
- Руководство JavaScript Function
- Руководство JavaScript Number
- Руководство JavaScript Boolean
- Руководство JavaScript String
- Заявление if/else в JavaScript
- Заявление Switch в JavaScript
- Обработка ошибок в JavaScript
- Руководство JavaScript Date
- Руководство JavaScript Module
- Функция setTimeout и setInterval в JavaScript
- Руководство Javascript Form Validation
- Руководство JavaScript Web Cookie
- Ключевое слово void в JavaScript
- Классы и объекты в JavaScript
- Техника симулирования класса и наследственности в JavaScript
- Наследование и полиморфизм в JavaScript
- Понимание Duck Typing в JavaScript
- Руководство JavaScript Symbol
- Руководство JavaScript Set Collection
- Руководство JavaScript Map Collection
- Понимание JavaScript Iterable и Iterator
- Руководство Регулярное выражение JavaScript
- Руководство JavaScript Promise, Async Await
- Руководство Javascript Window
- Руководство Javascript Console
- Руководство Javascript Screen
- Руководство Javascript Navigator
- Руководство Javascript Geolocation API
- Руководство Javascript Location
- Руководство Javascript History API
- Руководство Javascript Statusbar
- Руководство Javascript Locationbar
- Руководство Javascript Scrollbars
- Руководство Javascript Menubar
- Руководство JavaScript JSON
- Обработка событий в Javascript
- Руководство Javascript MouseEvent
- Руководство Javascript WheelEvent
- Руководство Javascript KeyboardEvent
- Руководство Javascript FocusEvent
- Руководство Javascript InputEvent
- Руководство Javascript ChangeEvent
- Руководство Javascript DragEvent
- Руководство Javascript HashChangeEvent
- Руководство Javascript URL Encoding
- Руководство Javascript FileReader
- Руководство Javascript XMLHttpRequest
- Руководство Javascript Fetch API
- Разбор XML в Javascript с помощью DOMParser
- Введение в Javascript HTML5 Canvas API
- Выделение кода с помощью библиотеки Javascript SyntaxHighlighter
Show More