JavaScript 반 코 리 화
24985 단어 JavaScript
코 리 화
커 리 화 는 부분 적 인 값 을 구 하 는 것 이 라 고도 부 르 는데 그 의 미 는 함수 에 단계별 로 파 라 메 터 를 전달 하 는 것 이다. 매번 파 라 메 터 를 전달 한 후에 파 라 메 터 를 응용 하고 더욱 구체 적 인 함수 로 돌아 가 남 은 파 라 메 터 를 받 아들 이 는 것 이다. 이 중간 에 다 층 과 같은 일부 매개 변수 함 수 를 삽입 하여 마지막 결 과 를 되 돌 릴 수 있다.따라서 코 리 화의 과정 은 점차적으로 인삼 을 전달 하고 함수 의 적용 범 위 를 점차적으로 좁 히 며 점차적으로 해답 을 구 하 는 과정 이다.제 다른 블 로 그 를 만 나 보 세 요. 자 바스 크 립 트 의 함수 currying 코 리 화 분석
반 코 리 화
반면, 반 코 리 화 작용 은 함수 의 적용 성 을 확대 하여 원래 특정 대상 으로 가지 고 있 던 기능 의 함 수 를 임 의 대상 에 게 사용 할 수 있 도록 한다. 즉, 다음 과 같은 주어진 함수 에 서명 하 는 것 이다.
obj.func(arg1, arg2)
함수 형식 으로 전환 하여 다음 과 같이 서명 합 니 다.
func(obj, arg1, arg2)
이것 이 바로 반 코 리 화의 형식화 묘사 다.
물론 전제 가 있 습 니 다. 함수 y 는 언어 적 으로 오리 유형 을 지원 하고 위 키 오리 유형 에 서 는 대상 의 유형 자체 가 아니 라 어떻게 사용 하 는 지 에 주목 하고 있다.오리 유형의 언어 를 사용 할 때, 이러한 함 수 는 임의의 유형의 대상 을 받 아들 일 수 있 으 며, 그것 의 걷 기와 부 르 는 방법 을 호출 할 수 있다. 에서 인용 해 야 합 니 다.
예 를 들 어 다음 의 간단 한 실현:
Function.prototype.uncurrying = function() { var that = this; return function() { return Function.prototype.call.apply(that, arguments); } }; function sayHi () { return "Hello " + this.value +" "+[].slice.call(arguments); } var sayHiuncurrying=sayHi.uncurrying(); console.log(sayHiuncurrying({value:'world'},"hahaha"));
설명:
uncurrying
는 Function
에 정 의 된 prototype
방법 이기 때문에 모든 함수 에 이 방법 을 사용 할 수 있다.호출 시: sayHiuncurrying=sayHi.uncurrying()
그래서 uncurrying
중의 this
함 수 를 가리 키 는 것 입 니 다.(일반 원형 방법 중의 sayHi
은 원형 대상 this
을 가리 키 는 것 이 아니 라 호출 대상 을 가리 키 는 것 이다. 여기 서 호출 대상 은 다른 함수 이 고 자바 script 에서 함수 도 대상 이다) prototype
call.apply(that, arguments)
를 that
방법의 문맥 로 설정 한 다음 에 call
을 arguments
l 방법 에 전달 하고 앞의 예, cal
실제 가리 키 기 때문에 호출 that
은 sayHi
에 해당 한다.sayHiuncurrying(arg1, arg2, ...)
, sayHi.call(arg1, arg2, ...)
함 수 는 sayHi.call(arg1, arg2, ...)
를 call
의 상하 문 으로 간주 하고 arg1
등 남 은 매개 변 수 를 sayHi 에 게 전달 하기 때문에 마지막 으로 sayHi
에 해당 한다.arg2,...
는 arg1.sayHi(arg2,...)
과 같다.마지막 으로 우리 가 거꾸로 보면 사실은 반 코 리 화 는 원래
sayHiuncurrying(obj,args)
의 형식 을 obj.sayHi(args)
으로 전환 시 켜 sayHi(args)
의 사용 범 위 를 일반화 시 킨 것 과 같다.더욱 추상 적 으로 표현 하면 sayHiuncurrying(obj,args)
반 코 리 화 는 원래 sayHi
호출 을 uncurryinging
형식의 호출 으로 전환 할 수 있다.x '가 x 또는 다른 대상 이 라 고 가정 하면 함수 의 사용 범 위 를 확대 한다.통용 반 코 리 화 함수
위의 예 에서
x.y(z)
을 y(x',z)
에 썼 는데 이것 은 그다지 좋 지 않다. 우 리 는 사실 uncurrying
을 하나의 함수 로 포장 할 수 있다.var uncurrying= function (fn) { return function () { var args=[].slice.call(arguments,1); return fn.apply(arguments[0],args); } };
위의 이 함 수 는 매우 뚜렷 하고 직접적 이다.사용 시 호출
prototype
하고 기 존 함수 uncurrying
를 전송 합 니 다. 반 코 리 화 함 수 는 새로운 함 수 를 되 돌려 줍 니 다. 이 새 함수 가 받 은 첫 번 째 실 삼 은 uncurrying
의 문맥 로 연결 되 고 다른 매개 변 수 는 fn
에 매개 변수 로 전 달 됩 니 다.따라서 반 코 리 화 에 대한 더욱 통속 적 인 해석 은 함수 의 차용 일 수 있 고 함수 가 다른 대상 을 받 아들 일 수 있 으 며 차용 범 화 를 통 해 함수 의 사용 범 위 를 확대 할 수 있다.
그래서
fn
더 흔히 볼 수 있 는 용법 은 자 바스 크 립 트 에 내 장 된 다른 방법 에 대한 차출 이다.텍스트 설명 이 비교적 복잡 합 니까? 아니면 코드 를 계속 보 시 겠 습 니까?
var test="a,b,c"; console.log(test.split(",")); var split=uncurrying(String.prototype.split); //[ 'a', 'b', 'c' ] console.log(split(test,',')); //[ 'a', 'b', 'c' ]
this
에 게 fn
구체 적 인 uncurrying
, 즉 split=uncurrying(String.prototype.split)
, uncurrying
함수 에 fn
기능 을 가 집 니 다. 함수 호출 String.prototype.split
시 들 어 오 는 첫 번 째 매개 변 수 는 split
실 행 된 문맥 이 고 나머지 매개 변 수 는 원 String.prototype.split
함수 에 전달 되 는 것 과 같 습 니 다.예 를 하나 더 보 자.
var $ = {}; console.log($.push); // undefined var pushUncurrying = uncurrying(Array.prototype.push); $.push = function (obj) { pushUncurrying(this,obj); }; $.push('first'); console.log($.length); // 1 console.log($[0]); // first console.log($.hasOwnProperty('length')); // true
'jquery 라 이브 러 리 유사' 가 실 현 될 때 Array 를 빌 리 는
split(test,',')
방법 을 모방 했다.우 리 는 대상 이 split
방법 이 없다 는 것 을 알 고 있 기 때문에 String.prototype.split
되 돌아 가기 push
는 push
를 빌려 처리 할 수 있 고 console.log(obj.push)
원생 의 배열 방법 (js 엔진) 으로 위조 배열 대상 의 length 속성 과 배열 구성원 을 유지 할 수 있다.같은 이치 로 우 리 는 계속 있 을 수 있다.
var indexof=uncurrying(Array.prototype.indexOf); $.indexOf = function (obj) { return indexof(this,obj); }; $.push("second"); console.log($.indexOf('first')); // 0 console.log($.indexOf('second')); // 1 console.log($.indexOf('third')); // -1
예 를 들 어 우리 가 자신의 라 이브 러 리 를 실현 할 때 어떤 방법 이 원생 과 유사 하 다 면
undefined
원생 방법 을 빌려 쓸 수 있다.우 리 는
Array
방법 push
도 할 수 있다. 예 를 들 어:var call= uncurrying(Function.prototype.call); var fn= function (str) { console.log(this.value+str); }; var obj={value:"Foo "}; call(fn, obj,"Bar!"); // Foo Bar!
이렇게 하면 함수 도 일반적인 '데이터' 로 사용 할 수 있 고 함수 식 프로 그래 밍 이 있어 서 일부 라 이브 러 리 에서 이런 용법 을 자주 볼 수 있다.
유 니 버 설 uncurrying 함수 의 진격
위의
uncurrying
함 수 는 사고방식 에 비교적 부합 되 고 이해 하기 쉬 운 버 전 입 니 다. 다음 에 들 어가 서 몇 가지 다른 버 전 을 보 겠 습 니 다.우선, B 칸 이 조금 높 으 면
Function.prototype.call/apply
도 이렇게 쓸 수 있 습 니 다.var uncurrying= function (fn) { return function () { var context=[].shift.call(arguments); return fn.apply(context,arguments); } };
물론 B 칸 을 더 올 려 야 한다 면 그 럴 수도 있 습 니 다.
var uncurrying= function (fn) { return function () { return Function.prototype.call.apply(fn,arguments); } };
시작 하 는 split 의 예 를 들 어 위의 고 B 격 함수 가 어떻게 작 동 하 는 지 보 세 요.
uncurring
uncurrying
uncurrying
var split=uncurrying(String.prototype.split);
, fn 은 split(test,',');
의 문맥 에 응 용 된 다음 에 새로운 함수 에 봉 하여 되 돌려 줍 니 다.String.prototype.split
, 호출 시 fn
, Function.prototype.call
split
split(test,',')
, arguments
call [test,',']
fn. call (arguments) fn
Function. prototype. split. call (test, ',') 'apply
대상 은 ,
의 문맥 로 설정 되 었 고 나머지 매개 변수 ,
는 test
함수 이 를 통 해 알 수 있 듯 이
Function.prototype.split
는 ','
에 비해 응용 split
한 후에 자동 으로 Function.prototype.call.apply(fn,arguments)
을 첫 번 째 매개 변수 와 나머지 매개 변수 로 나 누 어 각각 응용 하 는 것 과 같다.앞의 두 가지 표기 법 이 첫 번 째 매개 변 수 를 분리 하 는 절 차 를 줄 였 다.자, B 칸 의 향상 을 추구 하 는 길 은 끝 이 없다. 그러면 지금 은 절정 에 이 르 렀 다.
var uncurrying=Function.prototype.bind.bind(Function.prototype.call);
나 는 이 코드 를 처음 보 았 을 때 바로 어 지 러 워 서 감탄 을 금치 못 했다. 과연 자 바스 크 립 트 의 각종 기예 가 음탕 하구 나!!
How it works!
이 몇 개의 영어 단 어 를 많이 봤 군요. 하하, 다시 한 번 말씀 드 리 겠 습 니 다. 어떻게 일 하 는 지 보 겠 습 니 다.
여기 서 함수 의 두 가지 원형 방법
fn.apply(arguments[0],args)
을 사 용 했 습 니 다. call
이 두 함수 arguments 는 두 부분 으로 분해 할 수 있 습 니 다. 첫 번 째 매개 변 수 는 모두 함수 로 설정 되 어 문맥 을 집행 하 는 데 사 용 됩 니 다. 나머지 매개 변 수 는 호출 함수 에 전 달 됩 니 다. 다른 점 은 arguments
즉시 응용 되 고 모든 매개 변 수 는 한 번 에 전 달 됩 니 다.그러나 Function.prototype.call
남 은 매개 변 수 는 호출 함수 에 순서대로 들 어 오고 실행 을 지연 시 킵 니 다. 그래서 Function.prototype.bind
는 코 리 화 된 것 입 니 다. 아, 멀 어 졌 습 니 다. 그러나 어쨌든 arguments 를 두 부분 으로 나 누 면 그들의 코드 는 이렇게 보 입 니 다.Function.prototype.call= function (scope,...args) { // ECMAScript 6 ... }; Function.prototype.bind= function (scope,...args) { // ECMAScript 6 ... };
우선, 우 리 는
call
에서 자신 을 상 향 조정 할 수 있 습 니 다. bind
은 하나의 함수 이기 때문에 원형 함수 bid 를 호출 할 수 있 습 니 다. 이것 은 우리 가 bind
의 두 번 째 Function.prototype.bind
에 무엇 을 전달 하 든 첫 번 째 Function.prototype.bind
함수 의 첫 번 째 매개 변수 Function.prototype.bind.bind()
라 고 부 르 는 것 을 의미 합 니 다.var uncurrying=Function.prototype.bind.bind(Function.prototype.call);
다음으로 전환:
var uncurrying= function(){ return Function.prototype.bind.apply(Function.prototype.call) }
... 과 같다
var uncurrying= function (fn) { return Function.prototype.call.bind(fn); };
여기 서
bind
인상 용 bind
, 우 리 는 bid 가 바 인 딩 되 고 새로운 함수 로 돌아 갈 것 이라는 것 을 알 고 있 습 니 다.,이것 은 다음 과 같다.
var uncurrying= function (fn) { return function(scope,...args){ return fn.call(scope,...args); } };
ECMAScript 6 에서
scope
나머지 인 자 를 가 져 오 겠 다 고 표 시 했 습 니 다. 이제 ES6 에 의존 하지 않도록 다시 쓰 겠 습 니 다.var uncurrying= function (fn) { return function(){ var args=[].slice.call(arguments,1); return fn.apply(arguments[0],args); } };
아하, 우 리 는 지금 돌 아 왔 습 니 다. 위의 함 수 는 이미 앞의 '통용 반 코 리 화 함수' 와 같 습 니 다.
그리고 우 리 는 지금 앞으로 나 아 간다.
var bind = Function.prototype.bind; uncurryThis = bind.bind(bind.call); call = uncurryThis(bind.call);
상기 코드 의 작용 은
call
에 대해 반 코 리 화 를 하 는 것 으로 알 수 있 듯 이 이것 은 바로 앞의 고 B 격 서법 의 변형 이다.마지막 으로 코드 를 한 소절 더 보 겠 습 니 다.
var bind = Function.prototype.call.bind(Function.prototype.bind);
아아, 이 코드 도 뼈 가 놀 라 워 보이 고 용모 가 비범 해 보이 는데..
우 리 는 그것 을 계속 읽 을 수 있 는 버 전 으로 바 꾸 었 다.
var bind = Function.prototype.call.bind(Function.prototype.bind); // var bind= function (scope) { return function () { return scope.call(arguments); } }; // , scope Function.prototype.bind var bind= function () { return Function.prototype.bind.call(arguments); }; // , bind bind(func, scope), , var bind= function (func,scope) { return Function.prototype.bind.call(func,scope); }; // var bind= function (func,scope) { return func.bind(scope); };
테스트 코드:
var bind = Function.prototype.call.bind(Function.prototype.bind); var context={foo:"bar"}; function returnFoo(){ return this.foo; } var amazing=bind(returnFoo,context); console.log(amazing()); // bar // var bind2= function (func,scope) { return func.bind(scope); }; var amazing2=bind2(returnFoo,context); console.log(amazing2()); // bar
위의 테스트 코드 는 원래
bind
와 우리 가 바 꾼 코드 를 호출 하고 테스트 결 과 는 모두 같은 bar 로 되 돌려 줍 니 다.이 글 은 여기까지 쓴 지 이미 오래 되 었 습 니 다. 친구 가 여 기 를 볼 수 있 을 지 모 르 겠 습 니 다.) 다음 에 마지막 으로 하나 더 보충 하 겠 습 니 다. 그 뜻 은?
var slice = Function.prototype.call.bind(Array.prototype.slice);
이것 은 말 그대로
...
를 Function.prototype.call
에 연결 시 키 고 전환 과정 을 알 수 있다.var slice2= function(){ return Function.prototype.call.apply(Array.prototype.slice); }; var slice2=function(fn) { return Array.prototype.slice.call(fn); }; var slice2=function() { return Array.prototype.slice.call(arguments[0],arguments[1],arguments[2]); };
테스트 코드:
var slice = Function.prototype.call.bind(Array.prototype.slice); console.log(slice([1,2,3],0,1)); // [ 1 ] console.log(slice2([1,2,3],0,1)); // [ 1 ] console.log(Array.prototype.slice.call([1,2,3],0,1)); // [ 1 ]
이것 도
var bind = Function.prototype.call.bind(Function.prototype.bind);
, call
, Array.prototype.slice
세 가지 방법 에 대해 많은 연습 을 한 셈 이다. 이 세 가지 방법 은 자 바스 크 립 트 함수 식 스타일 의 중요 한 기초 이다. 어린이 신발 들 이 상기 고 B 격 문 구 를 포장 하고 바 꿀 때 함수 변환 수학 문 제 를 풀 수 있 는 방법 이 있다.원문:http://www.cnblogs.com/zztt/p/4152147.html
참고 자료: 자 바스 크 립 트 의 함수 currying 코 리 화 분석 자 바스 크 립 트 의 Function. prototype. bind () 방법 분석 원형 대상 중 this 에 대한 어 리 석 은 잘못된 인식 자 바스 크 립 트 의 재 미 있 는 반 코 리 화 기술
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
기초 정리 - 1문자 (String) 숫자 (Number) 불린 (Boolean) null undefined 심볼 (Symbol) 큰정수 (BigInt) 따옴표로 묶어 있어야 함 Not-A-Number - 숫자 데이터 / 숫자로 표...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.