2.this,call,apply

4991 단어
본고는 본인의 (탐저)에 대한 읽기와 총결산에서 기원한다.자세한 내용을 알고 싶으면 이 책을 읽으세요.

1. this


this는 항상 하나의 대상을 가리키며, 실행할 때 함수를 기반으로 하는 실행 환경의 동적 연결을 구체적으로 가리킨다.

this의 지향


with와 eval을 제외하고 실제 응용에서this지향은 다음과 같은 네 가지로 나뉜다.
  • 를 대상으로 하는 방법 호출
  • 일반 함수로 호출
  • 구조기 호출
  • Function.prototype.call & Function.prototype.apply

  • 대상의 방법으로 호출하다
    var obj = {
        a: 1,
        getA: function(){
            console.log(this === obj); // true
            console.log(this.a); // 1
        }
    }
    
    obj.getA();
    

    이때,obj가 호출한 geta() 함수이기 때문에this는obj를 가리킨다.
    일반 함수로 호출
    var obj = {
        name: aaaa,
        getName: function(){
            console.log(this === obj); // false
            console.log(this.name); // yozo
        }
    }
    
    window.name = yozo;
    var getGlobalName = function(){
        console.log(this.name);
    }
    
    var getName = obj.getName;
    
    getGlobalName(); // yozo;
    getName();
    

    함수에 호출자가 없으면 this는 전역 대상을 가리키며 브라우저의 Js에서 전역 대상은 window입니다.엄격한 모드에서this는 전체 대상을 가리키지 않습니다.여기서 주로 볼 때getName 그 자체는 하나의 함수일 뿐이고 추출되어 있기 때문에getName()를 실행할 때 호출자가 없고 getGlobalName와 같이 일반 함수로 호출된다.
    구조기 호출
    var Myclass = function(){
        this.name = 'yozo';
    };
    
    var obj = new Myclass();
    console.log(obj.name); // yozo
    

    이때의this는 새로 만들어진 대상을 대표한다obj.
    하지만
    var Myclass = function(){
        this.name = 'yozo';
        return {
            name: 'ann'
        }
    };
    
    var obj = new Myclass();
    console.log(obj.name); // ann
    

    대상을 되돌려준다고 표시할 때, 이 때 되돌려준다는 대상은obj에 인용되기 때문에 이때obj.name는 yozo가 아니라 ann입니다.
    Function.prototype.call & Function.prototype.apply
    var obj1 = {
        name: 'yozo',
        getName: function(){
            console.log(this.name);
        }
    }
    
    var obj2 = {
        name: 'ann'
    }
    
    console.log(obj1.getName()); // yozo
    console.log(obj1.getName.call(obj2)); // ann
    
  • 첫 번째 콘솔에서 getName의 호출자는obj1이고this는obj1을 가리킨다.
  • 두 번째 콘솔 중getName의 호출자는 원래obj1이었으나 이때 나타났다.call(obj2).마치 obj2에게 전화를 걸어 "여보세요,obj2,obj1의 getName 방법을 집행하세요"라고 말한 것 같다. 그래서 이때 호출자는 obj2가 된다. 우리는 this가 항상 호출자를 가리키는 것을 알고 있다. 그래서 이때this는 obj2를 가리킨다.

  • 2. 콜과 apply


    콜과 apply의 차이
    방금 우리가 말했듯이call의 작용은 바로 함수를 바꾸는 호출자이다.그럼 apply의 역할은요?함수를 바꾸는 호출자이기도 하다.차이점은 콜과 apply가 모두 Function이라는 점이다.prototype의 방법이기 때문에 함수만 이 두 함수를 호출할 수 있습니다. 함수의call과apply라면 함수는 실행할 때 항상 파라미터가 있을 것입니다. 그러면 호출자를 바꾸면 함수의 파라미터는 어떻게 처리합니까?
  • call: 매개 변수를 하나하나 열거하기(고정되지 않은 매개 변수, 첫 번째는 새로운 호출자, 다른 것은 이 함수에 전송된 다른 매개 변수)
  • apply: 매개 변수를 한 솥에 전송(두 개의 매개 변수만 있고, 첫 번째는 새로운 호출자, 다른 매개 변수는 매개 변수 그룹)
  • var func = function(a, b, c){
        console.log([a, b, c]);
    }
    
    func.apply(null,[1, 2, 3]);
    func.call(null, 1, 2, 3);
    

    이 함수는this가 없기 때문에 호출자가 필요하지 않습니다. 우리는 콜과 apply의 사용법을 구별하는 데만 사용됩니다.
  • call: 두 번째 매개 변수부터func에 대응하는 매개 변수
  • apply: 매개 변수 수조와func의 각 매개 변수가 일일이 대응한다.

  • 콜 및 apply 용도
  • this지향변경
  • document.getElementById('div1').onclick = function(){
        console.log(this.id); // div1
        var func = function(){
            console.log(this.id);
        }
        func(); // undefined ( )
        func.call(this); // div1 
    }
    

    onclick 리셋 함수에서this는document을 표시합니다.getElementById ('div1 ') 이지만,func () 를 실행할 때 호출자가 없습니다. 기본 호출자는 window이지만,document을 가리키기를 바랍니다.getElementById ('div1') 는 이 함수를 호출하도록 this를func에 전달합니다.
  • Function.prototype.bind: 함수의this를 특정한 대상으로 고정시킨 다음 사용할 때 콜과 apply를 사용하지 않습니다.Starter:
  • Function.prototype.bind = function (context) {
      var self = this;
      return function () {
        self.apply(context, arguments);
      }
    }
    
    var obj1 = {
      name: 'yozo',
      getName: function () {
        console.log(this.name);
      }
    }
    
    var obj2 = {
      name: 'ann'
    }
    
    var obj2getName = obj1.getName.bind(obj2);
    obj2getName(); // ann
    

    이때의this는 이미obj2로 고정되었다.
    이 버전에서는 객체를 고정할 때 매개변수를 저장할 수 없으므로 업그레이드 버전:
    Function.prototype.bind = function () {
      var self = this; //  
      var context = [].shift.call(arguments); //  , 
      var args = [].slice.call(arguments); //  
      
      //  
      return function () {
        //  , , 
        self.apply(context, [].concat.call(args, [].slice.call(arguments)));
      }
    }
    
    var obj = {
      name: 'yozo'
    }
    
    var func = function (a, b, c, d) {
      console.log(this.name);
      console.log([a, b, c, d]);
    }.bind(obj, 1, 2);
    
    func(3, 4); // 1, 2, 3, 4
    
  • 다른 대상을 빌리는 방법: 이전obj1.getName.call(obj2)은obj2가obj1을 빌리는 방법이다.우리가 자주 사용하는 것은 Object나 Array의 프로토타입을 빌리는 방법:
  • (function(){
        Array.prototype.push.call(arguments, 3, 4);
        console.log(arguments);
    })(1, 2)
    
    // 1, 2, 3, 4
    

    이것은 사실arguments 매개 변수 그룹의 대상이 진수 그룹의 대상을 이용하고 매개 변수 그룹은 위조수 그룹(DOM 노드 그룹도)이지만 위조수 그룹은 진수 그룹의 방법을 빌려 쓸 수 있다.
    위조 배열은 다음 두 조건을 충족해야 합니다.
  • 객체 자체에 대한 액세스 가능 속성
  • 대상length 속성 읽기 가능
  • 좋은 웹페이지 즐겨찾기