Почему методы массива находятся в прототипе, а не в конструкторе? 
		
		
		
		Приветствую) 
	Почему стандартные объекты в JavaScript (вроде строк или массивов) наследуют свои методы из прототипа, вместо того, чтобы задать их присваиваниями в своём конструкторе? То есть почему в Array делается так: 
function Array() {}
Array.prorotype = {
    push: function (...) {...},
    ...
};
Вместо того, чтобы сделать так: 
function Array() {
    this.push = function (...) {...};
    ...
}
Ведь именно конструктор - место для задания полей будущего объекта, а прототип - это способ реализовать наследование. Я хочу сказать, что такая архитектура не типична, и если бы вам нужно было реализовать массивы в C++, то вы бы обошлись одним классом, а не двумя с наследованием. Так что каждый раз при создании своих объектов приходится решать для себя дилемму: следовать этой странной яваскриптовой традиции или сделать "по-нормальному". Может быть я чего-то не понимаю, хочется понять причины такой вот яваскриптовой традиции. У меня есть некоторые догадки на этот счёт, но мне бы хотелось узнать ваше мнение) Вот мои мысли: 1) Расширение функциональности. Чтобы можно было легко расширить функциональность всех строк. Кроме того можно легко поменять прототип для всех новых объектов. Это правда считается дурным тоном, нарушением инкапсуляции и вообще ведёт к конфликтам. Так что в нормальных классовых языках этому вообще нет аналога. 2) Производительность. Немного ускоряется создание новых объектов, так как нет множества присваиваний в конструкторе. Однако также немного замедляется обращение к методам, так как приходится дольше их искать. 3) Красивая структура. Чтобы получилась более красивая структура объектов. Если унаследоваться от прототипа, а не от полноценного массива, то потомок не будет засоряться локальными для массива данными вроде length. Хотя обратное вовсе не вредит. Напротив, тогда этот length можно не инициализировать руками в своём потомке.  | 
	
		
 Цитата: 
	
  | 
	
		
 Вряд ли так уж в разы. Функция - это особый вид объекта. Объекты копируются по ссылке, а не по значению. Значит, чтобы избежать излишнего потребления памяти достаточно вытащить определения методов из конструктора (чтобы эти функции-методы не создавались каждый раз при создании нового объекта). 
	Было: 
function Array() {
    this.push = function (...) {...};
    ...
}
Стало: 
function push(...) {...}
function Array() {
    this.push = push;
}
Тогда мы тратим память лишь на хранение ссылок в каждом инстансе, а это совсем не так страшно, так как ссылка мало весит.  | 
	
		
 Цитата: 
	
 var x = 1 /* и тут ты задаешь присваиванием в своем конструкторе */ + 2 /* тут тоже */ + 3 /* и тут */ т.о. для того, чтобы сложить три числа, тебе надо вручную построить три объекта. Аналогично и со строками. Не бред ли? var x = 1 + 2 + 3 // === var y = 1..valueOf() + 2..valueOf() + 3..valueOf(); alert( x ); alert( y ); хотя, скорее всего, примитивы оборачиватюся в объекты только при необходимости В целом могу сказать, что: "хотите писать на js, забудьте про классы, привыкайте (наслаждайтесь) прототипами" Цитата: 
	
  | 
	
		
 Цитата: 
	
 Цитата: 
	
 Например, если вам надо сделать цепочку наследований, такого плана: 
{
    a: function () {},
    __proto__: {
        b: function () {},
        __proto__: {
            c: function () {}
        }
    }
}
То вы не сможете решить прототипами задачу оптимизации, так как прототип уже использован под наследование: 
function A() { this.a = function () {}; }
A.prototype = new B(); // Сюда не получится запихнуть реализацию метода a.
function B() { this.b = function() {}; }
B.prototype = { c: function () {} };
 | 
	
		
 Цитата: 
	
 Цитата: 
	
 
function A() { this.a = A.a  }
A.prototype = new B(); // Сюда не получится запихнуть реализацию метода a.
A.a = function () {};
function B() { this.b = function() {}; }
B.prototype = { c: function () {} };
? (один из вариантов) забыли про 
function A() { }
A.prototype = new B(); // Сюда не получится запихнуть реализацию метода a.
A.prototype.a = function () {};
function B() { this.b = function() {}; }
B.prototype = { c: function () {} };
 | 
	
		
 Цитата: 
	
 В вашем 1-м варианте вы предварительно сохраняете ссылку на метод в свойство конструктора. Я сохраняю в независимую переменную. Куда бы мы её не сохраняли - принцип один и он не имеет отношения к теме наследований. А во 2-м предложенном варианте вы создадите объект другой структуры: 
{ // A
    __proto__: { // B
        a: function () {},
        b: function () {},
        __proto__: { // C
            c: function () {}
        }
    }
}
Что-то я тут расфлудился) Надеюсь, я никого не утомил своими изысканиями.  | 
	
		
 Цитата: 
	
 Цитата: 
	
 Цитата: 
	
  | 
	
		
 Думаю, что я понял почему так сделано) 
	Дело не в том, что это какой-то идеально-правильный способ реализовывать ООП в яваскрипте. Всё дело в литералах. 'text' - литерал строки, [ 1, 2, 3 ] - литерал массива, /^nya$/ - литерал регулярки и т.д. Ими все пользуются и никто от них не собирается отказываться. Каждому литералу соответствует конструктор (можно сказать класс). Мы не можем заменить этот класс на другой. Поэтому единственная возможность расширить/изменить функционал классов, связанных с литералами - модифицировать сам класс. И вот нам дали эту единственную возможность - средствами языка через прототип. Между прочим та же проблема есть в других языках (например Ruby) и решается она там точно также, через модификацию стандартного класса. А если же мы строим какие-то свои классы (которым не соответствуют никакие литералы языка), то совершенно не обязательно и не нужно в общем случае городить этот дополнительный слой наследований.  | 
	
		
 Цитата: 
	
  | 
| Часовой пояс GMT +3, время: 05:58. |