Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Почему не работает код? Вопрос о this.constructor. (https://javascript.ru/forum/misc/31272-pochemu-ne-rabotaet-kod-vopros-o-constructor.html)

FINoM 31.08.2012 21:57

Почему не работает код? Вопрос о this.constructor.
 
Есть всем известный самый простой вариант наследования:
X = function() {}
Y = function() {}
X.prototype.method = function() {alert( "ок" )};
Y.prototype = new X;
y = new Y;
y.method();
Здесь мы присваиваем прототипу Y объект, полученный из конструктора X. Всё логично.

По умолчанию, если мы не используем наследование, то в объекте свойство constructor хранит ссылку на свой конструктор (кэп).
Y = function() {};
y = new Y;
alert( y.constructor === Y );


Но, если мы делаем финт ушами и меняем прототип Y через свойство constructor, ничего из X не наследуется:
X = function() {}
Y = function() {}
X.prototype.method = function() { alert( 'ок' ) };
y = new Y;
alert( y.constructor === Y );
y.constructor.prototype = new X;
alert( y.constructor.prototype === Y.prototype );
y.method();


Почему?

UPD
Так, кстати, тоже не работает:
X = function() {}
Y = function() {}
X.prototype.method = function() { alert( 'ok' ) };
y = new Y;
Y.prototype = new X;
y.method();


Оказывается, я не знаю Javascript.

Dim@ 31.08.2012 22:06

FINoM,
потому что объект y уже создан и не расширяется прототипом Y зато следующие объекты Y будут иметь метод method
X = function() {}
Y = function() {}
X.prototype.method = function() { alert( 'ок' ) };
y = new Y;
alert( y.constructor === Y )
y.constructor.prototype = new X;
yy = new Y;
yy.method();

FINoM 31.08.2012 22:13

Цитата:

Сообщение от Dim@
потому что объект y уже создан и не расширяется прототипом Y зато следующие объекты Y будут иметь метод method

Это я уже понял. Но, я всегда думал, что, если метод не найден в прототипе конструктора, он будет искать его дальше:
C.prototype.method > не найден
C.prototype.constructor.prototype.method > не найден
C.prototype.constructor.prototype.constructor.prot otype.method ... и так дальше, пока ...prototype.constructor !== ...prototype.constructor.prototype.constructor

FINoM 31.08.2012 22:16

Что характерно:
X = function() {}
Y = function() {}
X.prototype.method = function() { alert( 'ok' ) };
y = new Y;
y.constructor.prototype = new X;
alert( y instanceof Y );
alert( y instanceof X );

Dim@ 31.08.2012 23:13

Цитата:

Сообщение от FINoM
Но, я всегда думал, что, если метод не найден в прототипе конструктора, он будет искать его дальше:
C.prototype.method > не найден
C.prototype.constructor.prototype.method > не найден
C.prototype.constructor.prototype.constructor.prot otype.method ... и так дальше, пока ...prototype.constructor !== ...prototype.constructor.prototype.constructor

Блин я тоже так думал, но после этого убедился что это не так
X = function() {}
Y = function() {}
X.prototype.method = function () { alert( 'ok' ) };
y = new Y;
Y.prototype = new X;
alert( y.method );//undefined
alert( y.constructor.prototype.method );//function () { alert( 'ok' ) }

становиться очевидно что при создании объекта что то летает по внутренностям добавляя свойства и методы только один раз что бы потом не искать прототипе
P.S. спасибо за тему - кое что из неё я усвоил :thanks:

9xakep 31.08.2012 23:59

Цитата:

Сообщение от Dim@
что при создании объекта что то летает по внутренностям добавляя свойства и методы

прости что?

nerv_ 01.09.2012 01:17

Цитата:

Сообщение от FINoM
Так, кстати, тоже не работает:

у Фленагана ошибка?
Цитата:

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

FINoM 01.09.2012 01:20

Цитата:

Сообщение от nerv_
у Фленагана ошибка?

Тут неоднозначно написано:
Цитата:

Сообщение от nerv_
были добавлены в прототип после создания объекта

Я ведь прототип переопределил, а не добавил новое свойство.

nerv_ 01.09.2012 01:25

Цитата:

Сообщение от FINoM
Я ведь прототип переопределил, а не добавил новое свойство.

твоя правда
var X = function() {}
var Y = function() {}
X.prototype.method = function() { alert( 'ok' ) };

var y = new Y;
Y.prototype.method = X.prototype.method;

y.method();

nerv_ 01.09.2012 13:10

Цитата:

Сообщение от FINoM
Так, кстати, тоже не работает:

http://learn.javascript.ru/task/prot...osle-sozdaniya

Цитата:

Сообщение от FINoM
Я ведь прототип переопределил, а не добавил новое свойство.

Цитата:

Сообщение от nerv_ (Сообщение 202164)
твоя правда
var X = function() {}
var Y = function() {}
X.prototype.method = function() { alert( 'ok' ) };

var y = new Y;
Y.prototype.method = X.prototype.method;

y.method();

http://learn.javascript.ru/task/izme...osle-sozdaniya


http://learn.javascript.ru/prototype#свойство-prototype

думаю, тему можно закрывать.

FINoM 01.09.2012 16:04

nerv_, а где список всех задач посмотреть?

nerv_ 01.09.2012 18:36

FINoM, я знаю только этот способ - здесь нажать показать/спрятать задачи.

FINoM 01.09.2012 23:59

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

В разделе "ваши сайты и скрипты" я предложил два метода: использовать __proto__ и тупо соединить старый прототип с новым объектом, просто копируя новые свойства.

FINoM 02.09.2012 03:49

После долгого и нудного гугления, определил, что никак. Когда-нибудь в браузерах появится Object.setProrotypeOf, но сейчас этот метод только обсуждается.

devote 02.09.2012 04:16

вот нашел у себя в хламе давно как то экспериментировал:
function setProto( object, proto ) {

	if ( "__proto__" in Object.prototype ) {
		return object.__proto__ = proto, object;
	}

	var protoFn = function() {},
		hasDefine = false;

	try {
		Object.defineProperty({}, 'test', {value:null});
		hasDefine = true;
	} catch( _e_ ) {}

	protoFn.prototype = proto;
	proto = new protoFn();

	for( var key in object ) {
		if ( object.hasOwnProperty( key ) ) {
			if ( hasDefine ) {
				Object.defineProperty( proto, key, Object.getOwnPropertyDescriptor( object, key ) );
			} else {
				proto[ key ] = object[ key ];
			}
		}
	}

	return proto;
}


var a = {
	get name() {
		return "Hello";
	},
	testA: function() {}
}

var b = {
	get name() {
		return Object.getPrototypeOf( this ).name + " world";
	},
	testB: "str",
	he: undefined
}

var c = {
	name: function() {
		return Object.getPrototypeOf( this ).name + " world test";
	}
}

b = setProto( b, a )
c = setProto( c, b );

alert( c.name() );

FINoM 02.09.2012 04:19

devote, да, я тоже такое решение нашел. Но нужно не вернуть объект с новым прототипом, а привязать к уже готовому.

FINoM 02.09.2012 04:23

А вот зачем мне это: http://javascript.ru/forum/project/3...edovaniya.html (если ты тему раньше не заметил).

devote 02.09.2012 04:34

Цитата:

Сообщение от FINoM
а привязать к уже готовому.

ну это вряд ли сделаешь, а тупое копирование приведет к разрушению наследования.. То есть instanceof перестанет работать как надо.

devote 02.09.2012 04:35

Цитата:

Сообщение от FINoM
(если ты тему раньше не заметил).

я видел эту тему

nerv_ 02.09.2012 11:59

Цитата:

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

модифицировать можно. Вопрос в том, требуется ли, чтобы ранее созданные объекты имели доступ к новым методам и свойствам. Привязка новых свойств к прототипу после создания объекта не "совсем правильно".


Часовой пояс GMT +3, время: 15:23.