ГЛАВНАЯ     АРХИВ     НАПИСАТЬ АДМИНУ     ПОДПИСАТЬСЯ НА RSS     ВОЙТИ      

Поиск

Категории

Облако тегов

  << Предыдущий пост       Следующий пост >>  
От: inbruk
23. сентября 2012 01:51

JavaScript

Что такое прототипы в JavaScript ? Прототипы это объекты от которых другие объекты наследуют свойства. Любые объекты могут быть прототипами. Все объекты имеют прототипы по умолчанию. Так как прототипы сами по себе объекты, то каждый из прототипов имеет прототип тоже. За исключением прототипа по умолчанию, находящегося на вершине любой цепочки прототипов. Давайте вернемся немного назад. Что тfкое объект в JavaScript ? Объект в JavaScript это любая не отсортированная коллекция пар ключ-значение. Примитивные типы, такие как undefined, null, boolean, number или string не являются объектами. Мы говорили что все объекты имеют прототипы, но если мы напишем ({}).prototype мы получим undefined. Наибольшим источником путаницы о прототипах является свойство prototype. Ссылка на настоящий прототип объекта находится во внутреннем свойстве [[Prototype]]. ECMA 5 вводит стандартный стандартный доступ через Object.getPrototypeOf(object) который сейчас уже реализован в Firefox, Safari, Chrome и IE9. Также большинство браузеров (кроме IE) поддерживают не стандартный доступ через свойство __proto__. Поэтому нас постигнет неудача, если мы спросим конструктор объекта о его свойстве prototype.

var a = {};

//Fails in Opera or IE<=8
Object.getPrototypeOf(a); //[object Object]

//Fails in IE
a.__proto__; //[object Object]

//all browsers 
//(but only if constructor.prototype has not been replaced and fails with Object.create)
a.constructor.prototype; //[object Object]


Это все хорошо, но почему тогда false.__proto__ возвращает значение, хотя false это примитив ? Когда у примитива запрашивается свойство prototype, то примитив приводится к объекту.

//(works in IE<=8 too, due to double-negative)
false.__proto__ === Boolean(false).__proto__; //true


Если нам захочется использовать прототипы для наследования, то что мы должны сделать ? Изредка складывается ощущение, что множество прототипов относится только к одной сущности и только к ней одной. Тогда можно было бы просто добавить значение свойства прямо к сущности. Например, у нас есть объект и мы хотим добавить ему функционал объекта Array, тогда это бы выглядело так:

//fails in IE<=8
var a = {};

a.__proto__ = Array.prototype;

a.length; //0


Но реальную силу прототипов мы увидим, когда несколько экземпляров объекта разделяют один прототип. Свойства объекта прототипа, определенные однажды в нем будут унаследованы всеми объектами - потомками. Это соображение важно для производительности и поддержания. Тогда что происходит в констркторе ? Конструктор предполагает кросс-браузерный механизм присваивания прототипа объекту во время его создания. Но тогда что значит constructor.prototype ? Дело в том что JavaScript не делает различия между конструкторами и другими функциями. Так что каждая функция получает свойство prototype. Отсюда следует, что все что не является функцией, не имеет такого свойства.


//function will never be a constructor but it has a prototype property anyway
Math.max.prototype; //[object Object]

//function intended to be a constructor has a prototype too
var A = function(name) {
	this.name = name;
}
A.prototype; //[object Object]

//Math is not a function so no prototype property
Math.prototype; //null


Теперь можно сформулировать определение: в свойстве функции prototype находится объект, который будет присвоен как прототип для всех экземпляров объектов созданных, когда функция используется в качестве конструктора. Здесь важно понимать, что свойство функции prototype ничего не имеет общего с ее настоящим (актуальным) прототипом.


//(example fails in IE)
var A = function(name) {

	this.name = name;
}

A.prototype == A.__proto__; //false

A.__proto__ == Function.prototype; //true - A's prototype is set to its constructor's prototype property



Возможно вы видели подобное уже тысячи раз, но посмотрите еще раз, теперь с другой перспективы.


//Constructor. <em>this</em> is returned as new object and its internal [[prototype]] 
//property will be set to the constructor's default prototype property
var Circle = function(radius) {
    this.radius = radius;
    //next line is implicit, added for illustration only
    //this.__proto__ = Circle.prototype;
}

//augment Circle's default prototype property thereby augmenting the prototype of each generated instance
Circle.prototype.area = function() {
   return Math.PI*this.radius*this.radius;
}

//create two instances of a circle and make each leverage the common prototype
var a = new Circle(3), b = new Circle(4);
a.area().toFixed(2); //28.27
b.area().toFixed(2); //50.27


Это все хорошо. Но если мы изменим прототип конструктора, то все существующие экземпляры объекта получат доступ к новой версии правильно ? Нет, не совсем. Если я модифицирую свойство prototype уже существующего объекта, то так и случится, потому что a.__proto__ было определено при создании указывающим на A.prototype.

var A = function(name) 
{
    this.name = name;
}

var a = new A('alpha');
a.name; //'alpha'

A.prototype.x = 23;

a.x; //23


Но, если я заменю свойство prototype на новый объект, то a.__proto__ будет все еще указывать на оригинальный объект.

var A = function(name) {
    this.name = name;
}

var a = new A('alpha');
a.name; //'alpha'

A.prototype = {x:23};

a.x; //null


Так на что тогда похож прототип по умолчанию ? Это объект с одним свойством - конструктором.


var A = function() {};
A.prototype.constructor == A; //true

var a = new A();
a.constructor == A; //true (a's constructor property inherited from it's prototype)


Что делает выражение instanceof с прототипом ? Оно дает ответ true, если проверяемый объект входит в цепочку наследования от свойства prototype проверяемой функции, или false в другом случае. Дальше идет пример того, как замена прототипа на горячую, приводит к возвращению false выражением instanceof/

var A = function() {}

var a = new A();
a.__proto__ == A.prototype; //true - so instanceof A will return true
a instanceof A; //true;

//mess around with a's prototype
a.__proto__ = Function.prototype;

//a's prototype no longer in same prototype chain as A's prototype property
a instanceof A; //false


Так что еще могут прототипы ? Ранее я говорил, что каждый конструктор имеет свойство prototype, которое используется для присвоения прототипа, каждому создаваемому им объекту. Это работает с конструкторами таких нативных объектов как Function and String. Это дает возможность, расширяя, но не заменяя свойство prototype функции конструктора менять прототип каждого из таких объектов, добавляя нужный функционал.

String.prototype.times = function(count) {
    return count < 1 ? '' : new Array(count + 1).join(this);
}

"hello!".times(3); //"hello!hello!hello!";
"please...".times(6); //"please...please...please...please...please...please..."


Механизм наследования прототипов внутренний и не явный. Когда у объекта a запрашивается для расчета свойство (функция) foo, то JavaScript идет по цепочке прототипов ( начиная с самомго объекта a) и проверяет каждую ссылку в цепочке прототипов на существование свойства foo. И если свойство находится, то оно возвращается, если нет, но возвращается undefined.

Это перевод, а исходный текст взят отсюда

Похожие записи


Вопросы на собеседовании C#, Net, ASP.NET, SQL
Продолжая тему вопросов на собеседовании. Нашел еще одну подборку. Оригинал лежит здесь . Перенес, чтобы не затерялось. Есть вполне вменяемые ответы (хотя, на некоторые вопросы ответил бы по-другому). Ответы находятся после списка вопросов, я их не менял. 23. Что такое шаблон проектирования Model/View/Controller? Как и зачем его применяют? 2...

Что такое "стратегические изменения" в Windows 8?
Есть в английском языке такое слово, как "rethink". В последнее время стало оно очень популярно. Применяют его и по отношению к Windows8. И означает это слово в данном контексте, что подход в ней к решению многих задач совершенно иной, принципиально отличающийся от предыдущего. И если весь мир привык верить тому, что им вещают маркетологи, то русскоязычная публи...

Что такое Ogre 3D и как его едят ?
Оригинал статьи здесь. А это автор - Jere. Ogre 3D – это кросс-платформенное SDK для создания графических приложений. Она имеет довольно обширные возможности, такие как полная поддержка OpenGL и Direct3D, полная совместимость с платформами Windows, Linux, Mac OS X и iOS, поддержка широкого выбора файловых форматов, продвинутая система частиц, программирования ...

Добавить комментарий




biuquote
  • Комментарий
  • Предпросмотр
Loading


  Сохранить комментарий