2012-08-23 23 views
9

Estoy intentando comprender por qué una función interna puede acceder a una propiedad pública de una función externa cuando se llama directamente a la función externa, pero no cuando se asigna a una función ¿variable?Diferencia de Javascript entre llamar a una función y crear una instancia de una función

Ejemplo:

function outer(x,y){ 

    this.x = x; 
    this.y = y; 

    function inner(){ 
     alert(this.x);  
    } 

    inner(); 
} 

outer(1,2); //As expected, alerts 1 
var func = outer(1,2) //Also alert 1 
var func2 = new outer(1,2); //Alerts undefined 

Una cosa que probé era eliminar la palabra clave this de alert(this.x); y lo hizo el trabajo para los tres casos. Sin embargo, si eliminé la palabra clave this, estaría accediendo a la contraseña aprobada en param, no a la variable pública, que definitivamente no es la acción deseada. ¿Alguien puede explicar este comportamiento?

+0

uso Ony 'this' en el interior del cuerpo de la función, si la intención de lo invocan a través de' new', o como un método, o por medio de uno de los '.call()'/'.apply()' /'.bind() 'métodos. Una función que se invoca regularmente a través de 'funcName()' no debería usar 'this'. –

+1

Además, si el programa JavaScript se ejecuta en modo estricto, y una función se invoca a través de 'funcName()', entonces 'this' será' undefined'. Como resultado, el acceso a la propiedad (por ejemplo, 'this.x') arroja un error de referencia. –

Respuesta

12

Cuando se llama a outer(1, 2) así, this es una referencia a window, por lo que "x" e "y" son las variables globales con eficacia. Es por eso que inner() puede acceder a "x".

Cuando llama al new outer(1, 2) ha causado que this (en "exterior") sea una referencia a un nuevo objeto. Cuando se llama "interior" dentro de "exterior", this seguirá haciendo referencia a window, por lo que no hay "x".

El valor de this se determina para cada llamada de función, y el valor depende únicamente de los detalles de esa llamada. Por lo tanto, el hecho de que llame "externo" a través del new no tiene ningún efecto en la llamada interna a "interior" — porque simplemente llama a la función como inner();, el valor de this dentro de esa función será una referencia a window (bueno, el contexto, sea lo que sea).

Estas son las formas this se pueden establecer en una llamada a una función:

  1. Si la función se llama a través del operador new, entonces this hará referencia a un objeto recién creado.
  2. Si la referencia a la función se obtiene a través de una búsqueda de propiedades en un objeto (foo.someFunction()), entonces this será una referencia a ese objeto.
  3. Si la función se llama a través de .call() o .apply() del prototipo de función, entonces this se referirá al primer argumento a cualquiera de esas funciones se utilizó, forzada a un valor de objeto si es necesario.
  4. Si la función se llama a través de una simple referencia "desnuda", entonces this se referirá al contexto global (window en un navegador). edit — Šime Vidas señala en un comentario anterior que en modo estricto, este caso da como resultado this siendo null (lo que realmente tiene un poco más de sentido, y evitaría la rareza observada en el OP).
+1

¿Por qué 'this' dentro de la función interna apunta a la ventana? – Asciiom

+0

@JeroenMoons porque la llamada al interior está hecha de tal manera que no hay nada más que pueda ser. – Pointy

+0

Ok, ¿así que 'esto' se comporta de manera diferente que cualquier otra variable? Quiero decir, si defines una var dentro de la función externa (pero fuera de la función interna;)), y la utilizas dentro de la función interna, funcionaría, ¿correcto? – Asciiom

5

Hay 4 maneras de utilizar una función en Javascript lo que cada uno de estos se es cambiar lo que el contenido de this es:

  • función llama: este = objeto global (ventana en el navegador)
  • llamadas a métodos: this = object desde el que se llama.
  • llamadas al constructor: this = new object you are creating.
  • llamadas de llamada/solicitud: this = object you passed.

En su caso this == window cuando se llama a la función directamente (outer()), pero si se llama usando nueva (new outer()), entonces será el nuevo objeto que está creando.

básicamente lo que escribí here

+0

Ja, ja, me robaron descaradamente su explicación de "lista de escenarios" de esa otra respuesta :-) – Pointy

+0

Mientras la gente aprenda de ellos, no me importa ;-) –

Cuestiones relacionadas