tipos - llamar funcion javascript desde otro javascript
¿Cómo saber desde dónde se llama una función en JavaScript? (6)
Dependiendo de su navegador, podría provocar un error, accediendo a una variable no definida, por ejemplo, dentro de un try/catch
. Luego examine la traza de pila que algunos navegadores proporcionan en el error.
Esto será muy específico del navegador.
¿Es posible averiguar desde dónde se llama una función? En caso afirmativo, ¿cómo detectar, si se llama a una función desde un ámbito global , desde otra función o quizás desde una consola del navegador ?
Echa un vistazo al siguiente ejemplo:
<script>
function myFunc1() {
// some code
myFunc2(); // I was called from myFunc1()
}
function myFunc2() {
var callerName = new String;
callerName = arguments.callee.caller.name;
// some code
alert(''I was called from '' + callerName + '' function'');
}
myFunc2(); // I was called from global scope
</script>
Sé que esta línea callerName = arguments.callee.caller.name;
en el ejemplo anterior, me daría el nombre de la función del llamante. Pero no sé cómo detectar si una función fue llamada desde un ámbito global. Por ejemplo, si cambio myFunc2()
y agrego una sentencia if else
para verificar si arguments.callee.caller.name
devuelve un valor undefined
, sabiendo que esto sucederá cuando se llame a una función desde un ámbito global:
myFunc2() {
var callerName = new String;
callerName = arguments.callee.caller.name;
if(callerName == undefined) {
alert(''I was called from global scope'');
} else {
alert(''I was called from '' + callerName + '' function'');
}
}
Sin embargo, esto no funcionará si se llama a myFunc2()
desde un ámbito global y callerName = arguments.callee.caller.name;
provocará que JavaScript lance el siguiente error:
TypeError: ''null'' is not an object (evaluating ''arguments.callee.caller.name'')
Así que estoy de vuelta al punto uno, y la pregunta sigue siendo:
- ¿Cómo detectar si una función se llama desde un ámbito global?
- Si se llama desde un ámbito global, ¿es desde una consola del navegador?
En Chrome, puedes usar:
console.trace();
Solo agrega esa línea en tu función, normalmente la coloco como la primera línea. Si ves la consola, verás el nombre de tu función, y debajo de esa línea verás desde dónde se llama.
En JavaScript, la mayoría de las cosas son objetos, cuando declara callerName = new String
crea un objeto de cadena con algunas propiedades y métodos. Por ejemplo, el método valueOf()
devolverá el valor primitivo de un objeto de cadena. Sin embargo, al igual que JavaScript le dice que ''TypeError: ''null'' is not an object
null no es un objeto sino que es la ausencia de un objeto. null no tiene ningún método o propiedad. Cuando se llama a una función desde un ámbito global, los arguments.callee.caller
evalúan al llamante a nulo. Así que arguments.callee.caller.name
es como intentar acceder a la propiedad de name
null ( null.name
) , pero null no tiene una propiedad llamada name
, ya que no es un objeto y no puede tener ninguna propiedad. Es por eso que JavaScript se queja, porque estás intentando acceder a algo que no existe. Sin embargo, lo que puede hacer es verificar primero si la caller
que caller
es un valor falso utilizando una instrucción simple if else
if(!arguments.callee.caller)
, si no lo es, entonces puede acceder a la propiedad de name
de quien caller
y myFunc2()
qué función ha llamado myFunc2()
, pero si es así , entonces sabe que se llamó a la función desde un ámbito global.
function myFunc2() {
if(!arguments.callee.caller) {
callerName = "global";
alert(''I was called from global scope'');
} else {
callerName = arguments.callee.caller.name;
alert(''I was called from '' + callerName + '' function'');
}
}
Esa es una pregunta bastante difícil. Como se discutió en esta respuesta, Arguments.callee está en desuso en algunos navegadores.
Dependiendo de su enfoque, puede utilizar Function.caller. He escrito un ejemplo bastante simple.
function A() {
if (A.caller === null || A.caller.name == "") console.log("Function called from top window")
else console.log("Called from " + A.caller.name);
B();
}
function B() {
if (B.caller === null || B.caller.name == "") console.log("Function called from top window")
else console.log("Called from " + B.caller.name);
}
A();
Otro ejemplo más genérico se puede encontrar here
Sin embargo, el ''use strict''
hace que ambos enfoques fracasen, por lo que el uso de un bloque try / catch
puede resolver su problema o puede simular una " pila de llamadas ficticias " para sus funciones (dependiendo del hecho de que todo su código funciona de manera sincrónica)
Si se llama a la función desde el ámbito global, los arguments.callee.caller.name
no estarán definidos. De lo contrario, será el nombre de la función de la persona que llama (que también representa el alcance desde el que se llamó).
Por lo tanto, lo que ya tiene debería funcionar, excepto en modo estricto , donde los arguments.callee
no están disponibles.
Además: las herramientas de desarrollador disponibles desde su navegador son probablemente una mejor manera de inspeccionar este tipo de cosas: simplemente establezca un punto de interrupción y observe el panel de seguimiento de la pila. A menos que, por supuesto, su propio código necesite conocer el alcance de la llamada en el tiempo de ejecución.
function func1() {
// some code
func2(); // I was called from func1()
}
function func2() {
var callerName = new String;
callerName = arguments.callee.caller ? arguments.callee.caller.name : "global";
if(callerName == "global") {
alert(''I was called from global scope'');
} else {
alert(''I was called from '' + callerName + '' function'');
}
}
func1();
func2(); // I was called from global scope
Se llama a func2 que mostrará su nombre de la persona que llama, si fue llamado dentro de otro ámbito de función, mostrará el nombre de esa función y si fue llamado desde el alcance global, mostrará un mensaje que muestra que fue llamado desde el alcance global.