Maison >interface Web >js tutoriel >Activez le mode visite guidée d'utilisation pour appliquer, appeler et lier les compétences Javascript_javascript

Activez le mode visite guidée d'utilisation pour appliquer, appeler et lier les compétences Javascript_javascript

WBOY
WBOYoriginal
2016-05-16 15:34:461098parcourir

J'espère qu'à travers cet article, je pourrai clairement améliorer ma compréhension de l'application, de l'appel et de la liaison, et énumérer certaines de leurs merveilleuses utilisations pour approfondir ma mémoire.

postulez, appelez

En JavaScript, appeler et appliquer les deux existent pour changer le contexte lorsqu'une fonction est en cours d'exécution. En d'autres termes, ils doivent changer le pointeur de this à l'intérieur du corps de la fonction.

Une caractéristique majeure de JavaScript est que les fonctions ont les concepts de « contexte de définition » et de « contexte d'exécution » ainsi que de « contexte pouvant être modifié ».

Permettez-moi d'abord de vous donner un exemple de code :

function fruits() {}
fruits.prototype = {
  color: "red",
  say: function() {
    console.log("My color is " + this.color);
  }
}
var apple = new fruits;
apple.say();  //My color is red

Mais si nous avons un objet banane = {color : "jaune"} et que nous ne voulons pas redéfinir sa méthode say, alors nous pouvons utiliser la méthode say d'Apple via call ou apply :

banana = {
  color: "yellow"
}
apple.say.call(banana);   //My color is yellow
apple.say.apply(banana);  //My color is yellow

Ainsi, on peut voir que call et apply semblent changer cela de manière dynamique. Lorsqu'un objet n'a pas une certaine méthode (la banane dans cette châtaigne n'a pas de méthode say), mais d'autres en ont (la pomme dans cette châtaigne en a). une méthode par exemple), nous pouvons utiliser call ou apply pour fonctionner en utilisant les méthodes d'autres objets.

La différence entre postuler et appeler

Pour apply et call, les fonctions sont exactement les mêmes, mais la manière d'accepter les paramètres est différente. Par exemple, il existe une fonction définie comme suit :

var func = function(arg1, arg2) { 
};

peut être appelé comme suit :

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])

Lorsque c'est le contexte que vous souhaitez spécifier, il peut s'agir de n'importe quel objet JavaScript (tout en JavaScript est un objet), l'appel doit transmettre les paramètres dans l'ordre et l'application place les paramètres dans un tableau. ​

En JavaScript, le nombre de paramètres d'une fonction n'est pas fixe, donc si vous souhaitez appliquer des conditions, utilisez call lorsque le nombre de vos paramètres est clairement connu.

En cas de doute, utilisez apply, puis insérez les paramètres dans le tableau et transmettez-les. Lorsque le nombre de paramètres est incertain, tous les paramètres peuvent être parcourus à l'intérieur de la fonction via le tableau d'arguments.

Afin de consolider et d'approfondir la mémoire, voici quelques utilisations courantes :

1. Ajouter entre les tableaux

var array1 = [12 , "foo" , {name "Joe"} , -2458]; 
var array2 = ["Doe" , 555 , 100]; 
Array.prototype.push.apply(array1, array2); 
/* array1 值为 [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */

2. Obtenez les valeurs maximales et minimales dans le tableau

var numbers = [5, 458 , 120 , -215 ]; 
var maxInNumbers = Math.max.apply(Math, numbers),  //458
  maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458

Number lui-même n'a pas de méthode max, mais Math en a, nous pouvons donc utiliser sa méthode avec call ou apply.

3. Vérifiez s'il s'agit d'un tableau (à condition que la méthode toString() n'ait pas été remplacée)

functionisArray(obj){ 
  return Object.prototype.toString.call(obj) === '[object Array]' ;
}

4. Le tableau de classe (pseudo) utilise la méthode tableau

var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));

Il existe une structure d'objet appelée pseudo-tableau en Javascript. Ce qui est plus spécial, c'est l'objet arguments, et les appels comme getElementsByTagName, document.childNodes, etc., qui renvoient des objets NodeList sont des pseudo-tableaux. Les méthodes push, pop et autres sous Array ne peuvent pas être appliquées.

Mais nous pouvons le convertir en un véritable objet tableau avec la propriété length via Array.prototype.slice.call, afin que domNodes puisse appliquer toutes les méthodes sous Array.

Compréhension approfondie de l'utilisation de Apply et Call

Ce qui suit est [empruntant une question d'entretien] pour comprendre postuler et appeler plus en profondeur.

Définissez une méthode de journalisation afin qu'elle puisse proxy la méthode console.log. Une solution courante est :

function log(msg) {
 console.log(msg);
}
log(1);  //1
log(1,2);  //1

La méthode ci-dessus peut résoudre les besoins les plus élémentaires, mais lorsque le nombre de paramètres transmis est incertain, la méthode ci-dessus n'est pas valide pour le moment, vous pouvez envisager d'utiliser apply ou call. Faites attention au nombre de paramètres transmis. ici. est incertain, il est donc préférable d'utiliser apply La méthode est la suivante :

function log(){
 console.log.apply(console, arguments);
};
log(1);  //1
log(1,2);  //1 2

La prochaine exigence est d'ajouter un préfixe "(app)" à chaque message de journal, tel que :

log("hello world");  //(app)hello world

Comment le faire plus élégamment ? À ce stade, vous devez penser que le paramètre arguments est un pseudo-tableau, le convertir en un tableau standard via Array.prototype.slice.call, puis utiliser la méthode array unshift, comme ça :

function log(){
 var args = Array.prototype.slice.call(arguments);
 args.unshift('(app)');
 console.log.apply(console, args);
};

lier

Après avoir parlé de postuler et d’appeler, parlons de liaison. La méthode bind() est très similaire à apply et call, et peut également changer le pointeur de this dans le corps de la fonction.

L'explication de MDN est la suivante : la méthode bind() créera une nouvelle fonction, appelée fonction de liaison. Lorsque cette fonction de liaison est appelée, la fonction de liaison sera basée sur la première valeur transmise à la méthode bind() lorsqu'elle l'a été. créé. Le paramètre est celui-ci, et le deuxième paramètre et les suivants passés dans la méthode bind() ainsi que les paramètres de la fonction liée elle-même lors de l'exécution sont utilisés comme paramètres de la fonction d'origine pour appeler la fonction d'origine.

Voyons comment l'utiliser directement. Dans le mode singleton commun, nous utilisons généralement _this, that, self, etc. pour enregistrer ceci afin que nous puissions continuer à y faire référence après avoir changé le contexte. Comme ça :

var foo = {
  bar : 1,
  eventBind: function(){
    var _this = this;
    $('.someClass').on('click',function(event) {
      /* Act on the event */
      console.log(_this.bar);   //1
    });
  }
}

由于 Javascript 特有的机制,上下文环境在 eventBind:function(){ } 过渡到 $('.someClass').on('click',function(event) { }) 发生了改变,上述使用变量保存 this 这些方式都是有用的,也没有什么问题。当然使用 bind() 可以更加优雅的解决这个问题:

var foo = {
  bar : 1,
  eventBind: function(){
    $('.someClass').on('click',function(event) {
      /* Act on the event */
      console.log(this.bar);   //1
    }.bind(this));
  }
}

在上述代码里,bind() 创建了一个函数,当这个click事件绑定在被调用的时候,它的 this 关键词会被设置成被传入的值(这里指调用bind()时传入的参数)。因此,这里我们传入想要的上下文 this(其实就是 foo ),到 bind() 函数中。然后,当回调函数被执行的时候, this 便指向 foo 对象。再来一个简单的栗子:

var bar = function(){
console.log(this.x);
}
var foo = {
x:3
}
bar(); // undefined
var func = bar.bind(foo);
func(); // 3

这里我们创建了一个新的函数 func,当使用 bind() 创建一个绑定函数之后,它被执行的时候,它的 this 会被设置成 foo , 而不是像我们调用 bar() 时的全局作用域。

有个有趣的问题,如果连续 bind() 两次,亦或者是连续 bind() 三次那么输出的值是什么呢?像这样:

var bar = function(){
  console.log(this.x);
}
var foo = {
  x:3
}
var sed = {
  x:4
}
var func = bar.bind(foo).bind(sed);
func(); //?
 
var fiv = {
  x:5
}
var func = bar.bind(foo).bind(sed).bind(fiv);
func(); //?

答案是,两次都仍将输出 3 ,而非期待中的 4 和 5 。原因是,在Javascript中,多次 bind() 是无效的。更深层次的原因, bind() 的实现,相当于使用函数在内部包了一个 call / apply ,第二次 bind() 相当于再包住第一次 bind() ,故第二次以后的 bind 是无法生效的。

   apply、call、bind比较

那么 apply、call、bind 三者相比较,之间又有什么异同呢?何时使用 apply、call,何时使用 bind 呢。简单的一个栗子:

var obj = {
  x: 81,
};
var foo = {
  getX: function() {
    return this.x;
  }
}
console.log(foo.getX.bind(obj)()); //81
console.log(foo.getX.call(obj));  //81
console.log(foo.getX.apply(obj));  //81

三个输出的都是81,但是注意看使用 bind() 方法的,他后面多了对括号。

也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。

再总结一下:

apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后续参数传参;

bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

好了,本文关于开启Javascript中apply、call、bind的用法之旅模式的相关教程,到此给大家介绍完了,希望大家喜欢。

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