Maison  >  Article  >  interface Web  >  Quatre formes contraignantes de ceci dans les fonctions javascript

Quatre formes contraignantes de ceci dans les fonctions javascript

小云云
小云云original
2018-02-22 09:30:341695parcourir
À ce sujet, de nombreux concepts abstraits qui donnent le vertige ressortent. Ici, je ne parlerai que du point le plus essentiel - celui-ci dans une fonction pointe toujours vers l'objet qui l'appelle. les histoires suivantes tourneront toutes autour de ce point.
[Histoire] Il y a un jeune homme nommé "Dis" (ceci). Un jour, Dis a accidentellement voyagé dans un monde différent appelé "Gavaskeli" (javascript). À ce moment, Dis étant sans le sou, le premier). la chose qu'il doit faire est - trouver son endroit où rester - l'objet pour appeler la fonction

Liaison par défaut de ceci

[Histoire - Route 1] Si Dis (ceci) n'est pas disponible avant la nuit Incapable de trouver un endroit pour l'accueillir, il était sur le point de vivre la vie d'un réfugié africain. A cette époque, un chef de village magicien au bon cœur - sauveur de fenêtre est apparu comme un sauveur : Reste d'abord dans ma maison !

[Texte]
Lorsqu'une fonction n'a pas d'objet appelant clair, c'est-à-dire lorsqu'elle est simplement appelée comme une fonction indépendante, la liaison par défaut sera utilisée pour cela de la fonction : liée à l'objet fenêtre globale
function fire () {
     console.log(this === window)
}
fire(); // 输出true

I croyez l'exemple ci-dessus C'est simple pour la plupart des gens, mais parfois c'est déroutant si nous changeons l'exemple :
Quatre formes contraignantes de ceci dans les fonctions javascript
function fire () {
  // 我是被定义在函数内部的函数哦!     function innerFire() {
  console.log(this === window)
      }
     innerFire(); // 独立函数调用}
fire(); // 输出true
Quatre formes contraignantes de ceci dans les fonctions javascript

La fonction innerFire est déclarée et appelée dans une fonction externe fire, alors à qui pointe-t-elle ? Fenêtre toujours
Beaucoup de gens peuvent s'inquiéter de l'impact de la portée de la fonction de tir sur innerFire, mais nous n'avons besoin que de saisir notre arme théorique - lorsqu'il n'y a pas d'objet d'appel clair, nous utiliserons celle du function Liaison par défaut : liez-vous à l'objet fenêtre global pour obtenir la bonne réponse
La version améliorée de l'exemple ci-dessous affiche également vrai de la même manière
var obj = {
   fire: function () {
       function innerFire() {
          console.log(this === window)
        }
        innerFire();   // 独立函数调用     }
}
obj.fire(); //输出 true
Quatre formes contraignantes de ceci dans les fonctions javascript

[Note] Dans cet exemple, le L'appel à obj.fire() utilise en fait la liaison implicite de ceci. C'est ce dont je vais parler ci-dessous. Je vais continuer à expliquer cet exemple
[Résumé] Toutes les fonctions sont indépendantes. Un appel de fonction, peu importe. où il se trouve, se comporte de la même manière que de l'appeler directement dans l'environnement global

cette liaison implicite

[ Histoire - Route 2] Lorsque Dis (ceci) a voyagé dans le monde différent "Gavaskeli" (javascript), il s'est avéré qu'il avait de l'argent avec lui, alors il a trouvé un hôtel. Il est resté

Lorsqu'une fonction est "contenue" par un objet, on dit que le this de la fonction est implicitement lié à l'objet, à ce moment, vous pouvez accéder directement aux autres propriétés de l'objet lié via. ceci, comme ce qui suit une propriété
Quatre formes contraignantes de ceci dans les fonctions javascript
var obj = {
     a: 1,
      fire: function () {
           console.log(this.a)
        }
}
obj.fire(); // 输出1
Quatre formes contraignantes de ceci dans les fonctions javascript

Nous devons maintenant réfléchir plus en profondeur aux opérations de code courantes. Tout d'abord, ci-dessous. Les deux morceaux de code obtiennent le même effet :
Quatre formes contraignantes de ceci dans les fonctions javascript
// 我是第一段代码function fire () {
      console.log(this.a)
}
  var obj = {
      a: 1,
      fire: fire
  }
obj.fire(); // 输出1
 // 我是第二段代码var obj = {
        a: 1,
        fire: function () {
             console.log(this.a)
         }
}
obj.fire(); // 输出1
Quatre formes contraignantes de ceci dans les fonctions javascript

Le La fonction fire ne fait aucune différence car elle est définie à l'intérieur et à l'extérieur de l'objet obj, c'est-à-dire dans la liaison implicite ci-dessus. Dans les deux formes, fire peut toujours accéder à la propriété a dans obj via ceci, ce qui nous dit :
1. Ceci est lié dynamiquement, ou il est lié pendant l'exécution du code plutôt que pendant la période d'écriture
2 L'indépendance des fonctions par rapport aux objets, le problème de la perte de transmission de ceci<.> 
(下面的描述可能带有个人的情感倾向而显得不太严谨,但这是因为我希望阅读者尽可能地理解我想表达的意思)
Quatre formes contraignantes de ceci dans les fonctions javascript

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

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

 

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

 

 
在上面,我们的关键角色是otherFire函数,它接受一个函数引用作为参数,然后在内部直接调用,但它做的假设是参数fn仍然能够通过this去取得obj内部的a属性,但实际上, this对obj的绑定早已经丢失了,所以输出的是全局的a的值(2),而不是obj内部的a的值(1)
 Quatre formes contraignantes de ceci dans les fonctions javascript

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

在隐式绑定中,如果函数调用位置是在一串对象属性链中,this绑定的是最内层的对象。如下所示:
Quatre formes contraignantes de ceci dans les fonctions javascript
var obj = {
      a: 1,
      obj2: {
           a: 2,
           obj3: {
                a:3,
                getA: function () {
                    console.log(this.a)   
                 }
           }
       }
}
 
obj.obj2.obj3.getA();  // 输出3
Quatre formes contraignantes de ceci dans les fonctions javascript

 

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对象
 
例子:
Quatre formes contraignantes de ceci dans les fonctions javascript
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
Quatre formes contraignantes de ceci dans les fonctions javascript

 

 
原本丢失了与obj绑定的this参数的fireInGrobal再次重新把this绑回到了obj
 
但是,我们其实不太喜欢这种每次调用都要依赖call的方式,我们更希望:能够一次性 返回一个this被永久绑定到obj的fireInGrobal函数,这样我们就不必每次调用fireInGrobal都要在尾巴上加上call那么麻烦了。
 
怎么办呢? 聪明的你一定能想到,在fireInGrobal.call(obj)外面包装一个函数不就可以了嘛!
Quatre formes contraignantes de ceci dans les fonctions javascript
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
Quatre formes contraignantes de ceci dans les fonctions javascript

 

如果使用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指向所创建的新对象
 
Quatre formes contraignantes de ceci dans les fonctions javascript
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对象用法实例详解

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn