전단 면접에서 손으로 bind를 쓰는 방법

5799 단어 면접 시험
bind 함수는react를 쓰는 사람에게 낯설지 않습니다.읊다, 읊조리다네, 맞아요. 제 친구의 한 가지 용도는 함수this가 가리키는 방향을 바꾸는 거예요.만약bind의 실현을 자세히 연구해 보면, 안에 아직도 많은 것들이 있다는 것을 발견할 수 있으니, 우리는 오늘 토론을 전개해 봅시다.
bind를 말하기 전에, 우리는 먼저 우리의 오랜 지인인 **this를 이야기해야 한다.오늘 네 가지 귀속 규칙을 다시 한 번 보도록 하겠습니다.

This의 네 가지 바인딩 규칙


1. 기본 바인딩
독립 함수 호출 시 this 전역 대상을 가리키며, 엄격한 모드를 사용하면 전역 대상은 기본 귀속을 사용할 수 없습니다. this 귀속undefined 그리고 오류 (TypeError: this is undefined)
2. 암시적 바인딩
함수를 인용 속성으로 대상에 추가하면, 스텔스 귀속 규칙은 함수 호출 중인 this 을 이 상하문 대상에 귀속시킨다
3. 바인딩 표시
apply call 방법을 활용하여 함수를 호출할 때this, 즉 호출된 함수의this값을 귀속시킨다
4.new 바인딩
바로 new 조작부호를 사용할 때의this 귀속입니다
상술한 네 가지 규칙의 우선순위는 위에서 아래로 차례로 증가한다.
js의 다양한 귀속 규칙 때문에 귀속 스텔스 분실 문제를 가져왔다. 즉 함수 중의 this 귀속 대상을 분실하는 것이다. 즉, 제1조의 기본 귀속 규칙을 적용하여 this를 전역 대상이나 undefined에 귀속시킨다.
예를 들어 상하문 대상에 연결된 함수가 새로운 함수에 값을 부여받고 이 새로운 함수를 호출할 때
var obj = {
  a: 2,
 foo: function () {
   console.log(this.a)
  }
}
var a = 2
setTimeout(obj.foo, 0) // 2

우리 그때 어떻게 했는지 기억나?
...
var me = this;
return function () {
  me.xxx()
}
...

그리고 콜이나 apply로 표시된 귀속:
function foo() {
  console.log( this.a);
  }
var obj = {
  a: 2
  };
var bar = function() {
  foo.call(obj);
  };
bar();  // 2
setTimeout(bar, 100);  // 2

이런 용법이 너무 많아서 ES5에서 방법을 제시했어요 Function.prototype.bind (), 그것 때문에 엔지니어의 생활이 많이 좋아진 것 같습니다. 한 bind로 많은 문제를 해결할 수 있습니다.

bind 정의를 먼저 보겠습니다.


MDN의 정의는 다음과 같습니다.
bind () 방법은 새 함수를 만듭니다. 이 함수가 호출될 때this는 제공하는 값으로 설정하고, 매개 변수 목록의 앞부분은 만들 때 지정한 매개 변수 서열로 설정합니다.
fun.bind(thisArg[, arg1[, arg2[, ...]]])

bind() 함수는 조정된 함수와 동일한 함수체를 가진 새 바인딩 함수를 생성합니다(ECMAScript 5).귀속 함수를 호출하면 포장 함수 귀속 함수를 실행할 수도 있고 new 연산자 구조를 사용할 수도 있습니다. 이렇게 하면 마치 목표 함수를 이미 구성한 것과 같습니다.제공하는this값은 무시되고, 선행 인자는 아날로그 함수에 제공됩니다
전반적으로 bind에는 다음과 같은 세 가지 기능이 있습니다.
  • 원함수의this지향, 즉 상하문을 귀속시키고 원함수의 복사
  • 를 되돌려줍니다
  • 귀속 함수가 호출될 때bind의 추가 매개 변수는 실참 전에 귀속된 방법에 전달됩니다.
  • 귀속 함수도 new 조작부호를 사용하여 대상을 만들 수 있음을 주의하십시오. 이런 행위는 원래 함수를 구조기로 삼는 것과 같아서thisArg 파라미터가 무효입니다.즉 new 조작부호가this가 가리키는 우선순위를 수정하는 것입니다.

  • 그렇게 많이 말했는데, 우리 지금 bind 하나 실현할 수 있을까요?


    사실 때때로 이런 JS API의 실현을 연구하는 것은 매우 재미있다. 너는 많은 지식을 배울 수 있다.오늘 우리 손으로 한번 쓰다듬어 봅시다.
    bind의 정의 설명에서 볼 수 있듯이 우리가 쓸 이 함수의 입력과 출력은 기본적으로 확정되었다.
  • 입력: 하나 이상의 매개 변수를 받아들인다. 첫 번째는 귀속할 상하문이고 추가 매개 변수는 귀속 함수의 선행 매개 변수로 한다.
  • 출력: 원함수의 복사, 즉 하나의 함수를 되돌려줍니다. 이 함수는 원함수의 기능을 갖추고 있습니다
  • //  myBind
    Function.prototype.myBind = function(thisArg) {
      if (typeof this !== 'function') {
        return;
      }
      var _self = this;
      var args = Array.prototype.slice.call(arguments, 1) // 
      return function() {
        return _self.apply(thisArg, args.concat(Array.prototype.slice.call(arguments))); //  
      }
    }
    

    테스트해 보겠습니다.
    function foo(name) {
    this.name = name;
    }
    
    var obj = {}
    
    //     done
    var bar = foo.myBind(obj)
    bar('jack')
    console.log(obj.name) //'jack'
    
    //       done
    var tar = foo.myBind(obj, 'rose');
    tar()
    console.log(obj.name) //'rose'
    // new     error
    var alice = new bar('alice')
    console.log(obj.name) //alice   obj name should be 'jack'
    console.log(alice.name) //undefined, alice name should be 'alice'
    
    new를 사용하여 실례적으로 귀속된 방법을 볼 수 있고 상하문은 전송된obj를 가리킨다. 이 방법은 문제가 있다. 우리가 고려해야 할 것은 myBind의 실현에서 new의 조작을 검출해야 한다는 것이다.
    우리는 먼저 new 조작부호가 구조 함수를 호출할 때 어떤 조작을 했는지 고려해 봅시다.
    예를 들면var a = new b()
    {}
    .__proto__ = b.prototype
    

    그래서 우리는 다음과 같이 수정했다.
    Function.prototype.myBind = function(thisArg) {
      if (typeof this !== 'function') {
        return;
      }
      var _self = this;
      var args = Array.prototype.slice.call(arguments, 1)
      var fnBound = function () {
        //   New
        //  this this  new  
        var _this = this instanceof _self ? this : thisArg;
        return _self.apply(_this, args.concat(Array.prototype.slice.call(arguments)));
      }
      //   new 
      //       ( , ?
      fnBound.prototype = this.prototype;
      return fnBound;
    }
    

    테스트가 완료되었습니다.
    function foo(name) {
    this.name = name;
    }
    var obj = {};
    var bar = foo.myBind(obj);
    bar('Jack');
    console.log(obj.name);  // Jack
    var alice = new bar('Alice');
    console.log(obj.name);  // Jack
    console.log(alice.name);    // Alice
    

    이 용례에서 우리 토론해 봅시다
    bar의this지향:
  • 변수bar는 귀속 후의 함수, 즉fnBound,self는 원함수foo의 인용
  • 이다
  • 직접bar('jack')는 window나undefined를 가리킨다.
  • 그리고 new bar('alice')(new foo('alice'에 해당) 과정에서 fnBound의this는 new 표현식이 되돌아오는 대상 alice
  • 를 가리켰다.
  • new 호출 귀속 함수라면 귀속 함수 중의this는 new 호출 귀속 함수가 되돌아오는 실례 대상이고 이 대상의 구조 함수는fnBound이다
  • 우리가 원형 연결 행 코드를 무시할 때 그 원형 대상은 원 함수self의 원형과 같지 않기 때문에thisinstanceofself?this:oThis에서 얻은 값은 new에서 되돌아오는 대상이 아니라 지정한 전송 대상입니다
  • 그래서 fnBound.prototype = this.prototype이 필요합니다!!그러나 이 원형 값에 문제가 있음을 주의하십시오.
    이유는 제가 여기서 그만 말하고 여러분께 남겨 두겠습니다.
    Function.prototype.myBind = function(thisArg) {
      if (typeof this !== 'function') {
        return
      }
      var _self = this
      var args = Array.prototype.slice.call(arguments, 1)
      var fnNop = function () {} //  
      var fnBound = function () {
        var _this = this instanceof _self ? this : thisArg
    
        return _self.apply(_this, args.concat(Array.prototype.slice.call(arguments)))
      }
      //  
      if (this.prototype) {
        fnNop.prototype = this.prototype;
      }
    
      fnBound.prototype = new fnNop();
    
      return fnBound;
    }
    

    여기에 우리는 빈 함수를 만들어서 중간자가 되고 원 함수의 원형을 귀속 함수에 맡긴다. 문제가 되면 끝난다. 많은 지식이 있는지 천천히 보자.만약 당신이 괜찮다고 생각하거나 문장의 오류를 발견하거나 더 좋은 건의가 있다면 평론을 환영하거나 전단 창고에 들어오십시오: 866109386.

    좋은 웹페이지 즐겨찾기