Implementación de enlace de llamada de aplicación manuscrita

aplicar enlace de llamada relacionado

Para aplicar enlace de llamada, también escribí un artículo de nivel de entrada muy detallado antes de aplicar, llamar, enlazar el uso y las diferencias

Después de comprender el uso, es mejor comprender su principio de implementación para que pueda comprenderlo a fondo

La diferencia entre los tres

  1. callY applyestán hechos para abordar thispuntos cambiantes . El efecto es el mismo, pero la forma de pasar los parámetros es diferente
  2. Además del primer parámetro, callpuede recibir una lista de parámetros y applysolo aceptar una matriz de parámetros
  3. bindEl efecto es el mismo que los otros dos métodos, excepto que el método devuelve una función. No se ejecutará de inmediato

Llamada escrita a mano

  • Manejar las necesidades:

    • Cambie este punto. Apuntar a la ventana por defecto
    • Puede recibir múltiples parámetros
    • Ejecute el método después de cambiar esta solicitud
    • Todos los métodos montan esto myCall
  • Analizar las ideas de realización:

    • Para this. Solo recuerde, quien llame a este método, esto apuntará a (excepto para las funciones de flecha), y dejará que el objeto / ventana pase para llamar al método.
    • Reciba múltiples parámetros: argumentso nueva sintaxis es6:...args
    • Ejecute la función inmediatamente, rocíe agua
    • Se montan todos los métodos, luego se usa la cadena del prototipo, se monta en el Functionobjeto
  • Todo está listo, comienza a lograr:

Function.prototype.myCall = function(context, ...args) {
    
    
  // 默认的window对象
  context = context && typeof context === 'object' ? context : window
  // 防止覆盖掉原有属性
  const key = Symbol()
  // 这里的this为需要执行的方法
  context[key] = this
  // 方法执行
  const result = context[key](...args)
  delete context[key]
  return result
}
  • Resumir la implementación
    • Primero, asegúrese de que el nuevo puntero sea un tipo de objeto object. De lo contrario, todas son ventanas por defecto. Por supuesto, typeof null también es igual a "object". Entonces tenemos que usar un juicio para asegurarnos de que el contexto existe
    • SymbolRol: prevenir el conflicto de nombres de atributos. ¿Por qué quieres hacer esto? Debido a que necesitamos poner una propiedad en el nuevo objeto, esta propiedad es la antigua this. Pero, ¿cómo garantizar que las nuevas propiedades y no contextlos atributos originales entren en conflicto? Entonces usaSymbol
    • Podría estar por encima de toda context[key] = thisduda. Es por eso que, al final, ¿por qué debería la nueva contextversión de este viejo objeto? Habrá principios de explicación del código más adelante
    • No hay problema con el método de ejecución ~
    • Finalmente delete, nuestra nueva propiedad, después de todo, no puede afectar el contextobjetivo original.

¿Cuál es el contexto de expansión pequeña [clave] = esto?

La comprensión context[key] = thistiene un significado muy importante para toda la implementación del código escrito a mano.

En primer lugar, el principio que se ha mantenido inalterado durante miles de años: quien llama a un método, este señala a quién.
Entonces, ¿por qué no contextllamar al método correspondiente?
Porque contextbásicamente no existe un método correspondiente

Utilice un pequeño ejemplo para comprender el problema.

let data = {
    
    
  key: 1,
  name: 'Jioho',
  say: function() {
    
    
    console.log(this.name)
  }
}
function fn() {
    
    
  console.log(this.name)
}

data.say() // Jioho
fn() // 打印为空

// 那如果这样:
data.sayfn = fn
data.sayfn() // Jioho
  • Gap apareció, siempre que el método correspondiente en el que un objeto, el método pueda obtener la thisinstancia actual
  • context[key] = thisLo mismo es verdad. Esta vez thises la función original this. Esto en la función original tiene su propio método. Así que asignamos directamente todo esto a context. Al igual que la línea 16 del código anterior
  • Como comenzamos keypor qué Symbol. Es solo que tenemos miedo de tener el mismo nombre si no se llama a nuestro 16º nuevo atributo sayfn. Llamado say, nuestras operaciones posteriores afectarán las propiedades del objeto original ¡Este es un problema que no debe surgir!

Aplicar escritura a mano

Si la escritura a mano llama después de entender, aplique solo una pregunta, pase Senado

No es necesario cambiar el resto del código, solo debe ser un tipo de matriz al recibir el segundo parámetro

Function.prototype.myApply = function(context, args = []) {
    
    
  // 默认的window对象
  context = context && typeof context === 'object' ? context : window
  // 防止覆盖掉原有属性
  const key = Symbol()
  // 这里的this为需要执行的方法
  context[key] = this
  // 方法执行
  const result = context[key](...args)
  delete context[key]
  return result
}

Enlace de escritura a mano

  • Manejar las necesidades:

    • Cambie este punto. Apuntar a la ventana por defecto
    • Parámetros antes de llamar a bind, puede pasar múltiples
    • En la función devuelta, puede continuar pasando parámetros. Esta escena sigue siendo muy práctica.
    • Todos los métodos montan esto myBind
  • Analizar las ideas de realización:

    • No es necesario cambiar este punto para decir, si está escrito a mano, usar el original applyo calllo hará.
    • Puede pasar varios parámetros antes de llamar a bind, todavía se usa argumentso se ...argsrecibe unificado
    • bind necesita devolver uno 函数. Y puede continuar pasando parámetros en la nueva función, luego debe usar cierres
    • Se montan todos los métodos, luego se usa la cadena del prototipo, se monta en el Functionobjeto
Function.prototype.myBind = function(context, ...args) {
    
    
  context = context && typeof context === 'object' ? context : window
  const _self = this
  return function(...args2) {
    
    
    return _self.apply(context, [...args, ...args2])
  }
}

// 接下来验证一下:
var data = {
    
     baseCount: 10 }
function add(num1, num2) {
    
    
  return this.baseCount + num1 + num2
}

// 调用方法
var addBind = add.myBind(data, 1)
addBind(2) // 13

// 或者这样写
add.myBind(data, 1)(2) // 13
  • Resumir la implementación
    • Los mismos años contextpara lograr
    • Debido a que hay formas de recibir una pluralidad de parámetros dos veces, solíamos ...argsrecibir también debe haber una matriz de. Por lo tanto, es más apropiado usar aplicar en la función devuelta.

No subestimes la forma aparentemente extraña de escribir bind. ¿Por qué tienes que pasar el parámetro dos veces? Cuando hablemos de currying complejo más adelante, descubriremos el encanto de bind now.

La publicación original se publicó en: aplicar la nueva dirección de blog relacionada con la vinculación de llamadas , puede verificarla si está interesado

Supongo que te gusta

Origin blog.csdn.net/Jioho_chen/article/details/107011523
Recomendado
Clasificación