Примечания к «частичному решению»:
Обратите внимание, что фрагменты кода, размещенные ниже, показывают только "некоторые альтернативы, которые могут или не могут предоставить достаточно, чтобы обойтись". Это потому, что они не захватывают значения (объекты Player) внутри конструктора, а только переносят значения, идущие внутрь.
«Полное решение» может также обернуть конструктор Player и использовать свойство или другой механизм, чтобы «запомнить» объекты, созданные для различных входных значений; альтернативно, он может запомнить порядок создания объекта . Затем его можно использовать для переноса Match, а затем извлекать созданных игроков из общего хранилища после запуска конструктора Match - однако эти детали оставляются в качестве упражнения. Код переноса Player может использовать код, представленный ниже (при условии, что Player является глобальным / доступным свойством).
Точный запрос невозможен с учетом вышеуказанного контекста.
Переменные (реальные переменные, а не свойства) доступны только из области, в которой они объявлены, или из вложенной области, поскольку они разрешаются через цепочки областей. Это также включает использование eval
. Хотя это может показаться ограничением, оно также гарантирует, что цепочки областей видимости (и их переменные) не могут быть извлечены извне, если они не раскрыты.
Однако рассмотрим этот забавный подход, использующий тот факт, что явный объект можно return
редактировать из Конструктора:
var oldMatch = Match
// note this form, else above would be pre-clobbered
Match = function Match (playerRed, playerBlue) {
var m = new oldMatch(playerRed, playerBlue)
// either "inject" method here, or save in object for later
m.myPlayerRed = playerRed
m.myPlayerBlue = playerBlue
return m
}
Конечно, это сломает такие вещи, как new Match(...) instanceof Match
.
Удачного кодирования.
Обновление:
Вот модификация вышеописанного для работы с методом «обернуть конструктор в новый конструктор, а затем установить равные прототипы», как обсуждалось в ссылке в посте. Хитрость заключается в «краже» имени глобального свойства. Я также изменил код, чтобы oldMatch
оставался закрытым, чтобы избежать загрязнения.
// note this form, else Match property would be pre-clobbered
Match = (function (oldMatch) {
function Match (playerRed, playerBlue) {
oldMatch.call(this, playerRed, playerBlue);
// either "inject" method here, or save in object for later
this.myPlayerRed = playerRed
this.myPlayerBlue = playerBlue
}
Match.prototype = oldMatch.prototype
return Match
})(Match)
В отличие от первого фрагмента кода, он должен работать с new Match(...) instanceof Match
, но он все равно может сломаться в зависимости от конкретных предположений, сделанных в методах объекта Match.
Пример того, как инвертировать («извлечь») данные из конструктора Player:
// original -- remember this method will only work
// if Player is used as a property (and not itself a closure'd variable)
function Player (name) {
this.name = name
}
Player = (function (oldPlayer) {
function Player (name) {
oldPlayer.call(this, name)
var fn = arguments.callee
fn.recent = fn.recent || []
fn.recent.push([name, this])
}
Player.prototype = oldPlayer.prototype
return Player
})(Player)
var p1 = new Player("fred");
var p2 = new Player("barney");
alert("instanceof check? " + p1 instanceof Player)
alert("name check? " + ("barney" == p2.name))
alert(Player.recent.join(","))
Player.recent = [] // reset