globales - tipos de funciones en javascript
FunciĆ³n de Javascript-AsignaciĆ³n de puntero (11)
Para cada FunctionDeclaration f en el código, en el orden de los textos fuente, haga lo siguiente:
Deje fn ser el identificador en FunctionDeclaration f.
Deje que sea el resultado de instanciar FunctionDeclaration f como se describe en la cláusula 13.
Deja que funcAlreadyDeclared sea el resultado de llamar al método concreto HasBinding de env pasando fn como argumento.
Si funcAlreadyDeclared es falso, llame al método concreto CreateMutableBinding de env pasando fn y ConfigurableBinding como argumentos.
Referencias
Considere este código javascript:
var bar = function () { alert("A"); }
var foo = bar;
bar = function () { alert("B"); };
foo();
Al ejecutar este código, obtengo "A". ¿Este comportamiento es parte de la especificación de JavaScript y puedo confiar en él?
En otros ejemplos, nada fue pasado por valor; todo fue pasado por referencia.
bar y foo son AMBOS indicadores
Todos los vars / manejadores de objetos NO primitivos en javascript son punteros; los punteros SON nativos de javascript, son los predeterminados.
var bar = function () { alert("A"); } //bar is a pointer to function1
var foo = bar; //pointer copied; foo is now also a pointer to function1
bar = function () { alert("B"); }; //bar points to function2
foo(); //foo is still a pointer to function1
Te encontrarás con errores ocultos e insectos si crees que son copias. Especialmente si trabajas con objetos complejos. Por ejemplo
function person(name){this.name = name}
var john = new person("john")
var backup = john
backup.name //john
john.name = "jack"
backup.name //jack, NOT john
Para COPIAR realmente una no primitiva en javascript se necesita más trabajo que simplemente a = b. Por ejemplo:
function person(name){ this.name = name}
var john = new person("john")
var backup = new Object()
backup = JSON.parse(JSON.stringify(john))
backup.__proto__ = john.__proto__ //useful in some cases
john.name = "jack"
backup.name //john
Esos no son indicadores de función (y no hay punteros en JS de forma nativa). Las funciones en JS pueden ser anónimas y son objetos de primera clase. Por lo tanto
function () { alert("A"); }
crea una función anónima que alerta a "A" en la ejecución;
var bar = function () { alert("A"); };
asignar esa función a la barra;
var foo = bar;
asigna foo a la barra, que es la función "A".
bar = function () { alert("B"); };
volver a vincular la barra a una función anónima "B". Esto no afectará a foo ni a la otra función "A".
foo();
Llame a la función almacenada en foo, que es la función "A".
En realidad, en idiomas donde hay puntos de función, por ejemplo, C, tampoco afectará a foo
. No sé de dónde sacas la idea de obtener una "B" en la reasignación.
void A(void) { printf("A/n"); }
void B(void) { printf("B/n"); }
typedef void(*fptr_t)(void);
fptr_t foo = A;
fptr_t bar = foo;
bar = B;
foo(); // should print "A"
Está asignando el valor de una función anónima a una variable, no a un puntero.
Si desea jugar con punteros, puede usar objetos que se pasan por referencia, no por copia.
Aquí hay unos ejemplos:
"obj2" es una referencia de "obj1", cambia "obj2" y "obj1" cambia. Alertará false
.
var obj1 = {prop:true},
obj2 = obj1;
obj2.prop = false;
alert(obj1.prop);
"prop" apunta a una propiedad que no es un objeto, "prop" no es un puntero a este objeto sino una copia. Si cambia "prop", "obj1" no cambia. Alertará true
var obj1 = {prop:true},
prop = obj1.prop;
prop = false;
alert(obj1.prop);
"obj2" es una referencia a la propiedad "subObj" de "obj1". si se cambia "obj2", se cambia "obj1". Alertará false
.
var obj1 = {subObj:{prop:true}},
obj2 = obj1.subObj;
obj2.prop = false;
alert(obj1.subObj.prop);
Esto asigna una variable a una función sin nombre, no un puntero a una función
Llegué un poco tarde, pero pensé dar una respuesta de todos modos y dar forma a algo.
Lo mejor es no pensar en términos de punteros y referencias de memoria cuando se discuten los aspectos internos de JavaScript (o ECMAScript) cuando se trata de las especificaciones. Las variables son registros de entorno internos y se almacenan y referencian por nombre, no por dirección de memoria. Lo que está haciendo su declaración de asignación, internamente y por diseño, es buscar el nombre del registro del entorno (ya sea "foo" o "bar") y asignar el valor a ese registro.
Asi que,
var bar = function () { alert("A"); }
está asignando al registro de entorno "barra" el valor (función anónima).
var foo = bar;
internamente llama a GetValue ("barra") que recupera el valor asociado con la "barra" de registro y luego asocia ese valor con el registro "foo". Por lo tanto, después, el valor original de la barra todavía se puede usar, ya que ahora está asociado con foo.
Debido a que las referencias de JavaScript por cadena y no por la dirección de memoria es precisamente la razón por la que puede hacer cosas como esta:
someObject["someProperty"]
que está buscando el valor basado en el nombre de la propiedad.
Me gustaría añadir que esto también funciona para funciones con nombres predefinidos:
function myfunc() { alert("A"); }
var bar = myfunc;
var foo = bar;
bar = function () { alert("B"); };
foo();
Esto hará lo mismo, lo que indica que los nombres de funciones actúan como nombres de matriz (punteros).
Sí, eso es lo que se espera y por diseño.
Su pregunta es básicamente: ¿la bar
referencia foo
como puntero o referencia lo haría en otro idioma?
La respuesta es no: el valor de la bar
en el momento de la asignación se asigna a foo
.
Sí, este es el comportamiento correcto.
//create variable bar and assign a function to it
var bar = function () { alert("A"); }
//assign value of bar to the newly created variable foo
var foo = bar;
//assign a new function to the variable bar
//since foo and bar are not pointers, value of foo doesn''t change
bar = function () { alert("B"); };
//call the function stored in foo
foo();
Sí, has creado un puntero a la función original "A". Cuando reasigna la barra, la está reasignando , pero todavía está dejando solo referencias a la función anterior.
Entonces, para responder a su pregunta, sí, puede confiar en eso.
Sí, no hay nada de especial en el hecho de que las variables se refieren a funciones, no hay aliasing involucrado.
var bar = 1;
var foo = bar;
bar = "something entirely different";
// foo is still 1