Добавление объекта с методами к конструктору
Приветствую!
Можно ли после создания конструктора добавить к нему объект с методами, использующими методы этого конструктора?
function CreateTest(name) {
this.name = name;
this.roll = () => ["simple", "hard"][Math.round(Math.random())];
/*
// объявление объекта внутри конструктора работает
this.renameObj = {
rename: function() {
return this.name = `${this.roll()} ${this.name}`;
}.bind(this)
};
*/
}
/*
// добавление объекта после объявления конструктора не работает
CreateTest.renameObj = {
rename: function() {
return this.name = `${this.roll()} ${this.name}`;
}.bind(CreateTest)
};
*/
let test = new CreateTest("js test");
test.renameObj.rename();
|
В javascript прототипное наследование.
Все методы добавляются в любое время в CreateTest.prototype. |
Так тоже не работает
CreateTest.prototype.renameObj = {
rename: function() {
return this.name = `${this.roll()} ${this.name}`;
}.bind(CreateTest)
};
Выдает ошибку "this.roll is not a function". |
Ты ищешь свойство у объекта созданного функцией а добавляешь свойство самой функции которая тоже ведет себя как объект.
Естественно объект созданный функцией и функция создающая объект это разные объекты и свойства у них разные |
Забавная задачка, ибо каждый объект в js независим, и никак обратно не связан со своим "родителем". Тут надо подумать, как сделать по-красивее.(но лучше вообще так не делать:))
|
А как же свойство Obj.__proto__.constructor ?
|
Думаю, надо объяснить, откуда вообще взялась эта задача. Я пишу библиотеку для работы с анимациями. В ее основе конструктор, содержащий свойства - координаты передаваемого в качестве аргумента DOM элемента, часть методов предназначена для работы с этими свойствами, а остальные методы - это методы-обертки, необходимые для вызова пользовательских функций (упакованных вместе с их параметрами в объекты). Т.е. пользователь может написать простую функцию, меняющую координаты элемента по некой формуле, поместив ее со своими параметрами в объект, затем вызвать ее через функцию обертку с промисом и raf. При этом он абстрагируется от асинхронной логики и думает только над уравнением перемещения. Чтобы это осуществить, как раз и требуется добавить объект в конструктор (тоже через обертку, чтобы это мог делать пользователь-новичок, не знакомый с ООП в js).
|
MallSerg, под "родителем" я имел ввиду не конструктор, а тот объект в котором он лежит. Наверно надо было сказать "никак не связан со своим контейнером"?)
|
Aetae,
То же не совсем понятно Есть родитель на которого всегда ссылка obj.prototype Есть функция создающая объект на которую указывает ссылка Obj.__proto__.constructor Есть this который динамически заменяется и всегда указывает в контексте какого объекта он исполняется.
<script>
function GetName() { return this.name; }
var vasa = {name: "Вася"};
var lena = {name: "Лена"};
var petia = {name: "Петя"};
vasa.gn = GetName;
lena.gn = GetName;
petia.gn = GetName;
document.write ( vasa.gn() + "<br>") ;
document.write ( lena.gn() + "<br>") ;
document.write ( petia.gn() + "<br>") ;
</script>
R2R, Без конкретного тестового примера понять что то сложно возможно использование наследования поможет небольшой пример
<script>
function CreateTest (){
this.__proto__ = CreateTest;
this.x = 5;
this.y = 20;
}
var ele = new CreateTest();
CreateTest.newFunc = function ( par){
alert ( this.x + this.y + par );
} ;
ele.newFunc ("----");
</script>
|
MallSerg, он хочет примерно такую наркоманию:
function CreateTest(name) {
this.name = name;
this.roll = () => ["simple", "hard"][Math.round(Math.random())];
/*
// объявление объекта внутри конструктора работает
this.renameObj = {
rename: function() {
return this.name = `${this.roll()} ${this.name}`;
}.bind(this)
};
*/
}
Object.bindedAppend = function(parent, name, child){
Object.defineProperty(parent.prototype, name, {
configurable: true,
enumerable: true,
get: function(){
if(this === parent.prototype)
return child;
return this[name] = new Proxy(this, {
get: (p, key) => key in child ? child[key] : this[key],
set: (p, key, val) => this[key] = val
})
}
});
return child
};
Object.bindedAppend(CreateTest, 'renameObj', {
rename: function() {
return this.name = `${this.roll()} ${this.name}`;
}
});
var test3 = new CreateTest("js test");
test3.renameObj.rename();
alert(test3.name)
|
var CreateTest = function CreateTest(name) {
this.name = name
this.roll = () => ['simple', 'hard'][Math.round(Math.random())]
}
CreateTest.prototype.renameObj = function () {
return {
rename: () => {
return this.name = `${this.roll()} ${this.name}`
}
}
}
var test = new CreateTest('js test')
console.log(test.renameObj().rename())
мои 5 копеек %) |
Цитата:
примерно так
function CreateTest(params) {
this.name = params.name;
this._calcFunc = params.calcFunc;
}
CreateTest.prototype = {
constructor: CreateTest,
move: function() {
var calcResult = this._calcFunc();
// ...
}
};
var test = new CreateTest({
name: '...',
calcFunc: function() { return 2 + 2; }
});
test.move();
|
SuperZen, все бы хорошо, только надо передавать объект, а не функцию)
Alexandroppolus, надо передавать в функцию объект, чтобы он записывался в конструктор. Aetae, Ваша реализация очень хороша, я немного подкорректировал ее:
function CreateTest(name) {
this.name = name;
this.roll = () => ["simple", "hard"][Math.round(Math.random())];
}
function bindedAppend(parent, name, child) {
Object.defineProperty(parent.prototype, name, {
configurable: true,
enumerable: true,
get: function() {
return this[name] = new Proxy(this, {
get: (p, key) => key in child ? child[key] : this[key],
set: (p, key, val) => this[key] = val
})
}
});
};
bindedAppend(CreateTest, 'renameObj', {
value : 7,
rename: function() {
return this.name = `${this.roll()} ${this.name}`;
}
});
let test3 = new CreateTest("js test");
test3.renameObj.rename();
console.log(test3.name, test3.renameObj.value);
Придумаю потом, как объявить bindedAppend в конструкторе, будет совсем конфетка) |
| Часовой пояс GMT +3, время: 09:40. |