>  기사  >  웹 프론트엔드  >  JS의 안티 커링

JS의 안티 커링

大家讲道理
大家讲道理원래의
2017-08-19 10:33:481612검색

디커링

반대로 디커링의 역할은 함수의 적용성을 확장하여 원래 특정 객체가 소유한 함수를 어떤 객체에서나 사용할 수 있도록 하는 것입니다.
그 아래에 주어진 함수


obj.func(arg1, arg2)


를 함수형으로 변환한 시그니처는 다음과 같습니다.


func(obj, arg1, arg2)


Anti-curring에 대한 형식적인 설명입니다.

예를 들어 다음은 간단한 구현입니다.


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의 프로토타입에 정의된 메서드이므로 이 메서드를 모든 함수에 사용할 수 있습니다. 호출할 때: sayHiuncurrying=sayHi.uncurrying(), 따라서 uncurrying에서 이것은 sayHi 함수를 가리킵니다. (일반적으로 프로토타입 메소드의 this는 프로토타입 객체 프로토타입을 가리키지 않고 호출 객체가 다른 호출 객체를 가리킵니다. 함수는 javascript)

  • call.apply(that, 인수)에서도 객체입니다. 이를 호출 메서드의 컨텍스트로 설정한 다음 이전 예에서는 호출 메서드에 인수를 전달합니다. sayHi를 가리키므로 sayHiuncurrying이 호출되는 (arg1, arg2, ...)은 sayHi.call (arg1, arg2, ...);

  • sayHi.call (arg1, arg2, ...)과 동일합니다. 호출 함수는 arg1을 sayHi의 컨텍스트로 처리합니다. 그런 다음 arg2,...와 같은 나머지 매개변수를 sayHi에 전달하므로 결국 arg1.sayHi(arg2,...);

  • 와 동일합니다. , 이는 sayHiuncurrying(obj,args)가 obj.sayHi(args)와 동일하다는 것과 동일합니다.

마지막으로 반대편에서 살펴보겠습니다. 사실 안티 커링은 sayHi(args)의 원래 형태를 sayHiuncurring(obj,args)로 변환하는 것과 동일하며, 이는 sayHi의 사용 범위를 일반화한 것입니다. 더 추상적으로 표현하면, 커링 방지 안티커링을 사용하면 원래 x.y(z) 호출을 y(x',z) 형식의 호출로 변환할 수 있습니다. x'가 x 또는 다른 객체라고 가정하면 함수의 사용 범위가 확장됩니다.

범용 디커링 기능

위의 예에서 uncurring은 프로토타입에 기록되는데 이는 좋지 않습니다. 실제로 uncurring을 별도의 함수로 캡슐화할 수 있습니다.


var uncurrying= function (fn) {    return function () {        var args=[].slice.call(arguments,1);        return fn.apply(arguments[0],args);        
    }    
};


위 함수는 매우 명확합니다. .
사용 시 uncurring을 호출하고 기존 함수 fn을 전달합니다. decurring 함수는 새 함수에서 허용하는 첫 번째 실제 매개변수가 fn의 this 컨텍스트에 바인딩되고 다른 매개변수가 전달됩니다. fn을 매개변수로 사용합니다.

그래서 안티 커링에 대한 더 대중적인 설명은 함수 차용이 될 수 있습니다. 즉, 함수는 다른 객체를 받아들이고 처리할 수 있으며 차용을 통한 일반화는 함수의 사용 범위를 확장한다는 의미입니다.

그래서 uncurring의 더 일반적인 사용법은 Javascript에 내장된 다른 메소드를 직접 구현하지 않고도 차용하는 것입니다.

텍스트 설명이 약간 복잡하므로 계속해서 코드를 읽어 보겠습니다.


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' ]


split=uncurrying(String.prototype.split) 특정 fn을 uncurrying에 전달합니다. 즉 String.prototype.split입니다. 분할 함수는 String.prototype.split 함수를 사용하여 함수가 분할(test,',')을 호출할 때 전달된 첫 번째 매개변수는 분할 실행의 컨텍스트이고 나머지 매개변수는 전달된 매개변수와 동일합니다. 원래 String.prototype.split 함수.

다른 예를 보세요:


var $ = {};
console.log($.push);                          // undefinedvar pushUncurrying = uncurrying(Array.prototype.push);
$.push = function (obj) {
    pushUncurrying(this,obj);
};
$.push('first');
console.log($.length);                        // 1console.log($[0]);                            // firstconsole.log($.hasOwnProperty('length'));      // true


이것은 "유사한 jquery라이브러리"를 모방하고 구현 시 Array의 푸시 방법을 차용합니다. 객체에는 푸시 메소드가 없으므로 console.log(obj.push)는 정의되지 않은 값을 반환합니다. 배열을 사용하여 푸시를 처리할 수 있습니다. 기본 배열 메소드(js 엔진)는 길이 속성 및 배열 멤버를 유지합니다. 의사 배열 객체.

같은 방식으로 다음을 계속할 수 있습니다.


var indexof=uncurrying(Array.prototype.indexOf);
$.indexOf = function (obj) {    return indexof(this,obj);
};
$.push("second");
console.log($.indexOf('first'));              // 0console.log($.indexOf('second'));             // 1console.log($.indexOf('third'));              // -1


예를 들어, 자체 클래스 라이브러리를 구현할 때 일부 메서드가 네이티브 클래스와 유사하면 다음을 통해 네이티브 메서드를 빌릴 수 있습니다. 다루지 않는.

Function.prototype.call/apply 메서드를 취소할 수도 있습니다. 예를 들면 다음과 같습니다.


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!


이렇게 하면 함수를 기능적 프로그래밍을 통해 매우 유연하게 일반 "데이터"로 사용할 수 있습니다. 이는 일부 클래스 라이브러리에서 종종 볼 수 있습니다.

일반 언커링 기능의 공격

위의 언커링 기능은 사고습관에 더 부합하고 이해하기 쉬운 버전입니다. 다음으로, 끝까지 공격하고 다른 여러 버전을 살펴보겠습니다.

먼저 무엇보다도, B 상자가 더 높으면 uncurringing은 다음과 같이 쓸 수도 있습니다:


var uncurrying= function (fn) {    return function () {        var context=[].shift.call(arguments);        return fn.apply(context,arguments);
    }
};


물론, 여전히 B 수준을 향상시켜야 한다면 다음과 같이 쓸 수도 있습니다:


으아악

위 내용은 JS의 안티 커링의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.