De hecho, este es un problema de cliché. Hay muchos artículos sobre esto. En realidad, pensé que lo había descubierto, pero ayer todavía tenía una pequeña duda durante el proyecto. Pensé en un artículo detallado que había recopilado y leído en JavaScript Weekly (había un enlace más tarde, y se adjuntó la traducción al chino en tierras raras) y otro artículo recomendado por un senior, por lo que los miré y mi comprensión de esto ha mejorado un poco.
'Esto' en JavaScript es dinámico y se determina cuando la función se ejecuta, no cuando se declara la función. Todas las funciones pueden llamar 'esto', lo que no importa si la función pertenece a un objeto. Con respecto a esto, hay principalmente cuatro situaciones.
1. El método utilizado como objeto se llama
Si la función es un método que se considera un objeto, entonces esto de la función apunta al objeto;
var John = {FirstName: "John"} function Func () {alert (this.firstname + ": Hola!")} John.sayhi = func John.sayhi () // this = JohnHay algo que vale la pena señalar aquí. Cuando se saca y asigna el método de un objeto a una variable, el método se convierte en un activador de función, y esto apunta a la ventana o bajo defensa (modo estricto).
2. Llame dentro de la función
Cuando esta función tiene esto, en realidad significa que se llama como un método. Llamar entre los dos es equivalente a tratarlo como un objeto de ventana. Esto apunta a la ventana. Vale la pena señalar que ES5 en realidad estipula que esto = Undefinado, y solo los navegadores todavía se ejecutan de acuerdo con el método anterior (lo pruebo en la última versión de Chrome, Safari y Firefox, todos los puntos de ventana (201607)), y uso el modo estricto para apuntar a sinfinado bajo Firefox;
func () función func () {alerta (this) // [ventana de objeto] o [objeto global] o tipo de ..}Para aprobar esto, () debe ser un tipo de referencia antes, similar a OBJ.A u OBJ ['A'], y no puede ser otra cosa.
También hay un pequeño pozo aquí. Cuando hay una función en el método del objeto, la función en realidad se activa como un modo de función, por lo que este valor predeterminado en la ventana (indefinido en modo estricto). La solución es unir esto a la función.
var nomes = {numberA: 5, numberB: 10, suma: function () {console.log (this === Numbers); // => Función verdadera Calculación () {// Esta es una ventana o indefinida en Strict Mode Console.log (this === Numbers); // => falso return this.numberA + this.numberb; } return calculate (); }}; números.sum (); // => nan o lanza typeError en el modo estricto var números = {numberA: 5, numberB: 10, suma: function () {console.log (this === Numbers); // => Función verdadera Calculación () {console.log (this === Numbers); // => Verdadero return this.numberA + this.numberb; } // utilizar el método .call () para modificar el contexto return calculate.call (this); }}; números.sum (); // => 153. Llame a nuevo
Una variable que hace referencia a un objeto realmente guarda una referencia al objeto, es decir, la variable realmente guarda un puntero a los datos reales.
Al usar la nueva palabra clave, este cambio realmente toma los siguientes pasos:
Crear esto = {}.
Esto puede cambiarse durante la ejecución de nuevos, y luego se agregan atributos y métodos;
Devuelve esto cambiado.
function animal (nombre) {this.name = name this.canwalk = true} var animal = new animal ("beastie") alerta (animal.name)Cabe señalar que si el constructor devuelve un objeto, entonces esto apunta al objeto devuelto;
function animal () {this.name = 'mousie'; this.age = '18'; regreso {nombre: 'Godzilla'} // <- se devolverá} var animal = new Animal () console.log (animal.name) // Godzilla console.log (animal.age) // UndefinadoEs importante tener en cuenta aquí que no se olvidan de usar nuevo, de lo contrario no se creará una nueva función. En cambio, solo ejecuta la función, que es equivalente a una llamada de función, y esto realmente apunta a la ventana
Function Vehicle (type, WheelsCount) {this.type = type; this.WheelsCount = WheelsCount; devolver esto;} // función invocationVar car = vehículo ('car', 4); CAR.TYPE; // => 'Car' Car.WheelsCount // => 4 Car === Ventana // => Verdadero4. Llame claramente a esto, use llamadas y aplique
Este es el lugar más inspirado en JavaScript.
El siguiente código:
func.call(obj, arg1, arg2,...)
El primer parámetro se utilizará como objeto de referencia de esto, y el parámetro posterior se utilizará como el parámetro de la función. La solución es usar Bind.
function animal (tipo, piernas) {this.type = type; this.legs = piernas; this.loginfo = function () {console.log (this === mycat); // => verdadero console.log ('The' + this.type + 'ha' + this.legs + 'piernas'); };} var mycat = new Animal ('Cat', 4); // registra "el gato tiene 4 piernas" setTimeOut (mycat.loginfo.bind (mycat), 1000); // settimeout ?? var John = {FirstName: "John", Incidente: "Smith"} function func (a, b) {alert (this [a] + '' + this [b])} func.call (John, 'FirstName', 'Surname') // "John Smith"En cuanto a la aplicación, simplemente pasa en parámetros en el cuadrado de la matriz, y las otras partes son las mismas, como sigue:
FURC.CALL (John, 'FirstName', 'Surname') FunC.Apply (John, ['FirstName', 'Apellido']))
También se pueden usar en la herencia de clase en ES5 para llamar al constructor principal.
function runner (name) {console.log (esta instancia de conejo); // => true this.name = name; } function rabbit (name, countlegs) {console.log (esta instancia de conejo); // => true // indirectamente llamado, el constructor principal runner.call (this, nombre); this.countlegs = countlegs; } var myrabbit = nuevo conejo ('conejo blanco', 4); Myrabbit; // {nombre: 'conejo blanco', countlegs: 4}5..Bind ()
Compare los métodos .Apply () y .call (), los cuales ejecutan la función inmediatamente, mientras que la función .bind () devuelve un nuevo método que une este preespecificado y puede retrasar la llamada.
La función del método .bind () es crear una nueva función. El contexto durante la ejecución es el primer parámetro aprobado por .bind (), que permite la creación de una función que tiene este preajuste.
var números = {matriz: [3, 5, 10], getNumbers: function () {return this.array; }}; // crea una función vinculada a límites boundgetNumbers = números.getNumbers.bind (números); boundgetNumbers (); // => [3, 5, 10] // Extraer método de objectVar simpletnumbers = números.getNumbers; simplegetNumbers (); // => indefinido o lanza un error en modo estrictoAl usar .bind (), debe tener en cuenta que .bind () crea una cadena de contexto eterna y no es modificable. Incluso si una función de enlace usa .call () o .Apply () para pasar a otros contextos diferentes, no cambiará el contexto de su conexión anterior, y la reincidencia no desempeñará ningún papel.
Solo cuando se llama al constructor, la función de unión puede cambiar el contexto, pero este no es un enfoque particularmente recomendado.
6. Función de flecha
La función de flecha no crea el contexto de su propia ejecución, de modo que esto depende de la función externa que se define en el momento de la definición.
Las funciones de flecha no se pueden cambiar después de vincular el contexto una vez, incluso si se usa el método de cambio de contexto:
números var = [1, 2]; (function () {var get = () => {console.log (this === Numbers); // => True return this;}; console.log (this === Numbers); // => true get (); // => [1, 2] // Funciones de flecha Use .Apply () y .call () get.call ([0]); // => [1, 2] Get.Apply (0] // => [1, 2] // bing get.bind ([0]) ();Esto se debe a que la función de flecha tiene un contexto estático y no cambiará debido a diferentes llamadas. Por lo tanto, no use funciones de flecha para definir métodos
Período de función (horas, minutos) {this.hurs = horas; this.mines = minutos; } Período.prototype.format = () => {console.log (this === Window); // => Verdadero return esto. Hours + 'horas y' + this.mines + 'minutos'; }; var walkperiod = nuevo período (2, 30); walkperiod.format (); // => 'horas indefinidas y minutos indefinidos'referirse a
Cuatro aromas de "esto"
Explicación suave de 'esta' palabra clave en JavaScript
Javascript Este misterio (traducción)
Es muy recomendable que los estudiantes que no lo entiendan. Echa un vistazo a los tres artículos anteriores, el tercero es la traducción del segundo. Si tiene alguna pregunta sobre esto, puede discutir juntos, comunicarse y promover el pensamiento y avanzar juntos.