Maison  >  Article  >  interface Web  >  Introduction détaillée à l'utilisation des fonctions de liaison, d'appel et d'application en JavaScript

Introduction détaillée à l'utilisation des fonctions de liaison, d'appel et d'application en JavaScript

黄舟
黄舟original
2017-03-14 15:23:121028parcourir

Lors de l'introduction de js dans d'autres programmes de notre équipe de projet, j'ai préparé beaucoup de contenu, mais cela n'a pas semblé avoir beaucoup d'effet Comme prévu, il ne suffit pas d'en parler, vous. il faut le faire. Il y a quelques jours, quelqu'un m'a interrogé sur l'utilisation de call() function dans le code, je lui ai demandé de lire un livre que je recommande aux programmeurs qui utilisent js d'écrire. les serveurs lisent javascriptProgrammingEssence" Ce livre, crockpourd ne l'a vraiment pas écrit. Plus tard, j'ai vu une question similaire sur segmentfault Après y avoir répondu, je viens de prendre une note ici.

Tout d'abord, concernant la méthode de définition d'une classe ou d'un objet en js, veuillez vous référer à w3school ici ici L'écriture est très détaillée et claire, donc. Je n'entrerai pas dans les détails.

Introduction détaillée à lutilisation des fonctions de liaison, dappel et dapplication en JavaScript

Afin de présenter l'utilisation des trois fonctions bind, call et apply, je dois introduire quelques paramètres de fonctions dans js. Concernant cette partie, il est recommandé de lire le chapitre 4 de "L'essence de la programmation JavaScript" Tout ce que je dis ici se trouve dans le livre.

Pour une introduction détaillée à ces trois fonctions, veuillez vous référer à la documentation MDN : bind, call, apply.

Commençons par les briques et modifions ma réponse précédente sur segmentfault :

Il existe 4 modes d'appel de fonction en js : appel de méthode et appel de fonction normal , appel de fonction constructeur, appel d'application/appel.

Dans le même temps, tout appel de fonction ajoutera automatiquement 2 paramètres formels, this et arguments, en plus des paramètres formels définis lors de votre déclaration.

arguments n'implique pas les trois fonctions ci-dessus, nous n'en parlons donc que ici. La valeur de this sera liée à différentes valeurs dans le mode d'appel en 4 ci-dessus. Parlons-en séparément :

Appel de méthode :

C'est facile à comprendre. Une fonction est l'attribut d'un objet , tel que

var a = {     
    v : 0,     
    f : function(xx) {                 
        this.v = xx;     
    } 
} 
a.f(5);
cette fois, this dans la fonction ci-dessus est lié à cet objet a. Donc this.v peut obtenir l'attribut v de l'objet a.

Appel de fonction normal : Toujours en train de regarder le code

function f(xx) {         
    this.x = xx; 
} 
f(5);
À ce stade, ceci dans la fonction f est lié à l'objet global, s'il est exécuté dans le navigateur Dans l'interpréteur, il s'agit généralement de l'objet window. Donc, ce à quoi this.x accède ici est window.x. Bien sûr, si window n'a pas d'attribut x, alors si vous l'écrivez comme ceci, selon la syntaxe de triche de js, vous ajouterez un x. attribut à l'objet window et attribuez une valeur en même temps.

Appel de fonction constructeur :

La fonction constructeur a toujours été ce que je pense être la partie la plus ennuyeuse de js, car c'est la même chose que la conception originale de js L'implémentation orientée objet basée sur un prototype n'est pas à sa place, comme si elle était spécialement conçue pour répondre aux habitudes que tout le monde a été gâchées par d'autres implémentations orientées objet basées sur les classes.

Si vous appelez une fonction avec le mot-clé

new, alors js créera un attribut prototype qui est un nouvel objet de cette fonction. En même temps, lors de l'appel de cette fonction, c'est le cas. lié à ce nouvel objet. Bien sûr, le nouveau mot-clé modifiera également le comportement de l'instruction return, mais nous n'en discuterons pas ici. Regardez le code

function a(xx)
{         
    this.m = xx; 
} 
var b = new a(5);
Il n'y a pas de différence entre la fonction ci-dessus et la fonction normalement appelée, sauf que le mot-clé new est ajouté devant le nom de la fonction lors de l'appel. lié. Ensuite, il y a l'objet global mentionné plus tôt, mais le nouvel objet créé ici, donc cette méthode est en fait très dangereuse, car rien qu'en regardant la fonction, vous ne saurez pas si cette fonction est destinée à être utilisée comme constructeur. ou utilisé par les fonctions générales. Nous pouvons donc voir que dans jslint, il aura besoin de tous les constructeurs que vous écrivez, c'est-à-dire qu'une fois qu'il aura constaté que vous avez utilisé le nouveau mot-clé, la première lettre de la fonction suivante doit être en majuscule. la fonction doit être en majuscule. Pour distinguer, je n'ai personnellement qu'un seul avis : tricher :)

postuler/appeler appeler :

我们知道,在 js 里,函数其实也是一个对象,那么函数自然也可以拥有它自己的方法,有点绕,在js 里,每个函数都有一个公共的 prototype —— Function,而这个原型自带有好几个属性和方法,其中就有这里困惑的 bind、call、apply 方法。先说 apply 方法,它让我们构造一个参数数组传递给函数,同时可以自己来设置 this 的值,这就是它最强大的地方,上面的 3 种函数调用方式,你可以看到,this 都是自动绑定的,没办法由你来设,当你想设的时候,就可以用 apply()了。apply 函数接收 2 个参数,第一个是传递给这个函数用来绑定 this 的值,第二个是一个参数数组。

看代码

function a(xx) {         
    this.b = xx; 
} 
var o = {}; 
a.apply(o, [5]); 
alert(a.b);    // undefined 
alert(o.b);    // 5

是不是很神奇,函数 a 居然可以给 o 加属性值。当然,如果你 apply 的第一个参数传递 null,那么在函数 a 里面 this 指针依然会绑定全局对象。

call() 方法和 apply() 方法很类似,它们的存在都是为了改变 this 的绑定,那 call() 和apply() 有什么区别呢?就我个人看来,没啥鸟区别。。。开玩笑!刚刚说了,上面 apply() 接收两个参数,第一个是绑定 this 的值,第二个是一个参数数组,注意它是一个数组,你想传递给这个函数的所有参数都放在数组里,然后 apply() 函数会在调用函数时自动帮你把数组展开。而 call()呢,它的第一个参数也是绑定给 this 的值,但是后面接受的是不定参数,而不再是一个数组,也就是说你可以像平时给函数传参那样把这些参数一个一个传递。

所以如果一定要说有什么区别的话,看起来是这样的

function a(xx, yy) {     
    alert(xx, yy);     
    alert(this);     
    alert(arguments); 
} 
a.apply(null, [5, 55]); 
a.call(null, 5, 55);

仅此而已。

最后再来说 bind() 函数,上面讲的无论是 call() 也好, apply() 也好,都是立马就调用了对应的函数,而 bind() 不会, bind() 会生成一个新的函数,bind() 函数的参数跟 call() 一致,第一个参数也是绑定 this 的值,后面接受传递给函数的不定参数。 bind() 生成的新函数返回后,你想什么时候调就什么时候调,看下代码就明白了

var m = {    
    "x" : 1 
}; 
function foo(y) { 
    alert(this.x + y); 
} 
foo.apply(m, [5]); 
foo.call(m, 5); 
var foo1 = foo.bind(m, 5); 
foo1();

末了来个吐槽,你在 js 里想定义一个函数,于是你会这么写:

function jam() {};

其实这是 js 里的一种语法糖,它等价于:

var jam = function() {};

然后你想执行这个函数,脑洞大开的你会这么写:

function jam() {}();

但是这么写就报错了,其实这种写法也不算错,因为它确实是 js 支持的函数表达式,但是同时 js 又规定以function 开头的语句被认为是函数语句,而函数语句后面是肯定不会带 () 的,所以才报错,于是聪明的人想出来,加上一对括号就可以了。于是就变成了这样:

1(function jam() {}());

这样就定义了一个函数同时也执行它,详情参加 ECMAScript  Expression Statement 章节。

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