[JavaScript] Cambie este punto de la función: llame a la función, aplique la función, enlace la función

JavaScript nos proporciona algunos métodos de funciones para ayudarnos a lidiar con el problema de señalar esto dentro de la función. Los métodos comúnmente utilizados son bind(), call(), apply()

1. función de llamada

El método call() puede llamar inmediatamente a una función y puede cambiar este punto de la función .

Uso: fun.call(thisArg,arg1,arg2,…)

  • thisArg: el valor especificado cuando se ejecuta la función divertida
  • arg1, arg2, ...: otros argumentos
  • Valor de retorno: es el valor de retorno de la función divertida, porque es la función de llamada

Entonces, cuando queremos cambiar el punto de esto y llamar a esta función al mismo tiempo, podemos usar la llamada, como la herencia .

function Father(uname, age) {
    
    
    this.uname = uname;
    this.age = age;
}

function Son(uname, age) {
    
    
    Father.call(this, uname, age);
}

var son = new Son('xiaoming', 18);
console.log(son.uname); //xiaoming

El constructor Hijo quiere heredar las propiedades del constructor Padre, en el constructor Hijo se llama al constructor Padre, ya la vez se cambia este punto para que apunte al constructor Hijo. Esta vez se utiliza la función de llamada.

El proceso de realizar la herencia: crear un objeto instanciado son de Son, y luego pasar 'xiaoming' y 18 a uname y age en función Son(uname, age) respectivamente, en este momento el parámetro formal uname='xiaoming'; age= 18;Luego existe una función Padre.llamar(esto,uname,edad) en función Hijo(uname,edad), donde uname y edad son parámetros formales, por lo que también tienen valores correspondientes en este momento, y luego el primero El parámetro se cambia a Para esto, this en el constructor Son debe apuntar a su objeto instanciado, que es el hijo aquí. Llame a la función Padre con estos tres parámetros, es decir, al atributo uname de hijo se le asigna el valor 'xiaoming' del parámetro formal uname, y al atributo de hijo se le asigna el valor 18 del parámetro formal edad. Se implementa la herencia.

Dos, aplicar la función

El método apply() puede llamar a una función inmediatamente y puede cambiar este punto de la función .

Cómo usar: fun.apply(thisArg,[argsArray])

  • thisArg: el valor especificado cuando se ejecuta la función divertida
  • [argsArray]: forma de valor pasado, matriz o pseudo-matriz
  • Valor de retorno: es el valor de retorno de la función divertida, porque es la función de llamada

Debido a que el parámetro que pasa es una matriz , podemos usarlo para tratar algunos problemas relacionados con la matriz , como tomar prestado Math.max() para encontrar el valor máximo/mínimo de la matriz.

var arr = [15, 6, 9, 33];
   	var max = Math.max.apply(Math, arr); //max = 33;
   	var min = Math.min.apply(Math, arr); //min = 6;

Math.max es un método (función), y el método de aplicación se usa para él. No hay necesidad de cambiar este punto aquí, por lo que el primer parámetro permite que apunte de nuevo a Math, y el segundo parámetro se puede pasar a la matriz a procesar. De esta forma, puede utilizar el método matemático para procesar la matriz.

El método de aplicación procesará automáticamente la matriz entrante en el tipo de datos correspondiente.

Tres, función de enlace

La función bind no llama a la función directamente , pero puede cambiar el puntero this dentro de la función , que es ampliamente utilizado.

Cómo usar: fun.bind(thisArg,arg1,arg2,…)

  • thisArg: el valor especificado cuando se ejecuta la función divertida
  • arg1, arg2, ...: otros argumentos
  • Valor devuelto: una copia de la función original modificada por este valor especificado y los parámetros de inicialización , es decir, el valor devuelto es una función

Por lo tanto, cuando solo queremos cambiar este punto y no queremos llamar a esta función de inmediato, podemos usar bind, como cambiar este punto del temporizador .

Por ejemplo, existe el requisito de que después de hacer clic en un botón, el botón se desactive y vuelva a la normalidad después de 2 segundos. Aquí, this en el temporizador apunta a la ventana, y queremos que apunte al botón en el que se ha hecho clic actualmente, por lo que debemos modificar este punto, pero no queremos que se llame de inmediato, sino esperar hasta que la condición del temporizador se cumple Así que use la función de vinculación .

Aquí hay un punto muy inteligente, por lo que esto en la función () { this.disabled = false; }.bind(this) ya está fuera del temporizador, por lo que ya no apunta a la ventana, y el entorno fuera del temporizador es el botón el evento de clic significa que esto apunta al btn en el que se hizo clic actualmente y, a través de la función de vinculación, este punto de la función del temporizador se cambia inteligentemente al btn en el que se hizo clic actualmente para realizar la función actual.

<body>
    <button>点击</button>
    <button>点击</button>
    <button>点击</button>
    <script>
        var btns = document.querySelectorAll('button');
        for (var i = 0; i < btns.length; i++) {
      
      
            btns[i].addEventListener('click', function () {
      
      
                this.disabled = true;
                setTimeout(function () {
      
      
                    this.disabled = false;
                }.bind(this), 2000);
            })
        }
    </script>
</body>

Otro ejemplo es el caso de cambio de paginación de la columna de tabulación orientada a objetos [JavaScript] que escribimos antes. En ese momento, para usar el global this, a que se definió fuera de la clase, y esto se guardó primero para uso posterior Genial, siempre debes recordar definir eso. Podemos intentar usar la función bind para optimizarla en lugar de definir una nueva variable que tome la función toggleTab como ejemplo.

Codigo original:

var that;
class Tab {
    
    
    //传入要做Tab栏的元素的id
    constructor(id){
    
    
    that = this;
        //获取元素
        this.main = document.getElementById(id);
        this.ul=this.main.querySelector('.tab_list ul:first-child');
        this.con=this.main.querySelector('.tab_con');
        this.add=this.main.querySelector('.tabAdd');
        this.init();
    }
    //初始化函数
    init(){
    
    
        this.update();
        //绑定事件
        this.add.addEventListener('click',this.addTab);
    }
    //切换功能
    toggleTab(){
    
    
        that.clearStyle();
        this.className='current';
        that.sections[this.dataIndex].className='item';
    }
    //清除样式 排他思想
    clearStyle(){
    
    
        for(var i=0;i<this.lis.length;i++){
    
    
            this.lis[i].className='';
            this.sections[i].className='';
        }
    }
    //更新li和section
    update(){
    
    
        //重新获取lis和sections和guanbiBtns
        this.lis = this.ul.querySelectorAll('li');
        this.sections=this.con.querySelectorAll('section');
        this.guanbiBtns=this.main.querySelectorAll('.tab_list .guanbi-btn');
        this.spans=this.ul.querySelectorAll('li span:first-child');

        //重新绑定事件
        for(var i = 0;i<this.lis.length; i++){
    
    
            this.lis[i].dataIndex=i;
            this.lis[i].addEventListener('click', this.toggleTab);
            this.spans[i].addEventListener('dblclick',this.editTab);
            this.sections[i].addEventListener('dblclick',this.editTab);
            this.guanbiBtns[i].addEventListener('click',this.removeTab);
        }
    }
}

La persona que llama a la función toggleTab es un li, por lo que esto en la función toggleTab apunta al li llamado, y necesitamos usar el lis de todo el elemento tab. Considere cambiar este punto, y esta función no se ejecuta de inmediato, pero clicked El evento se ejecuta, así que use la función bind . Pero también necesita usar su propio this aquí, por lo que no puede cambiar directamente este punto, entonces this.className='current', hay un problema, ¿cómo mantener dos thiss diferentes?

La función bind puede pasar múltiples parámetros, el primer parámetro es este punto, lo mantenemos sin cambios (porque se usará), y el segundo parámetro se pasa en este apuntando a todo el elemento de pestaña . La función toggleTab usa un que se hace cargo del segundo parámetro, de modo que se puede usar para apuntar a todo el elemento de la pestaña.

Otras funciones de agregar y eliminar son similares, solo haga los cambios correspondientes.

Código optimizado:

class Tab {
    
    
    //传入要做Tab栏的元素的id
    constructor(id){
    
    
        //获取元素
        this.main = document.getElementById(id);
        this.ul=this.main.querySelector('.tab_list ul:first-child');
        this.con=this.main.querySelector('.tab_con');
        this.add=this.main.querySelector('.tabAdd');
        this.init();
    }
    //初始化函数
    init(){
    
    
        this.update();
        //绑定事件
        this.add.addEventListener('click',this.addTab.bind(this.add,this));
    }
    //切换功能
    toggleTab(that){
    
    
        that.clearStyle();
        this.className='current';
        that.sections[this.dataIndex].className='item';
    }
    //清除样式 排他思想
    clearStyle(){
    
    
        for(var i=0;i<this.lis.length;i++){
    
    
            this.lis[i].className='';
            this.sections[i].className='';
        }
    }
    //更新li和section
    update(){
    
    
        //重新获取lis和sections和guanbiBtns
        this.lis = this.ul.querySelectorAll('li');
        this.sections=this.con.querySelectorAll('section');
        this.guanbiBtns=this.main.querySelectorAll('.tab_list .guanbi-btn');
        this.spans=this.ul.querySelectorAll('li span:first-child');

        //重新绑定事件
        for(var i = 0;i<this.lis.length; i++){
    
    
            this.lis[i].dataIndex=i;
            //bind函数优化///
            this.lis[i].addEventListener('click', this.toggleTab.bind(this.lis[i],this));
            this.spans[i].addEventListener('dblclick',this.editTab);
            this.sections[i].addEventListener('dblclick',this.editTab);
            this.guanbiBtns[i].addEventListener('click',this.removeTab.bind(this.guanbiBtns[i],this));
        }
    }
}

Cuatro Resumen

Mismo punto:

  • puede cambiar este punto dentro de la función

diferencia:

  • llamar y aplicar llamará a la función inmediatamente, y el valor devuelto es el valor devuelto después de ejecutar la función
  • bind no llamará a la función inmediatamente, el valor devuelto es una función y la copia modificada de la función original
  • Los parámetros pasados ​​por call y bind son el nuevo puntero this y otros parámetros de la función original, y los parámetros pasados ​​por apply son el nuevo puntero this y una matriz

Principales escenarios de aplicación

  • call() a menudo implementa la herencia
  • apply() a menudo se ocupa de problemas relacionados con matrices, como encontrar el valor máximo o mínimo de una matriz con la ayuda de un objeto matemático.
  • bind() no llama a la función, pero aún quiere cambiar este punto, como cambiar este punto dentro del temporizador

Supongo que te gusta

Origin blog.csdn.net/weixin_43790653/article/details/123672205
Recomendado
Clasificación