Voici deux implémentations de uncurring
Atteindre 1
Function.prototype.uncurrying = function(){
var self = this;
return function(){
// 获取传入的上下文对象
var context = Array.prototype.shift.call(arguments);
// 这里的this是调用uncurrying者
return self.apply(context, arguments);
};
};
var push = Array.prototype.push.uncurrying ();
var arr = [];
push(arr, 1); // ==> arr = [1]
push(arr, 4); // ==> arr = [1, 4]
Atteindre 2
Function.prototype.uncurrying = function(){
var self = this;
return function(){
return Function.prototype.call.apply(self, arguments);
};
};
var push = Array.prototype.push.uncurrying ();
var arr = [];
push(arr, 1); // ==> arr = [1]
push(arr, 4); // ==> arr = [1, 4]
Les deux résultats sont les mêmes, mais je suis un peu confus quant à la deuxième méthode de mise en œuvre, principalement ici
第一种方式显示的用self,在这里也就是push方法执行了一下,
self.apply(context, arguments);
但是如下第二种实现方式,却没有发现self执行的痕迹,
按我的理解这里就是用apply修改call的上下文为self,这里也就是push,
但这样有执行push方法吗?难道call内部的实现帮忙执行了self?求解
Function.prototype.call.apply(self, arguments);
J'ai été instantanément cliqué par vous, merci !
louiszhai
Function.prototype.call.apply(self, arguments);
先用apply修改了call的上下文为self,
后续调用uncurrying,相当于在self上调用call方法,也就执行了self
Function.prototype.call.apply(self, arguments);
Cela semble un peu compliqué, mais c'est en fait facile à comprendre.En fait, votre deuxième implémentation peut également conduire à la troisième implémentation de l'anti-currying :
Function.prototype.call.apply(self, arguments);
这个看起来有些绕,其实很好理解。实际上,由你的第二种实现还可以推出反柯里化的第三种实现:
接下来我会先分析下你的第二种实现,再分析第三种实现。你的实现是这样的:
谁调用
uncurrying
,谁就等于this
或self
. 这意味着self
就是数组的push方法
.替换掉
self
,最终外部的push
等同如下函数:函数放在这里,我们先来理解
apply
函数,apply
有分解数组为一个个参数的作用。推导公式:
a.apply(b, arguments)
意味着把b当做this上下文,相当于是在b上调用a方法,并且传入所有的参数,如果b中本身就含有a方法,那么就相当于b.a(arg1, arg2,…)
公式1:
a.apply(b, arguments) === b.a(arg1, arg2,…)
由于
call
和apply
除参数处理不一致之外,其他作用一致,那么公式可以进一步演化得到:公式2:
a.call(b, arg) === b.a(arg)
将公式1这些代入上面的函数,有:
a = Function.prototype.call
即a等于call方法。我们接着代入公式,有:
b = Array.prototype.push
即b等于数组的push方法那么
Function.prototype.call.apply(Array.prototype.push, arguments)
就相对于:Array.prototype.push.call(arg1, arg2,…)
,那么:push([], 1)
就相当于Array.prototype.push.call([], 1)
,再代入公式2,相当于:[].push(1)
答案已经呼之欲出了,就是往数组中末尾添加数字1。
接下来我来分析反柯里化的第三种实现:
对于
this.call.bind(this);
部分,this
相当于Array.prototype.push
,那么整体等同于如下:Array.prototype.push.call.bind(Array.prototype.push)
这里的难点在于bind方法,bind的实现比较简单,如下:
想要理解必须化繁为简,理解得越简单,也就理解得越透彻。进一步简化
bind
的原理,等同于谁调用bind
,就返回一个新的function。我们假设函数
fn
调用bind
方法如fn.bind([1, 2])
,经过简化,忽略bind
绑定参数的部分,最终返回如下:以上,将
Ensuite, j'analyserai d'abord votre deuxième implémentation, puis j'analyserai votre troisième implémentation. Votre implémentation ressemble à ceci : 🎜 🎜Celui qui appellefn
替换为Array.prototype.push.call
,[1, 2]
替换为Array.prototype.push
uncurrying
sera égal àthis
ouself
. Cela signifie queself
est le tableau. La méthode push
.remplace
self
, et lepush
externe final est équivalent à la fonction suivante : 🎜 🎜La fonction est placée ici. Comprenons d'abord que la fonctionapply
a pour fonction de décomposer le tableau en paramètres. 🎜 🎜Formule de dérivation :a.apply(b, arguments)
signifie traiter b comme ce contexte, ce qui équivaut à appeler la méthode a sur b et à transmettre tous les paramètres. Si b lui-même contient une méthode, alors cela équivaut àb.a(arg1, arg2,…)
🎜 🎜Formule 1 :a.apply(b, arguments) === b.a(arg1, arg2,…)
🎜 🎜Étant donné quecall
etapply
ont le même effet, à l'exception d'un traitement des paramètres incohérent, la formule peut être encore évoluée pour obtenir : 🎜 🎜Formule 2 :a.call(b, arg) === b.a(arg)
🎜 🎜Remplacez la Formule 1 dans la fonction ci-dessus, il y a : 🎜 🎜a = Function.prototype.call
Autrement dit, a est égal à la méthode d'appel. 🎜 🎜On branche ensuite la formule, on a : 🎜 🎜b = Array.prototype.push
Autrement dit, b est égal à la méthode push du tableau🎜 🎜AlorsFunction.prototype.call.apply(Array.prototype.push, arguments)
est relatif à : 🎜 🎜Array.prototype.push.call(arg1, arg2,…)
, puis : 🎜 🎜push([], 1)
est équivalent àArray.prototype.push.call([], 1)
, puis remplacez-le par Formule 2 fort> , équivalent à : 🎜 🎜[].push(1)
🎜 🎜La réponse est déjà évidente : ajouter le chiffre 1 à la fin du tableau. 🎜🎜Ensuite, permettez-moi d'analyser la troisième implémentation de l'anti-currying : 🎜 🎜Pour la partie
this.call.bind(this);
,this
est équivalent àArray.prototype.push
, alors l'équivalent global est comme suit : 🎜 🎜Array.prototype.push.call.bind(Array.prototype.push)
🎜 🎜La difficulté ici réside dans la méthode bind. La mise en œuvre de bind est relativement simple, comme suit : 🎜 🎜Si vous voulez comprendre, vous devez simplifier le complexe. Plus vous comprenez simple, plus vous comprendrez en profondeur. Pour simplifier encore le principe debind
, cela équivaut à celui qui appellebind
renvoyant une nouvelle fonction. 🎜 🎜Nous supposons que la fonctionfn
appelle la méthodebind
telle quefn.bind([1, 2])
, qui est simplifiée et ignorebindLa partie qui lie les paramètres renvoie finalement comme suit : 🎜 rrreee 🎜Ci-dessus, remplacez
La différence réside dans la première moitié de
fn
parArray.prototype.push.call
et[1, 2]
parArray.prototype push.
, puis : 🎜
rrreeeArray.prototype.push.call.bind(Array.prototype.push)
sera équivalent à :Array.prototype.push.call.bind(Array.prototype.push)
将等同于:这个看起来和反柯里化的第二种实现有些不大相同,不要急,虽然表面上看起来不一致,但骨子里还是一致的。请耐心往下看:
不同的地方在于前半部分
rrreeeArray.prototype.push.call
,这里它是一个整体,实际上想代表的就是call方法。而我们都知道,所有函数的call方法,最终都是Function.prototype
的call
方法。那么,就有如下恒等式成立:那么以上函数将等同于:
rrreee褪去代入的参数,函数可还原为:
rrreee综上,最终反柯里化的第三种实现将和第二种实现完全一致,推理完毕,码字不易,喜欢的请点个赞谢谢~
为了加深对
Cela semble un peu différent de la deuxième implémentation de l'anti-currying. Ne vous inquiétez pas, même si cela semble incohérent en surface, c'est toujours cohérent au fond. Soyez patient et lisez ci-dessous :bind
rrreeeArray.prototype.push.call
, qui est ici un tout et représente en fait la méthode d'appel. Et nous savons tous que la méthode d'appel de toutes les fonctions est finalement la méthodecall
deFunction.prototype
. Alors, l'identité suivante est valable :rrreee
Alors la fonction ci-dessus sera équivalente à : 🎜 rrreee 🎜En supprimant les paramètres substitués, la fonction peut être restaurée à : 🎜 rrreee 🎜Pour résumer, la troisième implémentation finale de l'anti-currying sera tout à fait cohérente avec la deuxième implémentation. Le raisonnement est complet et le codage n'est pas facile Si vous l'aimez, n'hésitez pas à l'aimer et merci~. 🎜 🎜Afin d'approfondir ma compréhension dubind
et du currying, j'ai également écrit un blog pour les analyser en profondeur. 🎜 🎜Veuillez vous référer à Currying et Decurrying dans Functional Programming et Function.prototype.bind Method Guide. 🎜 🎜Les étudiants qui l’aiment peuvent également prêter attention au cours approfondi frontal de Lewis dans ma chronique🎜Bases
Les différences et les fonctions d'appel et de candidature ne seront pas décrites en détail
Appelez et appliquez l'implémentation du code source
.Ils sont très proches Ici, nous introduisons uniquement l'appel, par exemple : a.call(b, c)
Supprimez le premier paramètre x = b || {}
x.fn = a
Splice les paramètres sauf le premier paramètre, séparés par des virgules, le résultat est d
Créez une fonction e = new Function() dans un environnement d'exécution indépendant et exécutez x.fn(d) à l'intérieur de la fonction
Exécuter l'e créé
Compréhension de l'option 2
Le problème de l'appel et de l'application pour développer la méthode objet n'est pas pris en compte ici, car les méthodes seront créées dynamiquement à partir du code source, ce problème ne sera donc pas abordé en détail ci-dessous.
self pointe vers Array.prototype.push
(Function.prototype.call).apply(Array.prototype.push, arguments);
Utilisez le code source qui vient d'être expliqué et transformez 2 pour obtenir : Array.prototype.push.(Function.prototype.call)(arguments). Il doit également être converti ici. L'appel n'accepte pas un tableau, voir 4.
arguments est un objet de type tableau [arr, 1]. Transformez 3 pour obtenir : Array.prototype.push.(Function.prototype.call)(arr, 1)
Le code source de l'appel a été expliqué, alors changez 4 et obtenez arr.(Array.prototype.push)(1)
Écrivez-le mieux, arr.push(1)