Вот пример:JavaScript кластерные методы в суб-объекты
var Bidule = function() {
this.value = 8 ;
this.calc = {
plus : function(x) { return this.value + x ; },
minus : function(x) { return this.value - x ; },
square : function() { return this.value * this.value ; }
}
this.fn = {
random : {
set : function() { return this.value = random() ; },
add : function() { return this.value += random() ; }
}
}
} ;
var b = new Bidule() ;
console.log(b.value) ; // 8
console.log(b.calc.plus(4)) ; // Error : 'this.value' is undefined.
console.log(b.fn.random.add()) ; // Error : 'this.value' is undefined.
Дело в том, что кластерный методы, как она выглядит более элегантно, чем мне «b.fn_random_add()».
Это легко исправить «это» ссылка:
var _plus = b.calc.plus ;
b.calc.plus = function() {
return _plus.apply(b, arguments) ;
} ;
console.log(b.calc.plus(4)) ; // 12
Однако ни предыдущий «this.calc.plus», ни новый набор один находятся в прототипе Bidule в.
Я думал о том, подобъектах со своим прототипом, как:
this.calc = new Bidule_calc ;
Но я не был бы в состоянии установить главный объект «это» ссылки.
Есть ли другой способ, чем ...:
b.calc.plus.call(b, 4) ;
... установить и вызвать кластерные методы?
Как я пишу это, я только что узнал, возможное решение:
var context = this ;
Object.defineProperty(this.calc, 'value', {
get : function() {
return context.value ;
}
}) ;
Однако, есть еще проблема бесцельно дублирующих функций, как «this.calc» не в прототип и «Object.defineProperty» будут вызываться для каждого экземпляра Bidule, поэтому будут созданы дублированные функции для переопределения кластеризованных методов.
Edit: я должен точено, что мы должны использовать прототип для всех методов:
var Bidule = function() {
this.value = 8 ;
} ;
Bidule.prototype = {
getValue : function() { return this.value ; }
} ;
Хотя конструктор Bidule и прототип имеет два разделенных областей. Это означает, что мы не можем делиться никаким «var» в конструкторе, который будет использоваться для методов.
Быстрое «исправление» заключается в том, чтобы объявить «var that = this;» в верхней части вашей основной функции, а затем ссылаться на «это» во всех подмодулях, когда вам нужно ссылаться на владельца «Bidule». Во-вторых, нет метода 'random()', поэтому вы не можете просто делать '= random();', поэтому ваши 'fn.random.set' и' fn.random.add' не будут работать – Ian
Is есть причина, по которой вы хотите, чтобы ваши методы были вложены так? Это не типичная идиома JavaScript из-за проблемы «этого». Почему бы не поставить их прямо на «Bidule.prototype»? Тогда вы можете просто сделать b.plus (4) '. –
@ Lan: Я знаю, что 'random()' не существует, просто нужно просто привести пример. И хм ... Я знал, что настройка 'this' в переменной будет работать, но прототип не получит доступ к частной переменной' that'. @ Crazy Train: Я знаю, что это не типично, но я нашел и эту проблему, и способ реализации этого интересного. Я хотел получить ответы других и точки зрения. – Tot