# Прототипное ООП. ## Идея. Прототипное ООП в **JS** базируется на простой идее, которую следует запомнить: каждый объект имеет прототип, т. е. другой *объект*, в котором ищуться *поля* в случае отсутствия их в оригинальном объекте: ```javascript var a = {}; a.toString() // "[object Object]" a.__proto__ // Object {} a.__proto__.constructor // function Object() { [native code] } ``` `a.toString()` отсутствует как явно определенный в объекте `a`, однако он найден в *прототипе* `Object`. ```javascript function Drawable(){ Drawable.prototype.addInstance(this); } Drawable.prototype.draw = function(){}; Drawable.prototype.instances = []; Drawable.prototype.addInstance = function(item){ Drawable.prototype.instances.push(item); } Drawable.prototype.drawAll = function(){ for(var i = 0; i<Drawable.prototype.instances.length;i++){ Drawable.prototype.instances[i].draw(); } } ``` Определенные в прототипе поля являются статическими (общими) для класса, так как у всех объектов класса есть *один* объект-прототип. При этом они работают как методы *каждого* объекта, если используют `this`, являющийся ссылкой на конкретный объект. ## Наследование Наследование в **JS** обычно реализуется в два этапа - создание *одного* объекта с прототипом предка, насыщение его общими и статическими методами *этого* класса, после чего использование этого объекта в качестве *прототипа* для объектов класса: ```javascript function Field(width, height, step, scale){ Drawable.apply(this); this.width = width || 10000; this.height = height || 10000; this.step = step || 50; this.scale = scale || 1; for (var i = 0;i<100;i++){ new Food(Math.random()*this.width, Math.random()*this.height, Math.random()*10, colors[Math.floor(Math.random()*colors.length)]); } } Field.prototype = Object.create(Drawable.prototype); //!!! Field.prototype.constructor = Field; Field.prototype.draw = function(){ for (var i=0;i < this.width; i += this.step){ ctx.beginPath(); ctx.moveTo(i,0); ctx.lineTo(i,this.height); ctx.stroke(); } for (var i=0;i < this.height; i += this.step){ ctx.beginPath(); ctx.moveTo(0,i); ctx.lineTo(this.width,i); ctx.stroke(); } } ``` ## Пример https://jsfiddle.net/42jgnfcq/58/