De fato, essa é uma questão clichê. Existem muitos artigos sobre isso. Na verdade, eu pensei que tinha descoberto, mas ontem ainda tinha uma pequena dúvida durante o projeto. Pensei em um artigo detalhado que eu colecionei e li no JavaScript Weekly (houve um link mais tarde, e a tradução chinesa em terras raras foi anexada) e outro artigo recomendado por um veterano, então olhei para eles e meu entendimento disso realmente melhorou um pouco.
'Este' em JavaScript é dinâmico e é determinado quando a função é executada, não quando a função é declarada. Todas as funções podem chamar 'isto', o que não importa se a função pertence a um objeto. Em relação a isso, existem principalmente quatro situações.
1. O método usado como objeto é chamado
Se a função é um método considerado um objeto, essa da função aponta para o objeto;
var john = {FirstName: "John"} função func () {alert (this.firstname + ": oi!")} John.sayhi = func John.sayhi () // this = JohnHá algo que vale a pena notar aqui. Quando o método de um objeto é retirado e atribuído a uma variável, o método se torna um gatilho de função, e isso aponta para a janela ou para encontrar (modo rigoroso).
2. Ligue para dentro da função
Quando essa função tem isso, na verdade significa que é chamado de método. A chamada entre os dois é equivalente a tratá -lo como um objeto de janela. Isso aponta para a janela. Vale ressaltar que o ES5 realmente estipula que isso = indefinido, e apenas os navegadores ainda são executados de acordo com o método antigo (eu o testo na versão mais recente de Chrome, Safari e Firefox All Point to Window (201607)) e uso o modo rigoroso para apontar para o Firefox;
func () function func () {alert (this) // [janela do objeto] ou [objeto global] ou tipo de ..}Para passar por isso, () deve ser um tipo de referência antes, semelhante a obj.a ou obj ['a'] e não pode ser mais nada.
Há também um pequeno poço aqui. Quando há uma função no método do objeto, a função é realmente acionada como um modo de função, portanto, isso é padrão na janela (indefinido no modo rigoroso). A solução é ligar isso à função.
var números = {número: 5, númerob: 10, soma: function () {console.log (this === Numbers); // => função true calcular () {// Esta é a janela ou indefinida no modo rigoroso console.log (this === números); // => False Return this.NumberA + this.numberb; } return calcule (); }}; números.sum (); // => nan ou lança o TypeError no modo rigoroso var números = {número: 5, númerob: 10, soma: function () {console.log (this === números); // => função true calcule () {console.log (this === Numbers); // => True Return this.NumberA + this.numberb; } // use o método .Call () para modificar o retorno do contexto calcular.Call (this); }}; números.sum (); // => 153. Ligue para o novo
Uma variável que faz referência a um objeto realmente salva uma referência ao objeto, ou seja, a variável realmente salva um ponteiro para os dados reais.
Ao usar a nova palavra -chave, essa alteração realmente toma as seguintes etapas:
Crie isso = {}.
Isso pode ser alterado durante a execução de novos e, em seguida, atributos e métodos são adicionados;
Retorna isso mudou.
função animal (nome) {this.name = nome this.canwalk = true} var animal = new animal ("beastie") alerta (animal.name)Deve -se notar que, se o construtor retornar um objeto, isso aponta para o objeto retornado;
function animal () {this.name = 'Mousie'; this.age = '18'; retornar {nome: 'Godzilla'} // <- será devolvido} var animal = new animal () console.log (animal.name) // godzilla console.log (animal.age) // indefinidoÉ importante observar aqui que não se esqueça de usar novas; caso contrário, uma nova função não será criada. Em vez disso, ele apenas executa a função, que é equivalente a uma chamada de função, e isso realmente aponta para a janela
VEÍCULO DE FUNÇÃO (TIPO, WHEELSCOUNT) {this.type = type; this.wheelsCount = wheelscount; Retornar este;} // função InvocationVar Car = veículo ('carro', 4); car.type; // => 'carro' car.wheelscount // => 4 car === janela // => true4. Ligue para isso claramente, use a chamada e aplique
Este é o local mais inspirado em JavaScript.
O seguinte código:
func.call(obj, arg1, arg2,...)
O primeiro parâmetro será usado como objeto de referência disso, e o parâmetro subsequente será usado como parâmetro da função. A solução é usar o Bind.
função animal (tipo, pernas) {this.type = type; this.legs = pernas; this.loginfo = function () {console.log (this === Mycat); // => true console.log ('o' + this.type + 'tem' + this.legs + 'pernas'); };} var mycat = new animal ('gato', 4); // Logs "The Cat tem 4 pernas" setTimeout (mycat.loginfo.bind (mycat), 1000); // setTimeout ?? var John = {primeiro nome: "John", incidente: "smith"} function func (a, b) {alert (this [a] + '' + this [b])} func.call (John, 'primeironame', 'sobrenome') // "John Smith"Quanto à aplicação, ele apenas passa em parâmetros no quadrado da matriz, e as outras partes são as mesmas, o que se segue:
Func.Call (John, 'FirstName', 'Sobrenome') Func.Apply (John, ['FirstName', 'Sobrenome']))
Eles também podem ser usados na herança de classe no ES5 para chamar o construtor pai.
function corredor (nome) {console.log (esta instância de coelho); // => true this.name = nome; } function rabbit (name, Countlegs) {console.log (esta instância de coelho); // => true // indiretamente chamado, o pai do construtor pai Runner.call (este, nome); this.countlegs = Countlegs; } var myrabbit = new Rabbit ('White Rabbit', 4); mirabbit; // {Nome: 'White Rabbit', Countlegs: 4}5..Bind ()
Compare os métodos .Apply () e .Call (), os quais executam a função imediatamente, enquanto a função .bind () retorna um novo método que vincula esse pré-especificado e pode atrasar a chamada.
A função do método .bind () é criar uma nova função. O contexto durante a execução é o primeiro parâmetro aprovado pelo .bind (), que permite a criação de uma função que possui essa predefinição.
var números = {array: [3, 5, 10], getNumbers: function () {return this.array; }}; // Crie um functionVar limite limitado = números.getNumbers.bind (números); limite de limites (); // => [3, 5, 10] // Extrair o método do objectVar SimplegetNumbers = Numbers.getNumbers; SimplegetNumbers (); // => indefinido ou lança um erro no modo rigorosoAo usar .bind (), você deve observar que .bind () cria uma cadeia de contexto eterna e não é modificável. Mesmo que uma função de ligação use .call () ou .Apply () para passar para outros contextos diferentes, ela não mudará o contexto de sua conexão anterior e a reembolso não desempenhará nenhum papel.
Somente quando o construtor é chamado, a função de ligação pode alterar o contexto, mas essa não é uma abordagem particularmente recomendada.
6. Função de seta
A função de seta não cria o contexto de sua própria execução, de modo que isso depende da função externa que ela é definida no momento da definição.
As funções de seta não podem ser alteradas após vincular o contexto uma vez, mesmo que o método de mudança de contexto seja usado:
Var números = [1, 2]; (function () {var get = () => {console.log (this === Numbers); // => Retornar true this;}; console.log (this === Numbers); // => true get (); // => [1, 2] // seta funções use .pply () e .call () () [1, 2, 2] / //s Arrow Funções. // => [1, 2] // bind get.bind ([0]) ();Isso ocorre porque a função de seta tem um contexto estático e não muda devido a chamadas diferentes. Portanto, não use funções de seta para definir métodos
Período da função (horas, minutos) {this.hours = horas; this.minutes = minutos; } Period.prototype.format = () => {console.log (this === Window); // => True Return this.hours + 'horas e' + this.minutes + 'minutos'; }; var walkperiod = novo período (2, 30); walkperiod.format (); // => 'Horas indefinidas e minutos indefinidos'consulte
Quatro aromas de "this"
Explicação suave sobre a palavra -chave 'essa' em JavaScript
JavaScript Este mistério (tradução)
É altamente recomendável que os alunos que não entendam. Confira os três artigos acima, o terceiro é a tradução do segundo. Se você tiver alguma dúvida sobre isso, poderá discutir juntos, comunicar e promover o pensamento e progredir juntos.