JavaScript 함수에서 call, apply, bind에 대한 자세한 설명 및 수동 구현

배경

이게 뭐야

앞에서 배운 JS 프로토타입 체인에서 js의 모든 함수는 Function의 인스턴스이고 Function의 프로토타입 객체(Function.prototype)에는 call, apply 및 bind 메서드를 포함하여 많은 속성과 메서드가 있음을 알 수 있습니다.

프로토타입의 규칙에 따라 모든 함수는 프로토타입의 속성과 메서드를 사용할 수 있으므로 모든 함수와 함수만 호출, 적용 및 바인딩 메서드를 사용할 수 있습니다.

뭐하세요?

그들의 기능은 한 문장으로 설명될 수 있습니다: 이것의 방향을 바꾸는 것입니다.

call(), apply(), bind()의 차이점

같은:

  • 둘 다 대상 함수가 실행될 때 내부 this 포인터를 변경할 수 있습니다.
  • 메서드의 첫 번째 매개변수는 함수가 실행될 때 this의 내부 값을 지정하는 데 사용됩니다.
  • 대상 함수에 매개 변수를 얼마든지 전달하도록 지원
  • 메서드의 첫 번째 매개 변수에 값이 전달되지 않거나 undefined 및 null이 전달되면 JavaScript 일반 모드에서 대상 함수 내부의 this는 window 개체를 가리키고 엄격 모드에서는 각각 undefined 및 null을 가리킵니다.

다른:

  • apply() 메소드는 두 개의 매개변수를 수신할 수 있는 반면 call() 및 bind() 메소드는 여러 매개변수를 수신할 수 있습니다.
  • apply() 메서드가 대상 함수에 매개변수를 전달할 때 메서드의 두 번째 매개변수로 매개변수 배열 또는 인수 객체만 사용하면 되지만 call() 및 bind() 메서드는 전달된 매개변수를 나열해야 합니다. 메서드의 매개변수를 하나씩 하나씩.
  • call() 및 apply() 메서드가 호출되면 대상 함수가 즉시 실행되지만 bind() 메서드는 그렇지 않고 새 함수(대상 함수의 복사본)를 반환하며 함수 내부의 this는 함수를 가리킵니다. 첫 번째 One 매개변수에 추가한 후 새 기능을 실행하는 것은 대상 기능을 실행하는 것과 동일합니다.
  • bind() 메서드만 함수 커링을 구현하므로 대상 함수에 매개 변수를 두 번 전달할 수 있습니다.

call() 및 수동 모의 구현

call() 메소드

call() 메서드를 호출하면 대상 함수가 즉시 실행되고 동시에 함수 내에서 this의 포인터가 변경됩니다. 이 지점은 메서드의 첫 번째 매개변수에 의해 결정되며, 나중에 하나씩 나열된 모든 매개변수는 대상 함수의 매개변수로 하나씩 전달됩니다.

let obj = {
    
    
  name:"胡歌",
  sum(a, b) {
    
    
    console.log(this.name)
    return a + b
  }
}

let obj1 = {
    
    
  name:"李逍遥"
}
obj.sum.call(obj1, 1, 2)  //  李逍遥 3

/* 正常模式 */
obj.sum.call()  //  window
obj.sum.call(undefined, 1, 2)  //  window
obj.sum.call(null, 1, 2)  //  window
 
/* 严格模式 */
'use strict'
 
obj.sum.call()  //  undefined
obj.sum.call(undefined, 1, 2)  //  undefined
obj.sum.call(null, 1, 2)  //  null

수동 모의 구현

설계 논리:

  • myCall() 메서드는 Function 프로토타입 개체에 추가되며, 대상 함수가 이 메서드를 호출하면 myCall() 메서드 내부의 this가 대상 함수를 가리킵니다.
  • 컨텍스트 개체의 메서드로 대상 함수를 실행하여 대상 함수 내부의 this가 컨텍스트 개체를 가리킬 것입니다.
  • 컨텍스트 개체에서 대상 함수를 제거합니다.
  • 스프레드 연산자...를 사용하여 대상 함수에 전달된 인수를 처리합니다.
Function.prototype.myCall = function (context, ...args) {
    
    
  if (context === undefined || context === null) {
    
    
    context = window
  }
  context.fn = this
  const result = context.fn(...args)
  delete context.fn
  return result
}
 


let obj1 = {
    
    
  num: 1,
  sum(a, b) {
    
    
    console.log(this)
    return this.num + a + b
  }
}
let obj2 = {
    
    
  num: 10
}
console.log(obj1.sum.call(obj2, 2, 3))  // 15
console.log(obj1.sum.myCall(obj2, 2, 3))  // 15

apply() 및 수동 모의 구현

적용() 메서드

apply() 메서드를 호출하면 대상 함수가 즉시 실행되고 동시에 함수 내에서 this의 포인터가 변경됩니다. 이 점은 메서드의 첫 번째 매개변수에 의해 결정되며 두 번째 매개변수는 매개변수 배열 또는 인수 객체이며 각 배열 요소 또는 인수 객체가 나타내는 각 매개변수는 매개변수로 하나씩 전달됩니다. 목표 기능.

obj1.sum.apply(obj2, [2, 3])

수동 모의 구현

설계 논리:

  • myApply() 메소드가 Function 프로토타입 객체에 추가됩니다. 대상 함수가 이 메소드를 호출하면 myApply() 메소드 내부의 this가 대상 함수를 가리킵니다.
  • 컨텍스트 개체의 메서드로 대상 함수를 실행하여 대상 함수 내부의 this가 컨텍스트 개체를 가리킬 것입니다.
  • 컨텍스트 개체에서 대상 함수를 제거합니다.
  • 스프레드 연산자...를 사용하여 대상 함수에 전달된 인수를 처리합니다.
Function.prototype.myApply = function (context, args) {
    
    
  if (context === undefined || context === null) {
    
    
    context = window
  }
  // 下面这行为核心代码
  context.fn = this
  const result = context.fn(...args)
  delete context.fn
  return result
}
 
console.log(obj1.sum.apply(obj2, [2, 3]))  // 15
console.log(obj1.sum.myApply(obj2, [2, 3]))  // 15

bind() 및 수동 모의 구현

바인드() 메서드

bind() 메서드를 호출하면 함수 내에서 this의 포인터도 변경되지만 함수를 호출하는 대신 대상 함수의 복사본인 새 함수를 반환합니다. 함수 내에서 이것은 메서드의 첫 번째 매개 변수를 가리킵니다. 나중에 하나씩 나열될 임의 매개변수는 목적 함수의 매개변수로 하나씩 전달됩니다. 나중에 새 기능을 실행하는 것은 대상 기능을 실행하는 것과 같습니다.

bind() 메서드는 함수 커링을 구현하므로 대상 함수에 매개 변수를 두 번 전달할 수 있습니다. 첫 번째 매개 변수는 bind() 메서드의 첫 번째 매개 변수 뒤에 나열되고 두 번째 매개 변수는 새 함수에 나열됩니다.

obj1.sum.bind(obj2, 2)(3)

수동 모의 구현

설계 논리:

  • myBind() 메서드는 Function 프로토타입 객체에 추가되며 대상 함수가 이 메서드를 호출하면 myBind() 메서드 내부의 this가 대상 함수를 가리킵니다.
  • 컨텍스트 개체의 메서드로 대상 함수를 실행하여 대상 함수 내부의 this가 컨텍스트 개체를 가리킬 것입니다.
  • 컨텍스트 개체에서 대상 함수를 제거합니다.
  • 스프레드 연산자...를 사용하여 대상 함수에 전달된 초기 및 후속 인수를 처리합니다.
Function.prototype.myBind = function (context, ...initArgs) {
    
    
  if (context === undefined || context === null) {
    
    
    context = window
  }
  // 缓存 this 值
  const _this = this
  return function (...args) {
    
    
    // 下面这行为核心代码
    context.fn = _this
    const result = context.fn(...initArgs, ...args)
    delete context.fn
    return result
  }
}
 
console.log(obj1.sum.bind(obj2, 2)(3))  // 15
console.log(obj1.sum.myBind(obj2, 2)(3))  // 15

Supongo que te gusta

Origin blog.csdn.net/qq_44182284/article/details/121765202
Recomendado
Clasificación