Получить объект содержащий caller
Данная тема создана с целью разделить два вопроса смешанных в одной теме здесь:
http://javascript.ru/forum/misc/3116...ascript-2.html Вкратце повторю суть задачи. Есть некий объект (A) у которого будут вызываться различные методы. И есть серия объектов (B1, B2, B3,...) которые будут обращаться к методам A. У B1, B2, B3,... общий прототип (P). В прототипе P или в конструкторе, при создании объекта, я могу создать что-либо, что позволит потом получить ссылку на этот объект. Теперь сама задача: когда B1, B2, B3,... обращается к методам A в этих методах я могу обратиться к "caller", но при этом я получаю ссылку на саму функцию прототипа P. А мне еще надо получить ссылку на объект у которого она была вызвана. Пока объект B1 существует в единственном экземпляре проблем нет - я его цепляю к прототипу и потом легко получаю, но как только появляется B2, B3,... уже достучаться до текущего объекта не получается. Объект A сейчас создается один раз и затраты на его создание сейчас большого значения не имеют. А вот объекты типа B будут создаваться регулярно и затраты на их создание мне надо максимально уменьшить. Т.е. минимализировать количество процедур в объекте B и аргументов передаваемых в объект A. Т.е. надо усложнять объект A, для того чтобы максимально упростить вызов его методов из объектов B. Так-же не будет проблемой если мы усложним конструктор объекта B. Теперь пример "не рабочего" кода, который я обещал привести: var A = { t : function() { var this_func = arguments.callee; // Ссылка на текущую функцию var caller = this_func.caller; // Ссылка на вызывающую функцию (в данном случае я получаю ссылку на свойство из прототипа) var that = caller.ref // Попытка получить ссылку на объект из которого произошел вызов alert(that.x); } } var B = function(x) { this.x = x; // Сохраняю свойство, для тестирования this.z.ref = this; // Пытаюсь сохранить ссылку на текущий объект, чтобы потом его получить. Но поскольку this.z фактически является свойством прототипа, это свойство потом презапишется } B.prototype = { x : "", z : function() { A.t(); } } var B1 = new B("LALA1"); B1.z(); var B2 = new B("LALA2"); B2.z(); Ключевые моменты в коде я прокомментировал. Если запустить код, том виде как я привел - вроде-бы все работает как надо. Мы получим, как и ожидаем два алерта: "LALA1" и "LALA2". Но если изменить финальную часть этого кода, например так: var B1 = new B("LALA1"); var B2 = new B("LALA2"); B1.z(); B2.z(); то все работает не правильно. Оба алерта будут "LALA2". Хотелось бы получить что-либо подобное, но правильно работающее. ;) |
хоть убейте до сих пор не пойму чем вам apply не подходит:
var A = { t : function() { alert(this.x); } } B = function(x) { this.x = x; // Сохраняю свойство, для тестирования } B.prototype = { x : "", z : function() { A.t.apply(this); } } B1 = new B("LALA1"); B2 = new B("LALA2"); B1.z(); B2.z(); |
Цитата:
Ну и вторая цель - вызовы из B1, мне надо сделать максимально простыми. Сейчас я делаю примерно так: var A = { t : function(that) { alert(that.x); } } B = function(x) { this.x = x; // Сохраняю свойство, для тестирования } B.prototype = { x : "", z : function() { A.t(this); } } B1 = new B("LALA1"); B2 = new B("LALA2"); B1.z(); B2.z(); и потом получаю ссылку на текущий объект как аргумент метода t(). По сути, это даже проще, чем то что Вы предлагаете. Но мне сейчас очень хочется отказаться от этого аргумента, если получится до него "достучаться" каким-либо другим способом. |
Цитата:
или вы считаете что так будет медленнее?мне кажется навряд ли медленне, хотя не уверен |
Gvozd,
Ну я же объяснил свои цели в начале: Цитата:
Но при этом сделать это так, чтобы это не вызвало путаницы. |
То есть усложнять конструктор B() и прототип создаваемых объектов нельзя?
ну, тогда не знаю как решить вашу задачу |
Цитата:
В прототипе так же можно создать какие-то вспомогательные методы, но только для того чтобы эти методы вызывались сами в какой-то момент. Чтобы тому кто будет писать B1, B2, B3,... не пришлось специально вызывать эти методы, иначе это будет сложнее чем передавать this через аргументы. |
я правильно понимаю:
var A = { t : function(that) { alert(that.x); } } B = function(x) { this.x = x; // Сохраняю свойство, для тестирования } B.prototype = { x : "", z : function() { A.t(this); } } //выше находится ваш код.там творим, все что нам надо //ниже код других людей.тут надо сделать чтобы все было максимально просто и прозрачно B1 = new B("LALA1"); B2 = new B("LALA2"); B1.z(); B2.z(); если нет, то перенесите разделитель на подобающее место. если же он там, то я не вижу усложнения рботы других людей код ниже не менялся на протяжении всей темы |
ok.
Вот так примерно работает тот скрипт, что у меня есть: var A = { t : function(that) { alert(that.x); } } var B = function() { this.tttt = 123; // Делаю что-то свое if(this.__constructor !== undefined && this.__constructor.constructor == Function) { this.__constructor.apply(this, arguments); // Вызываю "кастомерский" конструктор } } B.prototype = { some_special_method : function() { }, //выше находится наш код. Там творим, все что нам надо //ниже код других людей. Тут надо сделать чтобы все было максимально просто и прозрачно x : "", __constructor : function(x) // Конструктор других людей { this.x = x; // Сохраняю свойство, для тестирования }, z : function() { A.t(this); } } B1 = new B("LALA1"); B2 = new B("LALA2"); B1.z(); B2.z(); Теперь еще раз, с Вашего позволения, повторю задачу (для тех, кто возможно, не внимательно следил за нашим диалогом, но хочет сейчас к нему подключится). Надо в этой строчке: A.t(this); избавится от this, но таким образом, чтобы в вызываемом методе получить ссылку на текущий объект. |
так подойдет?
var A = { t : function() { alert(this.x); } } B = function(qwe) { this.x = qwe; // Делаю что-то свое if(this.__constructor !== undefined && this.__constructor == Function) { this.__constructor.apply(this, arguments); } } //конструкция, добавляющая A в верхнюю часть прототипирования B_proto_constr=function(){} B_proto_constr.prototype=A B.prototype=new B_proto_constr() //конструкция, добавляющая A в верхнюю часть прототипирования B.prototype.some_special_method = function() { }; //выше находится наш код. Там творим, все что нам надо //ниже код других людей. Тут надо сделать чтобы все было максимально просто и прозрачно B.prototype.x = "", B.prototype.__constructor = function() // Конструктор других людей { }; B.prototype.z = function() { this.t();//вынесли this из параметров.но приписали вначале)) } B1 = new B("LALA1"); B2 = new B("LALA2"); B1.z(); B2.z(); я решил добавить A в качестве прототипа прототипа объектов B |
Цитата:
Хотя я уже думал над чем-то подобным. Но я хотел в прототип как-то "вплести" третий (вспомогательный) объект. Но пока не придумаю как... |
я исчерпался
|
no_alex,
Если вы внутри функции 'A.t' откажетесь от той идеи, что значением 'this' должен быть исключительно объект 'A' и станете обращаться к нему по имени, то можно уйти от аргумента в пользу версии с 'apply' или её более упрощённого собрата. Это если вы не хотите кого-то инструктировать про аргумент... C другой стороны, вариант с передачей аргумента вряд ли можно назвать "нагружающим" процесс создания объектов, прототип создаётся один раз, вычисление значения 'this' в момент вызова мгновенное и т.д. Что касается варианта с 'caller', то это не кроссбраузерное решение, к тому же само свойство 'deprecated'... |
Цитата:
Цитата:
Цитата:
В остальных браузерах: - FF2, FF3 и другие браузеры на мозилловском движке (NN, Flock); - IE6, IE7; - Opera 9; - Safari; - Google Chrome; нормально отрабатывает. Я думаю, что если речь идет только об Opere 8 и ниже, то на это можно "забить". Цитата:
|
Цитата:
All traces of a caller property were removed a while ago, to follow ECMA-262 and to avoid any chance of a security exploit. The removal seems to me to have been overzealous, because it axed the caller property of function objects *and* the much-more-exploitable caller (or __caller__) property of activation objects. В общем, в основных движках свойство сидит с прошлого века, но в одном из них временно отстутствовало, выпадая из спеков. Все остальные традиционно бедны последовательной документацией, в Opera точно не было долго (помню был такой вопрос на винграде), в Safari ещё труднее сказать... свойство вне стандарта, редко используемое, может взбрыкнуть. ;) |
Часовой пояс GMT +3, время: 03:34. |