Function.prototype.call.apply(self, 인수);좀 복잡해 보이지만 실제로는 이해하기 쉽습니다. 실제로 두 번째 구현은 커링 방지의 세 번째 구현으로 이어질 수도 있습니다. Function.prototype.call.apply(self, arguments);这个看起来有些绕,其实很好理解。 实际上,由你的第二种实现还可以推出反柯里化的第三种实现:
다음으로 두 번째 구현을 먼저 분석한 다음 세 번째 구현을 분석하겠습니다. 구현 내용은 다음과 같습니다. 🎜
으아아아
🎜uncurring을 호출하는 사람은 this 또는 self와 같습니다. 이는 self가 배열임을 의미합니다. 푸시 메소드. 는 self를 대체하며 최종 외부 push는 다음 함수와 동일합니다. 🎜
으아아아
🎜여기에 함수가 배치되어 있습니다. 먼저 apply 함수에 대해 알아보겠습니다. apply에는 배열을 매개변수로 분해하는 기능이 있습니다. 🎜
🎜파생 공식: a.apply(b, 인수)는 b를 이 컨텍스트로 처리한다는 의미입니다. 이는 b에서 a 메서드를 호출하고 모든 매개변수를 전달하는 것과 동일합니다. b 자체에 메서드가 포함되어 있으면 b.a(arg1, arg2,…)🎜와 동일합니다.
🎜수식 1: a.apply(b, 인수) === b.a(arg1, arg2,…)🎜
🎜 호출과 적용은 일관되지 않은 매개변수 처리를 제외하고 동일한 효과를 갖기 때문에 공식을 더욱 발전시켜 다음을 얻을 수 있습니다. 🎜
🎜공식 2: a.call(b, arg) === b.a(arg)🎜
🎜위 함수에 공식 1을 대입하면 다음과 같습니다. 🎜
🎜a = Function.prototype.call 즉, a는 호출 방법과 같습니다. 🎜
🎜그런 다음 공식을 대입하면 다음과 같습니다. 🎜
🎜b = Array.prototype.push 즉, b는 배열의 푸시 방법과 같습니다🎜
🎜그러면 Function.prototype.call.apply(Array.prototype.push, 인수)는 다음을 기준으로 합니다. 🎜
🎜Array.prototype.push.call(arg1, arg2,…), 다음: 🎜
🎜push([], 1)는 Array.prototype.push.call([], 1)과 동일하며 이를 수식 2로 대체합니다. Strong> , 다음과 동일: 🎜
🎜[].push(1)🎜
🎜답은 이미 명확합니다. 배열 끝에 숫자 1을 추가하는 것입니다. 🎜
🎜다음으로 안티커링의 세 번째 구현을 분석하겠습니다. 🎜
🎜this.call.bind(this); 부분의 경우 this는 Array.prototype.push와 동일하며 전체적으로 동일합니다. 다음과 같습니다: 🎜
🎜Array.prototype.push.call.bind(Array.prototype.push)🎜
🎜여기서 어려운 점은 바인딩 방법에 있습니다. 바인딩의 구현은 다음과 같이 비교적 간단합니다.
으아아아
🎜이해하고 싶다면 복잡한 것을 단순화해야 합니다. 간단하게 이해할수록 더 철저하게 이해할 수 있습니다. bind의 원리를 더욱 단순화하기 위해 bind를 호출하는 사람이 새 함수를 반환하는 것과 동일합니다. 🎜
🎜우리는 fn 함수가 fn.bind([1, 2])와 같은 bind 메서드를 호출한다고 가정합니다. 이는 단순화되고 무시됩니다. bind매개변수를 바인딩하는 부분은 최종적으로 다음과 같이 반환됩니다. 🎜
으아아아
🎜위에서 fn을 Array.prototype.push.call로 바꾸고 [1, 2]를 Array.prototype push로 바꿉니다. , 다음: 🎜
Array.prototype.push.call.bind(Array.prototype.push)는 다음과 같습니다. Array.prototype.push.call.bind(Array.prototype.push) 将等同于:
두 번째 안티 커링 구현과는 조금 달라 보이지만 걱정하지 마세요. 표면적으로는 일관성이 없어 보이지만 핵심은 여전히 일관성이 있습니다. 인내심을 갖고 아래 내용을 읽어주세요:
차이점은 Array.prototype.push.call의 전반부에 있는데, 이는 여기서 전체이고 실제로 호출 방법을 나타냅니다. 그리고 우리 모두는 모든 함수의 호출 메소드가 궁극적으로 Function.prototype의 call 메소드라는 것을 알고 있습니다. 그러면 다음과 같은 신원이 성립됩니다:
으아아아
그러면 위 함수는 다음과 같습니다. 🎜
으아아아
🎜대체된 매개변수가 없으면 기능을 다음 위치로 복원할 수 있습니다.🎜
으아아아
🎜결론적으로 안티 커링의 마지막 세 번째 구현은 두 번째 구현과 완전히 일치하게 됩니다. 마음에 드셨다면 좋아요를 눌러주세요~ 🎜
🎜바인드와 커링에 대한 이해를 심화하기 위해 블로그에도 작성하여 심층적으로 분석했습니다. 🎜
🎜함수형 프로그래밍의 커링 및 디커링 및 Function.prototype.bind 메서드 가이드를 참조하세요. 🎜
🎜좋아하는 학생들은 내 칼럼 루이스의 프론트엔드 심층 강좌도 따라갈 수 있습니다🎜
Function.prototype.call.apply(self, 인수);
좀 복잡해 보이지만 실제로는 이해하기 쉽습니다.실제로 두 번째 구현은 커링 방지의 세 번째 구현으로 이어질 수도 있습니다.
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
绑定参数的部分,最终返回如下:以上,将
다음으로 두 번째 구현을 먼저 분석한 다음 세 번째 구현을 분석하겠습니다. 구현 내용은 다음과 같습니다. 🎜 으아아아 🎜fn
替换为Array.prototype.push.call
,[1, 2]
替换为Array.prototype.push
으아아아uncurring
을 호출하는 사람은this
또는self
와 같습니다. 이는self
가배열임을 의미합니다. 푸시 메소드
.는
self
를 대체하며 최종 외부push
는 다음 함수와 동일합니다. 🎜 으아아아 🎜여기에 함수가 배치되어 있습니다. 먼저apply
함수에 대해 알아보겠습니다.apply
에는 배열을 매개변수로 분해하는 기능이 있습니다. 🎜 🎜파생 공식:a.apply(b, 인수)
는 b를 이 컨텍스트로 처리한다는 의미입니다. 이는 b에서 a 메서드를 호출하고 모든 매개변수를 전달하는 것과 동일합니다. b 자체에 메서드가 포함되어 있으면b.a(arg1, arg2,…)
🎜와 동일합니다. 🎜수식 1:a.apply(b, 인수) === b.a(arg1, arg2,…)
🎜 🎜호출
과적용
은 일관되지 않은 매개변수 처리를 제외하고 동일한 효과를 갖기 때문에 공식을 더욱 발전시켜 다음을 얻을 수 있습니다. 🎜 🎜공식 2:a.call(b, arg) === b.a(arg)
🎜 🎜위 함수에 공식 1을 대입하면 다음과 같습니다. 🎜 🎜a = Function.prototype.call
즉, a는 호출 방법과 같습니다. 🎜 🎜그런 다음 공식을 대입하면 다음과 같습니다. 🎜 🎜b = Array.prototype.push
즉, b는 배열의 푸시 방법과 같습니다🎜 🎜그러면Function.prototype.call.apply(Array.prototype.push, 인수)
는 다음을 기준으로 합니다. 🎜 🎜Array.prototype.push.call(arg1, arg2,…)
, 다음: 🎜 🎜push([], 1)
는Array.prototype.push.call([], 1)
과 동일하며 이를 수식 2로 대체합니다. Strong> , 다음과 동일: 🎜 🎜[].push(1)
🎜 🎜답은 이미 명확합니다. 배열 끝에 숫자 1을 추가하는 것입니다. 🎜 🎜다음으로 안티커링의 세 번째 구현을 분석하겠습니다. 🎜 🎜this.call.bind(this);
부분의 경우this
는Array.prototype.push
와 동일하며 전체적으로 동일합니다. 다음과 같습니다: 🎜 🎜Array.prototype.push.call.bind(Array.prototype.push)
🎜 🎜여기서 어려운 점은 바인딩 방법에 있습니다. 바인딩의 구현은 다음과 같이 비교적 간단합니다. 으아아아 🎜이해하고 싶다면 복잡한 것을 단순화해야 합니다. 간단하게 이해할수록 더 철저하게 이해할 수 있습니다.bind
의 원리를 더욱 단순화하기 위해bind
를 호출하는 사람이 새 함수를 반환하는 것과 동일합니다. 🎜 🎜우리는fn
함수가fn.bind([1, 2])
와 같은bind
메서드를 호출한다고 가정합니다. 이는 단순화되고 무시됩니다.bind매개변수를 바인딩하는 부분은 최종적으로 다음과 같이 반환됩니다. 🎜 으아아아 🎜위에서
차이점은
fn
을Array.prototype.push.call
로 바꾸고[1, 2]
를Array.prototype push로 바꿉니다.
, 다음: 🎜Array.prototype.push.call.bind(Array.prototype.push)
는 다음과 같습니다.Array.prototype.push.call.bind(Array.prototype.push)
将等同于:这个看起来和反柯里化的第二种实现有些不大相同,不要急,虽然表面上看起来不一致,但骨子里还是一致的。请耐心往下看:
不同的地方在于前半部分
Array.prototype.push.call
,这里它是一个整体,实际上想代表的就是call方法。而我们都知道,所有函数的call方法,最终都是Function.prototype
的call
方法。那么,就有如下恒等式成立:那么以上函数将等同于:
褪去代入的参数,函数可还原为:
综上,最终反柯里化的第三种实现将和第二种实现完全一致,推理完毕,码字不易,喜欢的请点个赞谢谢~
为了加深对
두 번째 안티 커링 구현과는 조금 달라 보이지만 걱정하지 마세요. 표면적으로는 일관성이 없어 보이지만 핵심은 여전히 일관성이 있습니다. 인내심을 갖고 아래 내용을 읽어주세요:bind
으아아아Array.prototype.push.call
의 전반부에 있는데, 이는 여기서 전체이고 실제로 호출 방법을 나타냅니다. 그리고 우리 모두는 모든 함수의 호출 메소드가 궁극적으로Function.prototype
의call
메소드라는 것을 알고 있습니다. 그러면 다음과 같은 신원이 성립됩니다:으아아아
그러면 위 함수는 다음과 같습니다. 🎜 으아아아 🎜대체된 매개변수가 없으면 기능을 다음 위치로 복원할 수 있습니다.🎜 으아아아 🎜결론적으로 안티 커링의 마지막 세 번째 구현은 두 번째 구현과 완전히 일치하게 됩니다. 마음에 드셨다면 좋아요를 눌러주세요~ 🎜 🎜바인드
와 커링에 대한 이해를 심화하기 위해 블로그에도 작성하여 심층적으로 분석했습니다. 🎜 🎜함수형 프로그래밍의 커링 및 디커링 및 Function.prototype.bind 메서드 가이드를 참조하세요. 🎜 🎜좋아하는 학생들은 내 칼럼 루이스의 프론트엔드 심층 강좌도 따라갈 수 있습니다🎜기본
호출과 적용의 차이점과 기능은 자세히 설명하지 않겠습니다
소스 코드 구현 호출 및 적용
여기에서는 호출만 소개합니다. 예: a.call(b, c)
첫 번째 매개변수 x = b ||
입니다.
객체 메서드를 확장하기 위한 호출 및 적용 문제는 여기에서 고려하지 않습니다. 메서드는 소스 코드에서 동적으로 생성되므로 이 문제는 아래에서 자세히 설명하지 않습니다. 으아아아
self는 Array.prototype.push (Function.prototype.call).apply(Array.prototype.push, 인수);
방금 설명한 소스 코드를 사용하여 2를 변환하고 Array.prototype.push.(Function.prototype.call)(인수)를 가져옵니다. 또한 여기서 호출은 배열이 아닌 변환이 필요합니다. 4를 참조하세요.
arguments는 배열과 유사한 객체 [arr, 1]입니다. 3을 변환하면 Array.prototype.push.(Function.prototype.call)(arr, 1)
call의 소스코드가 설명되어 있으니 4번을 변경하고 arr을 받으세요.(Array.prototype.push)(1)
더 잘 써주세요, arr.push(1)
를 가리킵니다.