2014-10-01 7 views
0

Я новичок в Javascript и задавался вопросом, как можно изменить переменную public в прототипе.Как манипулировать переменной в прототипе?

function Thing (val) 
{ 
    this.x = val; 

    this.addToX = function (valIn) 
    { 
     this.x += valIn; 
    }; 
} 

function ChildThing() 
{ 
    this.y = 55; 
} 

ChildThing.prototype = new Thing(10); 

var frank = new ChildThing(); 

console.log("out1: " + frank.x); 

frank.addToX(10); 

console.log("out2: " + frank.x); 

Этот код принимает значение в прототипе x, которое равно 10, и добавляет 10 к нему в функции addToX. Новое значение x сохраняется в объекте верхнего уровня, а не заменяет текущее значение x в прототипе.

Есть ли способ переписать существующий x в прототипе или я использую Javascript неправильно?

+3

Почему вы пытаетесь это сделать? https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – candu

+1

В общем, вы [не должны использовать возвращаемые значения 'new' для прототипов] (http: //programmers.stackexchange. ком/кв/198267/51295). – apsillers

+0

Хорошо, поэтому я, возможно, упростил свою актуальную проблему. Все сводится к моему плохому пониманию того, как наследование должно действительно работать в Javascript. Фактическая проблема заключается в том, что вызывается функция рендеринга, а координаты x, y берутся из прототипа x, y. При попытке изменить эти значения значения child x, y обновляются, а значения, которые фактически используются для визуализации, всегда остаются теми же, поэтому объект всегда рисуется в старом местоположении. –

ответ

1

Это зависит. Какой смысл изменить x на прототипе? Как правило, вы не хотите менять общие свойства. Но я полагаю, что может быть прецедент (генерирующий новый идентификатор?).

Что касается вопроса: вы можете просто сделать:

this.addToX = function(valIn) { 
    ChildThing.prototype.x += valIn; 
}; 

Опять я не совет это делать.

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

var my_proto = new Thing(10); 
ChildThing.prototype = my_proto; 

, а затем

this.addToX = function(valIn) { 
    my_proto.x += valIn; 
}; 

Или вы даже можете играть с the singleton pattern ,

+0

Это немного смешно, чтобы ссылаться на дочерний конструктор в суперклассе ... – plalx

+0

@plalx Это просто пример.Он может ссылаться на прототип напрямую, определяя его сначала: var new_proto = new Thing (10); '. И еще одно: в отличие от вашего ответа моя отвечает на вопрос. – freakish

+0

Спасибо за помощь! Использовал бы этот .__ proto __. X + = valIn; 'будет плохая идея? Это, похоже, дает похожие результаты тому, что вы предложили. –

0

Что вы, похоже, хотите, очень похоже на то, что статические членов на классических языках. Очень сложно ввести метод в экземпляр объекта, и этот метод изменит состояние других объектов за пределами его области. Поэтому я считаю, что вы не должны полагаться на прототипы вообще для такого поведения. Вот что вы могли бы сделать, чтобы имитировать статические элементы.

function SomeClass() {} 

SomeClass.staticMember = 'initial value'; 
SomeClass.changeStaticMember = function (val) { this.staticMember = val; }; 

SomeClass.changeStaticMember('another value'); 

Я считаю, что приведенный выше код является менее загадочным и лучше информирует о поведении. Однако, если вы все же хотите делиться изменяемыми значениями между экземплярами через прототип, вы можете просто не записывать свойство напрямую в качестве примитивного значения, а скорее переносить его в изменяемый общий объект, как показано ниже. Обратите внимание, что вся иерархия наследования будет иметь одно и то же значение x.

//Mutable class to encapsulate the value of X 
 
function XValue(val) { 
 
    this.value = val; 
 
} 
 

 
XValue.prototype = { 
 
    constructor: XValue, 
 

 
    valueOf: function() { return this.value; }, 
 

 
    set: function (val) { this.value = val; }, 
 

 
    add: function (val) { this.value += val; } 
 
}; 
 

 
function Thing(x) { 
 
    this.x = x; 
 
} 
 

 
Thing.prototype = { 
 
    constructor: Thing, 
 

 
    _x: new XValue(), //shared mutable object representing the value of X 
 

 
    get x() { return this._x.valueOf(); }, 
 

 
    set x(val) { this._x.set(val); }, 
 

 
    addToX: function (val) { this._x.add(val); } 
 

 
}; 
 

 
function ChildThing() { 
 
    Thing.call(this, 10); //call parent constructor 
 
} 
 

 
ChildThing.prototype = Object.create(Thing.prototype); 
 

 

 
//helper for snippet 
 
function log(text) { 
 
    var span = document.createElement('span'); 
 
    span.innerHTML = text; 
 
    document.body.appendChild(span); 
 
    document.body.appendChild(document.createElement('br')); 
 
} 
 

 

 

 
var ct = new ChildThing(); 
 

 
ct.addToX(10); 
 
log('ct.x → ' + ct.x); 
 
log('Thing.prototype.x → ' + Thing.prototype.x);