Aprender os métodos call(), apply() e bind() é importante porque eles permitem que você controle o contexto disso em JavaScript. Em situações onde o comportamento padrão não funciona conforme o esperado, como ao emprestar métodos de um objeto para outro ou manter o contexto correto dentro de retornos de chamada, esses métodos fornecem flexibilidade e controle. Ao dominá-los, você pode escrever funções mais eficientes, reutilizáveis e sensíveis ao contexto, o que é especialmente útil em aplicativos complexos.
antes de passarmos para os métodos call(), apply() e bind(), vamos entender a palavra-chave ‘this’ e seu mecanismo.
Vamos entender quando e a que esta palavra-chave se refere pelos seguintes marcadores aqui:
Em um método de objeto, isso se refere ao objeto. Dentro de um método definido em um objeto, this apontará para o objeto que possui o método.
Em uma função regular, isso se refere ao objeto global. No modo não estrito, se uma função é invocada no contexto global (não como um método de um objeto), isso se refere ao objeto global (janela em navegadores).
Em uma função de modo estrito, isso é indefinido. Se a função não for um método de um objeto e não estiver vinculada a um contexto específico (via call, apply ou bind), isso será indefinido no modo estrito.
Em manipuladores de eventos, refere-se ao elemento que recebeu o evento. Quando um evento é acionado, refere-se ao elemento HTML que invocou o evento.
Neste caso, refere-se ao próprio elemento do botão que recebeu o evento onclick.
Em funções de seta, isso se comporta de maneira diferente. As funções de seta não possuem seu próprio contexto. Em vez disso, isso é herdado lexicalmente do escopo circundante no momento em que a função de seta é criada. Isso significa que this dentro de uma função de seta se referirá ao valor this de sua função ou contexto envolvente.
const person = { name: "Alice", greet: function() { setTimeout(() => { console.log(`Hi, I'm ${this.name}`); }, 1000); } }; person.greet(); // Output: Hi, I'm Alice
Nesse caso, a função de seta dentro de setTimeout herda isso do método greet, que aponta para o objeto person.
O método call() permite "pegar emprestado" uma função ou método de um objeto e usá-lo com outro objeto, passando o outro objeto como o primeiro argumento. O primeiro argumento se torna o valor this dentro da função, e argumentos adicionais seguem depois.
O método call() não cria uma nova função; ele executa a função existente com o contexto e os argumentos fornecidos.
const person = { fullName: function(city, country) { console.log(this.firstName " " this.lastName " is going to " city ", " country "."); } } const person1 = { firstName: "John", lastName: "Doe" } person.fullName.call(person1, "Oslo", "Norway"); // Output: John Doe is going to Oslo, Norway.
Neste exemplo, call() é usado para executar o método fullName de person com os dados de person1 (firstName e lastName), e os argumentos adicionais são "Oslo" e "Noruega".
O método apply() é muito semelhante ao método call(). A principal diferença está em como os argumentos são passados para a função. Com apply(), você passa os argumentos como um array (ou um objeto semelhante a um array), em vez de individualmente.
Assim como call(), o método apply() não cria uma nova função. Ele executa imediatamente a função com o contexto fornecido (este valor) e argumentos.
const person = { fullName: function(city, country) { console.log(this.firstName " " this.lastName " is going to " city ", " country "."); } } const person1 = { firstName: "John", lastName: "Doe" } person.fullName.apply(person1, ["Oslo", "Norway"]); // Output: John Doe is going to Oslo, Norway.
Neste exemplo, apply() é usado para chamar o método fullName do objeto person, mas com o contexto (this) de person1. Os argumentos "Oslo" e "Noruega" são passados como um array.
O método bind() em JavaScript permite definir o contexto (este valor) para uma função ou método, assim como call() e apply(). No entanto, ao contrário de call() e apply(), o método bind() não invoca a função imediatamente. Em vez disso, ele retorna uma nova função com o valor this definido para o objeto que você especificar.
const person = { fullName: function(city, country) { console.log(this.firstName " " this.lastName " is going to " city ", " country "."); } } const person1 = { firstName: "John", lastName: "Doe" } const func = person.fullName.bind(person1); func("Oslo", "Norway"); // Output: John Doe is going to Oslo, Norway.
Neste exemplo, bind() cria uma nova função func com o valor this definido como person1. A função não é chamada imediatamente, mas você pode invocá-la mais tarde, passando os argumentos "Oslo" e "Noruega".
Aqui está um exemplo de aplicação pequeno, mas complexo, onde usar call(), apply() ou bind() traz eficiência, especialmente no tratamento de aplicações parciais de funções para fins de registro:
Digamos que você tenha uma função de registro centralizada que registra informações sobre diferentes usuários executando ações. Usar bind() permite definir este contexto para diferentes usuários de forma eficiente, evitando código repetitivo.
const logger = { logAction: function(action) { console.log(`${this.name} (ID: ${this.id}) performed: ${action}`); } }; const user1 = { name: "Alice", id: 101 }; const user2 = { name: "Bob", id: 202 }; // Create new logger functions for different users const logForUser1 = logger.logAction.bind(user1); const logForUser2 = logger.logAction.bind(user2); // Perform actions without manually passing user context logForUser1("login"); // Output: Alice (ID: 101) performed: login logForUser2("purchase"); // Output: Bob (ID: 202) performed: purchase
Reutilização de contexto: Você não precisa passar manualmente o contexto do usuário sempre que registrar uma ação. O contexto (this) é vinculado uma vez e o log se torna reutilizável e limpo.
Modularidade: Se precisar adicionar mais usuários ou ações, você pode vinculá-los rapidamente ao logger sem alterar a função em si, mantendo seu código DRY (Don’t Repeat Yourself).
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3