Viktor Shevchenko
Web developer from Kyiv
var rect = {
width: 5,
height: 10
};
Самый простой и быстрый способ
function RectangleFactory(w, h) {
return {
width: w,
height: h
}
}
var rectangle = RectangleFactory(5, 10);
var rect = new Object({width: 5, height: 10});
var arr = new Array(10);
var date = new Date();
function Rectangle(w, h) {
this.width = w;
this.height = h;
}
var rectangle = new Rectangle(5, 10);
Главная задача конструктора - инициализация вновь созданного объекта – установке всех его
свойств, которые необходимо инициализировать до того, как объект сможет использоваться
Добавление новых свойств к объекту, на который
ссылается ключевое слово this
const rect = new Rectangle(10, 5)
function Rectangle(w, h) {
this.width = w;
this.height = h;
}
const rect = Rectangle.call({}, 10, 5)
function Rectangle(w, h) {
this.width = w;
this.height = h;
return this;
}
// Определяем конструктор.
// Инициализация объекта с помощью "this"
function Rectangle(w, h) {
this.width = w;
this.height = h;
}
// Вызываем конструктор для создания двух объектов Person.
var rect1 = new Rectangle(2, 4); // rect1 = { width:2, height:4 };
var rect2 = new Rectangle(8.5, 11); // rect2 = { width:8.5, height:11 };
function Rectangle(w, h) {
this.width = w;
this.height = h;
return 25;
}
const rect = new Rectangle(10, 5);
// {width: 10, height: 5}
function Rectangle(w, h) {
this.width = w;
this.height = h;
return {z: 13};
}
const rect = new Rectangle(10, 5);
function Rectangle(w, h) {
this.width = w;
this.height = h;
return () => {};
}
const rect = new Rectangle(10, 5);
// {z: 13}
// () => {}
function computeAreaOfRectangle(r) { return r.width * r.height; }
computeAreaOfRectangle(new Rectangle(4, 5));
// Создать объект Rectangle
var r = new Rectangle(8.5, 11);
// Добавить к объекту метод
r.area = function() { return this.width * this.height; }
// Теперь рассчитать площадь, вызвав метод объекта
var a = r.area();
совсем не обьектоно-ориентировано, но очень функционально
добавлять новый метод? каждый раз?
function Rectangle(w, h) {
this.width = w;
this.height = h;
this.area = function( ) {
return this.width * this.height;
}
}
var r = new Rectangle(8.5, 11);
var a = r.area();
Уже лучше, но еще не совсем оптимально.
Нужно место для хранения свойств и методов общих для всех экземпляров класса. (обектов созданых одной ФК).
И оно есть....
const circle = { radius: 25 }
Object.getPrototypeOf(circle);
const date = new Date();
Object.getPrototypeOf(date);
const regExp = /[a-z]/g
Object.getPrototypeOf(regExp);
const myFunc = function(r) {
return { radius: r };
}
const myArrow = r => ({ radius: r });
Object.getPrototypeOf(myFunc);
Object.getPrototypeOf(myArrow);
don't use .__proto__ in production
const circle = {radius: 25};
function Circle(r) {
this.radius = r;
}
Object.getPrototypeOf(circle) === Object.prototype // true
Object.getPrototypeOf(Circle) === Function.prototype // true
circle.prototype // undefined
Circle.prototype // {constructor: Circle}
Circle.prototype.constructor === Circle // true
// Функцияконструктор инициализирует те свойства, которые могут
// иметь уникальные значения для каждого отдельного экземпляра.
function Rectangle(w, h) {
this.width = w;
this.height = h;
}
// Прототип объекта содержит методы и другие свойства, которые должны
// совместно использоваться всеми экземплярами этого класса.
Rectangle.prototype.area = function() { return this.width * this.height; }
var r = new Rectangle(8, 1);
var a = r.area(); // 80
Constructor
Prototype
Instances
Rectangle()
prototype
constructor
area
new Rectangle(1, 2)
new Rectangle(3, 4)
Inherits
Inherits
var r = new Rectangle(2, 3);
r.hasOwnProperty("width"); // true: width – непосредственное свойство "r"
r.hasOwnProperty("area"); // false: area – унаследованное свойство "r"
"area" in r; // true: area – свойство объекта "r"
var Circle = function (x, y, r) {
this.x = x;
this.y = y;
this.r = r
}
Circle.prototype.pi = 3.14;
Circle.prototype.area = function() {return this.pi * Math.pow(this.r, 2)};
var c = new Circle(2, 3, 1);
// c ->> {r:1, x:2, y:3}
// Object.getPrototypeOf(c) -->
// {pi: 3.14, area: function() {return this.pi * Math.pow(this.r, 2)}}
c.x // 2
c.pi // 3.14
c.x = 4 // c --> {r:1, x:4, y:3}
c.pi = 4 // c --> {r:1, x:4, y:3, pi:4}, Object.getPrototypeOf(c).pi - 3.14
function Circle(r) {
this.radius = r;
}
Circle.prototype.pi = 3.14;
Circle.prototype.are = () => this.pi*(this.r**2);
Circle
.prototype
.pi
.area
.__proto__
const smallCircle = new Circle(10);
smallCircle
.radius // 10
.__proto__
const bigCircle = new Circle(1000);
bigCircle
.radius // 1000
.__proto__
internal hidden link
internal hidden link
instance
instance
Function.prototype
Создадим класс PositionedRectangle более специфический чем Rectangle и наследующий его свойства и методы.
// Этот код нам знаком...
function Rectangle(w, h) {
this.width = w;
this.height = h;
}
Rectangle.prototype.area = function( ) { return this.width * this.height; }
// Далее идет определение подкласса
function PositionedRectangle(x, y, w, h) {
// Вызываем конструктор надкласса
// _super()
Rectangle.call(this, w, h);
// Далее сохраняются координаты верхнего левого угла прямоугольника
this.x = x;
this.y = y;
}
Если мы будем использовать объект-прототип по умолчанию,который создается при определении конструктора PositionedRectangle(),
был бы создан подкласс класса Object.
// Чтобы создать подкласс класса Rectangle, необходимо явно создать объектпрототип.
PositionedRectangle.prototype = new Rectangle();
// Мы создали объектпрототип с целью наследования, но мы не собираемся
// наследовать свойства width и height, которыми обладают все объекты
// класса Rectangle, поэтому удалим их из прототипа.
delete PositionedRectangle.prototype.width;
delete PositionedRectangle.prototype.height;
// Переопределяем конструктор
PositionedRectangle.prototype.constructor = PositionedRectangle;
// можно приступать к добавлению методов экземпляров.
PositionedRectangle.prototype.contains = function(x,y) {
return (x > this.x && x < this.x + this.width &&
y > this.y && y < this.y + this.height);
}
var r = new PositionedRectangle(2,2,2,2);
console.log(r.contains(3,3)); // true // Вызывается метод экземпляра
console.log(r.area( )); // 4 // Вызывается унаследованный метод экземпляра
// Работа с полями экземпляра класса:
console.log(r.x + ", " + r.y + ", " + r.width + ", " + r.height); // "2, 2, 2, 2"
// Наш объект может рассматриваться как экземпляр всех 3 классов
console.log(
r instanceof PositionedRectangle &&
r instanceof Rectangle &&
r instanceof Object
); //true
необходимость вызова конструктора надкласса из конструктора подкласса, причем
конструктор надкласса приходится вызывать как метод вновь созданного объекта.
потребоность явно создать объект-прототип как экземпляр надкласса
после чего - явно изменить свойство constructor объекта-прототипа
есть желание удалить любые свойства, которые
создаются конструктором надкласса в объекте-прототипе
// Вместо использования метода call() или apply()
// для вызова конструктора надкласса как метода данного объекта
Rectangle.call(this, w, h);
// можно упростить синтаксис конструктора, добавив
// свойство superclass в объектпрототип подкласса:
PositionedRectangle.prototype.superclass = Rectangle;
function PositionedRectangle(x, y, w, h) {
this.superclass(w,h);
this.x = x;
this.y = y;
}
Упрощение функции конструктора, отказ от call()
!!! Не работает для многоуровневого наследования
PositionedRectangle.prototype = new Rectangle();
delete PositionedRectangle.prototype.width;
delete PositionedRectangle.prototype.height;
PositionedRectangle.prototype = Rectangle.prototype;
Object.setPrototypeOf(PositionedRectangle.prototype, Rectangle.prototype);
Object.create() создаёт новый объект с указанными объектом прототипа и свойствами.
PositionedRectangle.prototype = Object.create(Rectangle.prototype);
Object.create(proto[, propertiesObject])
proto - Объект, который станет прототипом вновь созданного объекта.
propertiesObject - Необязательный параметр. Если указан и не равен undefined, должен быть объектом.
function Rectangle(w, h) {
this.width = w;
this.height = h;
}
Rectangle.prototype.area = function() { return this.width * this.height; }
function PositionedRectangle(x, y, w, h) {
Rectangle.call(this, w, h);
this.x = x;
this.y = y;
}
PositionedRectangle.prototype = Object.create(Rectangle.prototype);
PositionedRectangle.prototype.constructor = PositionedRectangle;
PositionedRectangle.prototype.pertimeter = function() {return 2*(this.width + this.height)}
function Rectangle(w, h) {
this.width = w;
this.height = h;
}
Rectangle.prototype.copy = function() { return new this.constructor(this.width, this.height)}
function PositionedRectangle(x, y, w, h) {
Rectangle.call(this, w, h);
this.x = x;
this.y = y;
}
PositionedRectangle.prototype = Object.create(Rectangle.prototype);
const posRect = new PositionedRectangle(1,2,3,4);
const samePosRect = posRect.copy();
PositionedRectangle.prototype.toString = function() {
return "(" + this.x + "," + this.y + ") " + // поля этого класса
Rectangle.prototype.toString.apply(this); // вызов надкласса по цепочке
}
PositionedRectangle.prototype.toString = function( ) {
return "(" + this.x + "," + this.y + ") " + // поля этого класса
this.superclass.prototype.toString.apply(this);
}
var Rectangle = function (w, h) {
this.width = w;
this.height= h;
}
var rect = new Rectangle(5, 10);
r.width //свойство экземпляра
свойства экземпляра в JavaScript – свойства, которые создаются и/или инициализируются функцией конструктором
var Rectangle = function (w, h) {
this.width = w;
this.height= h;
};
Rectangle.prototype.area = function() {return this.width * this.height};
var rect = new Rectangle(5, 10);
r.area//метод экземпляра
Методы экземпляра ссылаются на объект, или экземпляр, с которым они работают, при помощи ключевого слова this.
var Rectangle = function (w, h) {
this.width = w;
this.height= h;
};
Rectangle.prototype.area = function() {return this.width * this.height};
Rectangle.UNIT = new Rectangle(1,1);
r.UNIT //свойство экземпляра
var Rectangle = function (w, h) {
this.width = w;
this.height= h;
};
Rectangle.prototype.area = function() {return this.width * this.height};
Rectangle.max= function(r1, r2) {
if (r1.area() > r2.area()) {
return r1;
}
return r2;
};
Rectangle.max// метод класса
this ссылается на саму функцию конструктор
// superclass - Function
// constructor - Function
// methods - Object of Functions
function defineClass(superclass, constructor, methods) {
constructor.prototype = Object.create(superclass.prototype);
constructor.prototype.constructor = constructor;
constructor.prototype.superClass = superclass;
for(var m in methods) {
constructor.prototype[m] = methods[m];
}
return constructor;
}
PositionedRectangle = defineClass(
Rectangle,
function(x, y, w, h){
this.superClass(w,h);
this.x=x,
this.y=y
},
{perimeter:function(){return 2*(x+y)}}
)
function borrowMethods(borrowFrom, addTo) {
var from = borrowFrom.prototype; // прототип источник
var to = addTo.prototype; // прототип приемник
for(m in from) { // Цикл по всем свойствам прототипа-источника
if (typeof from[m] != "function") continue; // Игнорировать не функции
to[m] = from[m]; // Заимствовать метод
}
}
Классы-смеси, или просто смеси (Mixin) -
классы, разрабатываемые специально с целью заимствования, обычно ничего особо полезного не
делающие, зато реализующих методы, которые могут быть заимствованы другими классами.
function GenericToString() {}
GenericToString.prototype.toString = function( ) {
//реализация универсального метода toString
}
function GenericEquals() {}
GenericEquals.prototype.equals = function(compareTo) {
// реализация универсального метода equals
// для сравнения 2х объектов
}
// Заимствование некоторых методов
borrowMethods(GenericEquals, Rectangle);
borrowMethods(GenericToString, Rectangle);
// Эта смесь содержит метод, зависящий от конструктора. Оба они,
// и конструктор, и метод должны быть заимствованы.
function Colored(c) { this.color = c; }
Colored.prototype.getColor = function() { return this.color; }
// Определение конструктора нового класса
function ColoredRectangle(w, h, c) {
Rectangle.call(this, w, h); // Вызов конструктора надкласса
Colored.call(this, c); // и заимствование конструктора Colored
}
// Настройка объектапрототипа на наследование методов от Rectangle
ColoredRectangle.prototype = Object.create(Rectangle.prototype);
ColoredRectangle.prototype.constructor = ColoredRectangle;
// Заимствовать методы класса Colored в новый класс
borrowMethods(Colored, ColoredRectangle);
// jQuery
// jQuery.extend( [deep ], target, object1 [, objectN ] )
// Returns target
var object1 = {
apple: 0,
banana: { weight: 52, price: 100 },
cherry: 97
};
var object2 = {
banana: { price: 200 },
durian: 100
};
$.extend(object1, object2) // Merge object2 into object1
object1 //{"apple":0,"banana":{"price":200},"cherry":97,"durian":100}
_.assign, _.merge from lodash, angular.extend
class Rectangle {
constructor(w, h) { //class constructor
this.width = w;
this.height = h;
}
area() { //class method
return this.width * this.height;
}
}
var rect = new Rectangle(5, 10);
rect.width // 10
rect.area() // 50
rect.hasOwnProperty("area") //false
const iForgotNew = Rectangle(10, 15);
Uncaught TypeError: Class constructor Rectangle cannot be invoked without 'new'
class Rectangle {
constructor(w, h) { //class constructor
this.width = w;
this.height = h;
}
static max(r1, r2) { // Rectangle.max
if (r1.area() > r2.area()) {
return r1;
}
return r2;
}
}
class Rectangle {
constructor(w, h) { //class constructor
this.width = w;
this.height = h;
}
static defaultRect() { // Rectangle.defaultRect
return new Rectangle(1, 1);
}
}
Rectangle.defaultRect = new Rectangle(1,1);
Object.defineProperty(Rectangle, defaultRect, {value: new Rectangle(1,1)});
static get ZERO() {
return new Point(0, 0);
}
class Rectangle {
constructor(w, h) { //class constructor
this.width = w;
this.height = h;
}
static defaultRect() {
return new Rect(1,1);
}
toString() {
return `Dimensions are ${this.width} x ${this.height}`;
}
}
class PositionedRectangle extends Rectangle {
constructor(x, y, w, h) {
super(w, h);
this.x = x;
this.y = y;
}
toString() {
return `${super.toString()}, located on ${this.x}, ${this.y}`;
}
}
var pRect = new PositionedRectangle(2, 2, 2, 2);
PositionedRectangle.defaultRect(); // {width: 1, height: 1}
class Rectangle {
constructor(w, h) { //class constructor
this.width = w;
this.height = h;
}
}
function colorMixin(Base) {
return class extends Base {
setColor (color) {
this.color = color;
}
}
}
class coloredRectange extends colorMixin(Rectangle) {}
By Viktor Shevchenko