>  기사  >  웹 프론트엔드  >  자바스크립트 함수의 네 가지 바인딩 형식

자바스크립트 함수의 네 가지 바인딩 형식

小云云
小云云원래의
2018-02-22 09:30:341695검색
이때 사람들을 현기증나게 만드는 추상적인 개념이 많이 나옵니다. 여기서는 핵심만 이야기하겠습니다. 함수에서 이것은 항상 호출하는 개체를 가리키며, 다음 이야기는 모두입니다. 이것을 중심으로 돌아갑니다.
【스토리】 어느 날, 디스는 우연히 "가바스켈리"(자바스크립트)라는 다른 세계로 여행을 떠났습니다. 그 순간 디스는 무일푼이었습니다. 할 일은 - 숙소 찾기 - 함수를 호출할 객체

이 기본 바인딩

【스토리—— 루트 1] If Dis (this )는 어두워지기 전에 데려갈 곳을 찾지 못해 아프리카 난민의 삶을 살게 된다. 이때 친절한 마술사 마을 촌장——창구의 구원자가 나타났다: 먼저 내 집에 있어라!

【텍스트】
함수에 명확한 호출 개체가 없는 경우, 즉 단순히 독립 함수로 호출되는 경우 이 함수에 대해 기본 바인딩이 사용됩니다. 창 개체
function fire () {
     console.log(this === window)
}
fire(); // 输出true

위의 예는 대부분의 사람들에게 간단하다고 생각하지만, 예를 바꾸면 때로는 혼란스러워질 수 있습니다.

function fire () {
  // 我是被定义在函数内部的函数哦!     function innerFire() {
  console.log(this === window)
      }
     innerFire(); // 独立函数调用}
fire(); // 输出true
obj.fire()에 대한 호출은 실제로 이것의 암시적 바인딩을 사용합니다. 이것이 제가 아래에서 설명할 내용입니다. 이 예제는 다음에 계속 설명하겠습니다자바스크립트 함수의 네 가지 바인딩 형식[요약] 모든 함수는 독립적입니다. 함수 호출은 어디에 있든 상관없습니다. 는 글로벌 환경에서 직접 호출하는 것과 동일하게 동작합니다
Back to top 자바스크립트 함수의 네 가지 바인딩 형식
이 암시적 바인딩

[스토리 - 경로 2] Dis(this)가 이세계로 여행했을 때 "Gavaskeli"(javascript) ), 그는 우연히 돈을 가지고 있었기 때문에

에 묵을 호텔을 찾았습니다. 함수가 객체에 의해 "포함"되면 함수의 this가 암시적으로 this에 바인딩되어 있다고 말합니다. 이때 바인딩된 개체의 다른 속성(예: 아래의 a 속성)에 직접 액세스할 수 있습니다. 일반적인 코드 작업에 대해 더 깊이 생각해보면, 다음 두 코드는 동일한 효과를 얻습니다.자바스크립트 함수의 네 가지 바인딩 형식

var obj = {
   fire: function () {
       function innerFire() {
          console.log(this === window)
        }
        innerFire();   // 独立函数调用     }
}
obj.fire(); //输出 true

fire 함수는 아무런 차이가 없습니다. 이는 obj 객체 내부와 외부에 정의되어 있기 때문입니다. 즉, 위의 두 가지 암시적 바인딩 형식에서 fire는 이를 전달합니다. obj의 a 속성에 계속 액세스할 수 있으며 이는 다음과 같습니다. 자바스크립트 함수의 네 가지 바인딩 형식1. , 또는 작성 중이 아닌 코드 실행 시간 동안 바인딩됩니다.
2. 객체로부터 함수의 독립성, 전달 손실 문제
 
(下面的描述可能带有个人的情感倾向而显得不太严谨,但这是因为我希望阅读者尽可能地理解我想表达的意思)
자바스크립트 함수의 네 가지 바인딩 형식

隐式绑定下,作为对象属性的函数,对于对象来说是独立的

 
基于this动态绑定的特点,写在对象内部,作为对象属性的函数,对于这个对象来说是独立的。(函数并不被这个外部对象所“完全拥有”)
 
我想表达的意思是:在上文中,函数虽然被定义在对象的内部中,但它和“在对象外部声明函数,然后在对象内部通过属性名称的方式取得函数的引用”,这两种方式在性质上是等价的(而不仅仅是效果上)
 
定义在对象内部的函数只是“恰好可以被这个对象调用”而已,而不是“生来就是为这个对象所调用的”
 
借用下面的隐式绑定中的this传递丢失问题来说明:
자바스크립트 함수의 네 가지 바인딩 형식
var obj = {
      a: 1,    // a是定义在对象obj中的属性   1      fire: function () {
   console.log(this.a)
        }
      }
 var a = 2;  // a是定义在全局环境中的变量    2var fireInGrobal = obj.fire;  
fireInGrobal(); //  输出 2
자바스크립트 함수의 네 가지 바인딩 형식

 

 
上面这段简单代码的有趣之处在于: 这个于obj中的fire函数的引用( fireInGrobal)在调用的时候,行为表现(输出)完全看不出来它就是在obj内部定义的,其原因在于:我们隐式绑定的this丢失了!! 从而 fireInGrobal调用的时候取得的this不是obj,而是window
 
上面的例子稍微变个形式就会变成一个可能困扰我们的bug:
 
자바스크립트 함수의 네 가지 바인딩 형식
var a = 2;var obj = {
    a: 1,    // a是定义在对象obj中的属性    fire: function () {
          console.log(this.a)
     }
}  
function otherFire (fn) {
     fn();
}  
otherFire(obj.fire); // 输出2
자바스크립트 함수의 네 가지 바인딩 형식

 

 
在上面,我们的关键角色是otherFire函数,它接受一个函数引用作为参数,然后在内部直接调用,但它做的假设是参数fn仍然能够通过this去取得obj内部的a属性,但实际上, this对obj的绑定早已经丢失了,所以输出的是全局的a的值(2),而不是obj内部的a的值(1)
 자바스크립트 함수의 네 가지 바인딩 형식

在一串对象属性链中,this绑定的是最内层的对象

在隐式绑定中,如果函数调用位置是在一串对象属性链中,this绑定的是最内层的对象。如下所示:
자바스크립트 함수의 네 가지 바인딩 형식
var obj = {
      a: 1,
      obj2: {
           a: 2,
           obj3: {
                a:3,
                getA: function () {
                    console.log(this.a)   
                 }
           }
       }
}
 
obj.obj2.obj3.getA();  // 输出3
자바스크립트 함수의 네 가지 바인딩 형식

 

this的显式绑定:(call和bind方法)

【故事——线路3】 迪斯(this)穿越来异世界“伽瓦斯克利”(javascript),经过努力的打拼,积累了一定的财富,于是他买下了自己的房子
 

 

上面我们提到了this的隐式绑定所存在的this绑定丢失的问题,也就是对于 “ fireInGrobal = obj.fire”
fireInGrobal调用和obj.fire调用的结果是不同的,因为这个函数赋值的过程无法把fire所绑定的this也传递过去。这个时候,call函数就派上用场了

 

call的基本使用方式: fn.call(object)
fn是你调用的函数,object参数是你希望函数的this所绑定的对象。
fn.call(object)的作用:
1.即刻调用这个函数(fn)
2.调用这个函数的时候函数的this指向object对象
 
例子:
자바스크립트 함수의 네 가지 바인딩 형식
var obj = {
      a: 1,    // a是定义在对象obj中的属性      fire: function () {
         console.log(this.a)
      }
}
 var a = 2;  // a是定义在全局环境中的变量  var fireInGrobal = obj.fire;
fireInGrobal();   // 输出2fireInGrobal.call(obj); // 输出1
자바스크립트 함수의 네 가지 바인딩 형식

 

 
原本丢失了与obj绑定的this参数的fireInGrobal再次重新把this绑回到了obj
 
但是,我们其实不太喜欢这种每次调用都要依赖call的方式,我们更希望:能够一次性 返回一个this被永久绑定到obj的fireInGrobal函数,这样我们就不必每次调用fireInGrobal都要在尾巴上加上call那么麻烦了。
 
怎么办呢? 聪明的你一定能想到,在fireInGrobal.call(obj)外面包装一个函数不就可以了嘛!
자바스크립트 함수의 네 가지 바인딩 형식
var obj = {
      a: 1,    // a是定义在对象obj中的属性      fire: function () {
        console.log(this.a)
      }
}
 var a = 2;  // a是定义在全局环境中的变量  var fn = obj.fire;var fireInGrobal = function () {
    fn.call(obj)   //硬绑定}
       
fireInGrobal(); // 输出1
자바스크립트 함수의 네 가지 바인딩 형식

 

如果使用bind的话会更加简单
var fireInGrobal = function () {
    fn.call(obj)   //硬绑定}

 

可以简化为:
var fireInGrobal = fn.bind(obj);

 

call和bind的区别是:在绑定this到对象参数的同时:
 
1.call将立即执行该函数
2.bind不执行函数,只返回一个可供执行的函数
 
【其他】:至于apply,因为除了使用方法,它和call并没有太大差别,这里不加赘述
 
在这里,我把显式绑定和隐式绑定下,函数和“包含”函数的对象间的关系比作买房和租房的区别。
 

 

因为this的缘故
 
在隐式绑定下:函数和只是暂时住在“包含对象“的旅馆里面,可能过几天就又到另一家旅馆住了
在显式绑定下:函数将取得在“包含对象“里的永久居住权,一直都会”住在这里“
 

new绑定

【故事】 迪斯(this)组建了自己的家庭,并生下多个孩子(通过构造函数new了许多个对象)
 
 

 

执行new操作的时候,将创建一个新的对象,并且将构造函数的this指向所创建的新对象
 
자바스크립트 함수의 네 가지 바인딩 형식
function foo (a) {     this.a = a;
}
 var a1  = new foo (1);var a2  = new foo (2);var a3  = new foo (3);var a4  = new foo (4);
 
console.log(a1.a); // 输出1console.log(a2.a); // 输出2console.log(a3.a); // 输出3console.log(a4.a); // 输出4

相关推荐:

JavaScript中的this规则及this对象用法实例

函数调用的不同方式及this的指向详解

js中this对象用法实例详解

위 내용은 자바스크립트 함수의 네 가지 바인딩 형식의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.