En JavaScript, call, apply et bind sont les trois méthodes fournies avec l'objet Function. Cet article comprendra les trois méthodes en détail à travers l'application de plusieurs scénarios.
appel()
La méthode call() appelle une fonction ou une méthode en utilisant une valeur this spécifiée et plusieurs valeurs de paramètres spécifiées.
Lors de l'appel d'une fonction, vous pouvez attribuer un autre objet à cet objet. ceci fait référence à l'objet actuel, le premier paramètre de la méthode d'appel.
Grâce à la méthode d'appel, vous pouvez emprunter des méthodes sur un objet à un autre objet, comme Object.prototype.toString.call([]), qui est un objet Array empruntant des méthodes sur l'objet Object.
Syntaxe fun.call(thisArg[, arg1[, arg2[, ...]]])
cetArg
La valeur this spécifiée lorsque la fonction fun est en cours d'exécution. Ce à quoi vous devez faire attention, ce sont les situations suivantes
(1) Ne pas transmettre, ou transmettre null ou undefined. Ceci dans la fonction pointe vers l'objet fenêtre
.
(2) Passez le nom de fonction d'une autre fonction. Ceci dans la fonction pointe vers une référence à cette fonction, qui n'est pas nécessairement la vraie valeur lorsque la fonction est exécutée
(3) Celui dont la valeur est une valeur primitive (nombre, chaîne, valeur booléenne) pointera vers l'objet de packaging automatique de la valeur primitive, tel que String, Number, Boolean
(4) Passez un objet, et ceci dans la fonction pointe vers cet objet
arg1, arg2, ...
La liste de paramètres spécifiée.
Exemple
Exemple d'application élémentaire
function a(){ //输出函数a中的this对象 console.log(this); } //定义函数b function b(){} var obj = {name:'这是一个屌丝'}; //定义对象obj a.call(); //window a.call(null); //window a.call(undefined);//window a.call(1); //Number a.call(''); //String a.call(true); //Boolean a.call(b);// function b(){} a.call(obj); //Object
Utilisez la méthode call pour appeler une fonction anonyme et précisez-la du contexte
Dans l'exemple suivant, lorsque la méthode greet est appelée, la valeur this de la méthode sera liée à l'objet i.
function greet() { var reply = [this.person, '是一个轻量的', this.role].join(' '); console.log(reply); } var i = {function greet() { var reply = [this.person, '是一个轻量的', this.role].join(' '); console.log(reply); } var i = { person: 'JSLite.io', role: 'Javascript 库。' }; greet.call(i); // JSLite.io 是一个轻量的 Javascript 库。 person: 'JSLite.io', role: 'Javascript 库。' }; greet.call(i); // JSLite.io 是一个轻量的 Javascript 库。
Utilisez la méthode call pour appeler des fonctions anonymes
Dans le corps de la boucle for de l'exemple suivant, nous créons une fonction anonyme, puis exécutons la fonction anonyme en appelant la méthode d'appel de la fonction, en utilisant chaque élément du tableau comme valeur spécifiée. L'objectif principal de cette fonction anonyme est d'ajouter une méthode d'impression à chaque objet élément du tableau. Cette méthode d'impression peut imprimer le numéro d'index correct de chaque élément du tableau. Bien entendu, il n'est pas nécessaire de transmettre les éléments du tableau dans la fonction anonyme avec cette valeur (les paramètres normaux suffisent). Le but est de démontrer l'utilisation de call.
var animals = [ {species: 'Lion', name: 'King'}, {species: 'Whale', name: 'Fail'} ]; for (var i = 0; i < animals.length; i++) { (function (i) { this.print = function () { console.log('#' + i + ' ' + this.species + ': ' + this.name); } this.print(); }).call(animals[i], i); } //#0 Lion: King //#1 Whale: Fail
Utilisez la méthode call pour appeler une fonction et transmettre des paramètres
var a = { name:'JSLite.io', //定义a的属性 say:function(){ //定义a的方法 console.log("Hi,I'm function a!"); } }; function b(name){ console.log("Post params: "+ name); console.log("I'm "+ this.name); this.say(); } b.call(a,'test'); //Post params: test //I'm onepixel //I'm function a!
postuler()
La syntaxe est presque identique à celle de la méthode call(), la seule différence est que le deuxième paramètre de apply doit être un tableau (ou un objet de type tableau) contenant plusieurs paramètres. Cette fonctionnalité d'application est très importante,
Lorsque vous appelez une fonction existante, vous pouvez spécifier un objet this pour celle-ci. this fait référence à l'objet actuel, qui est l'objet qui appelle cette fonction. En utilisant apply, vous pouvez écrire la méthode une fois, puis en hériter dans un autre objet, sans avoir à écrire la méthode à plusieurs reprises dans le nouvel objet.
Syntaxe : fun.apply(thisArg[, argsArray])
Remarque : Il est important de noter que Chrome 14 et Internet Explorer 9 n'acceptent toujours pas les objets de type tableau. Si des objets de type tableau sont transmis, ils lèveront une exception.
Paramètres
cetArg
Identique au paramètre thisArg de l'appel ci-dessus.
argsArray
Un tableau ou un objet de type tableau, dont les éléments du tableau seront transmis en tant que paramètres distincts à la fonction fun. Si la valeur de ce paramètre est nulle ou indéfinie, cela signifie qu'aucun paramètre ne doit être transmis. À partir d'ECMAScript 5, des objets de type tableau sont disponibles.
Exemple
function jsy(x,y,z){ console.log(x,y,z); } jsy.apply(null,[1,2,3]); // 1 2 3
Exemple d'utilisation du constructeur Appliquer au lien
Vous pouvez utiliser apply pour lier un constructeur à un objet, similaire à Java. Dans l'exemple suivant, nous allons créer une fonction de fonction globale appelée construct pour vous permettre d'utiliser un objet de type tableau dans le constructeur plutôt qu'une liste de paramètres. .
Function.prototype.construct = function(aArgs) { var fConstructor = this, fNewConstr = function() { fConstructor.apply(this, aArgs); }; fNewConstr.prototype = fConstructor.prototype; return new fNewConstr(); }; function MyConstructor () { for (var nProp = 0; nProp < arguments.length; nProp++) { console.log(arguments,this) this["property" + nProp] = arguments[nProp]; } } var myArray = [4, "Hello world!", false]; var myInstance = MyConstructor.construct(myArray); console.log(myInstance.property1); // logs "Hello world!" console.log(myInstance instanceof MyConstructor); // logs "true" console.log(myInstance.constructor); // logs "MyConstructor"
Utiliser les fonctions d'application et intégrées
L'utilisation intelligente de l'application vous permet d'utiliser des fonctions intégrées dans certaines tâches qui seraient autrement écrites sous forme d'itération sur des variables de tableau. Dans l'exemple suivant, nous utiliserons Math.max/Math.min pour trouver la valeur maximale/minimale dans un tableau.
//里面有最大最小数字值的一个数组对象 var numbers = [5, 6, 2, 3, 7]; /* 使用 Math.min/Math.max 在 apply 中应用 */ var max = Math.max.apply(null, numbers); // 一般情况是用 Math.max(5, 6, ..) 或者 Math.max(numbers[0], ...) 来找最大值 var min = Math.min.apply(null, numbers); //通常情况我们会这样来找到数字的最大或者最小值 //比对上面的栗子,是不是下面的看起来没有上面的舒服呢? max = -Infinity, min = +Infinity; for (var i = 0; i < numbers.length; i++) { if (numbers[i] > max) max = numbers[i]; if (numbers[i] < min) min = numbers[i]; }
Le tableau de paramètres est découpé en morceaux et passé en boucle
function minOfArray(arr) { var min = Infinity; var QUANTUM = 32768; for (var i = 0, len = arr.length; i < len; i += QUANTUM) { var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len))); console.log(submin, min) min = Math.min(submin, min); } return min; } var min = minOfArray([5, 6, 2, 3, 7]);
lier
La fonction bind() crée une nouvelle fonction (appelée fonction liée)
bind est une nouvelle méthode dans ES5
Passer des paramètres est similaire à appeler ou postuler
La fonction correspondante ne sera pas exécutée, call ou apply exécutera automatiquement la fonction correspondante
Renvoie une référence à la fonction
Syntaxe fun.bind(thisArg[, arg1[, arg2[, ...]]])
L'exemple suivant : lorsqu'un utilisateur clique sur une page Web, EventClick est déclenché et exécuté, et JSLite.io p1 p2 est généré, indiquant que cela dans EventClick a été transformé en objet obj par liaison. Si vous modifiez EventClick.bind(obj,'p1','p2') en EventClick.call(obj,'p1','p2'), la page affichera directement JSLite.io p1 p2
var obj = {name:'JSLite.io'}; /** * 给document添加click事件监听,并绑定EventClick函数 * 通过bind方法设置EventClick的this为obj,并传递参数p1,p2 */ document.addEventListener('click',EventClick.bind(obj,'p1','p2'),false); //当点击网页时触发并执行 function EventClick(a,b){ console.log( this.name, //JSLite.io a, //p1 b //p2 ) } // JSLite.io p1 p2
Compatible
if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { // closest thing possible to the ECMAScript 5 // internal IsCallable function throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, // this在这里指向的是目标函数 fNOP = function () {}, fBound = function () { return fToBind.apply(this instanceof fNOP ? this //此时的this就是new出的obj : oThis || this,//如果传递的oThis无效,就将fBound的调用者作为this //将通过bind传递的参数和调用时传递的参数进行合并,并作为最终的参数传递 aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; //将目标函数的原型对象拷贝到新函数中,因为目标函数有可能被当作构造函数使用 fBound.prototype = new fNOP(); //返回fBond的引用,由外部按需调用 return fBound; }; }
应用场景:继承
function Animal(name,weight){ this.name = name; this.weight = weight; } function Cat(){ // 在call中将this作为thisArgs参数传递 // Animal方法中的this就指向了Cat中的this // 所以Animal中的this指向的就是cat对象 // 在Animal中定义了name和weight属性,就相当于在cat中定义了这些属性 // cat对象便拥有了Animal中定义的属性,从而达到了继承的目的 Animal.call(this,'cat','50'); //Animal.apply(this,['cat','50']); this.say = function(){ console.log("I am " + this.name+",my weight is " + this.weight); } } //当通过new运算符产生了cat时,Cat中的this就指向了cat对象 var cat = new Cat(); cat.say(); //输出=> I am cat,my weight is 50
原型扩展
在原型函数上扩展和自定义方法,从而不污染原生函数。例如:我们在 Array 上扩展一个 forEach
function test(){ // 检测arguments是否为Array的实例 console.log( arguments instanceof Array, //false Array.isArray(arguments) //false ); // 判断arguments是否有forEach方法 console.log(arguments.forEach); // undefined // 将数组中的forEach应用到arguments上 Array.prototype.forEach.call(arguments,function(item){ console.log(item); // 1 2 3 4 }); } test(1,2,3,4);