source

원본을 참조하는 동안 자바스크립트 함수 덮어쓰기

factcode 2023. 11. 5. 14:59
반응형

원본을 참조하는 동안 자바스크립트 함수 덮어쓰기

기능이 하나 있는데,a(), 내가 무시하고 싶지만 원본도 가지고 있다는 것.a()상황에 따라 순서대로 행해집니다.예를 들어, 페이지를 생성할 때 다음과 같이 재정의할 수 있습니다.

function a() {
    new_code();
    original_a();
}

때로는 이렇게도 합니다.

function a() {
    original_a();
    other_new_code();
}

그걸 어떻게 얻을 수 있죠?original_a()내부에서a()? 그게 가능하긴 해요?

이런 식으로 오버라이딩하는 것에 대한 대안을 제시하지 말아주세요, 저는 많은 것을 알고 있습니다.저는 이 방법에 대해 구체적으로 묻고 있는 것입니다.

당신은 다음과 같은 것을 할 수 있습니다.

var a = (function() {
    var original_a = a;

    if (condition) {
        return function() {
            new_code();
            original_a();
        }
    } else {
        return function() {
            original_a();
            other_new_code();
        }
    }
})();

선언하기original_a익명 함수 내부에서는 글로벌 네임스페이스를 어지럽히는 것을 방지하지만 내부 함수에서는 사용할 수 있습니다.

Nerdmaster가 댓글에 언급된 것처럼, 반드시 다음 내용을 포함해야 합니다.()맨 끝에외부 함수를 호출하고 결과(두 내부 함수 중 하나)를 저장하려고 합니다.a, 외부 기능 자체를 저장하지 않습니다.a.

Proxy 패턴은 다음과 같은 도움을 줄 수 있습니다.

(function() {
    // log all calls to setArray
    var proxied = jQuery.fn.setArray;
    jQuery.fn.setArray = function() {
        console.log( this, arguments );
        return proxied.apply( this, arguments );
    };
})();

위에서 코드를 "프록시드" 변수를 숨기기 위한 함수로 래핑합니다.jQuery의 setArray-method를 클로저에 저장하고 덮어씁니다.그러면 프록시가 모든 호출을 메서드에 기록하고 호출을 원본에 위임합니다.apply(이것, 인수)를 사용하면 호출자가 원래 메서드와 프록시 메서드의 차이점을 알아채지 못할 수 있습니다.

고마워요 여러분 대리 패턴이 정말 도움이 됐어요...사실 글로벌 기능을 foo라고 부르고 싶었습니다.특정 페이지에서 나는 몇 가지 확인을 해야 합니다.그래서 저는 다음과 같이 했습니다.

//Saving the original func
var org_foo = window.foo;

//Assigning proxy fucnc
window.foo = function(args){
    //Performing checks
    if(checkCondition(args)){
        //Calling original funcs
        org_foo(args);
    }
};

감사합니다. 정말 도움이 되었습니다.

다음과 같은 컨스트럭트를 사용하여 함수를 재정의할 수 있습니다.

function override(f, g) {
    return function() {
        return g(f);
    };
}

예를 들어,

 a = override(a, function(original_a) {
      if (condition) { new_code(); original_a(); }
      else { original_a(); other_new_code(); }
 });

편집: 오타 수정.

임의 인수 전달 중:

a = override(a, function(original_a) {
    if (condition) { new_code(); original_a.apply(this, arguments) ; }
    else { original_a.apply(this, arguments); other_new_code(); }
});

@Matthew Crumley가 제공하는 대답은 즉시 호출된 함수 표현을 사용하여 이전의 'a' 함수를 반환된 함수의 실행 컨텍스트로 닫는 것입니다.이것이 가장 좋은 답이었다고 생각하지만, 개인적으로는 IIFE에 논쟁거리로 'a'라는 함수를 전달하는 것이 더 좋습니다.나는 그것이 더 이해할 수 있다고 생각합니다.

   var a = (function(original_a) {
        if (condition) {
            return function() {
                new_code();
                original_a();
            }
        } else {
            return function() {
                original_a();
                other_new_code();
            }
        }
    })(a);

위의 예는 정확하게 적용되지 않습니다.this아니면 패스arguments기능 오버라이드에 정확하게 맞추어야 합니다.언더스코어 _.wrap() 기존 함수 랩, 적용this통과.arguments정확하게참조: http://underscorejs.org/ #

제 생각에는 상위 답변들은 가독성/유지성이 떨어지고, 나머지 답변들은 문맥을 적절하게 묶지 못합니다.이 두 가지 문제를 모두 해결하기 위해 ES6 구문을 사용하여 읽을 수 있는 솔루션을 소개합니다.

const orginial = someObject.foo;
someObject.foo = function() {
  if (condition) orginial.bind(this)(...arguments);
};

다른 사람이 작성한 코드가 있어서 코드에서 찾을 수 없는 함수에 줄을 추가하고 싶었습니다.그래서 저는 그 해결책으로 그것을 무시하고 싶었습니다.

하지만 어떤 해결책도 저에게 효과가 없었습니다.

다음은 제 사례에서 작동한 것입니다.

if (typeof originalFunction === "undefined") {
    originalFunction = targetFunction;
    targetFunction = function(x, y) {
        //Your code
        originalFunction(a, b);
        //Your Code
    };  
}

여러 라이브러리의 기능을 무시해야 하는 경우가 많았기 때문에 비슷한 시나리오를 위해 작은 도우미를 만들었습니다.이 도우미는 "namespace"(기능 컨테이너), 기능 이름 및 재정의 기능을 수락합니다.참조된 네임스페이스의 원래 함수를 새 함수로 대체합니다.

새로운 함수는 원래 함수를 첫 번째 인수로 받아들이고, 원래 함수 인수를 나머지 인수로 받아들입니다.그것은 매번 상황을 보존할 것입니다.보이드 및 비보이드 기능도 지원합니다.

function overrideFunction(namespace, baseFuncName, func) {
    var originalFn = namespace[baseFuncName];
    namespace[baseFuncName] = function () {
        return func.apply(this, [originalFn.bind(this)].concat(Array.prototype.slice.call(arguments, 0)));
    };
}

부트스트랩에서의 사용 예:

overrideFunction($.fn.popover.Constructor.prototype, 'leave', function(baseFn, obj) {
    // ... do stuff before base call
    baseFn(obj);
    // ... do stuff after base call
});

성능 테스트는 따로 만들지 않았습니다.시나리오에 따라 큰 문제가 될 수도 있고 아닐 수도 있는 원치 않는 오버헤드가 추가될 수도 있습니다.

그래서 제 대답은 결국 원래의 개체를 가리키는 이 변수를 사용할 수 있는 해결책이 되었습니다.저는 "스퀘어"의 새로운 인스턴스를 만들지만, "스퀘어"가 크기를 생성하는 방식이 싫었습니다.저는 그것이 저의 구체적인 요구에 따라야 한다고 생각했습니다.하지만 그러기 위해서는 광장에 이미 존재하는 다른 함수들을 호출하는 해당 함수의 내부와 함께 업데이트된 "GetSize" 함수가 필요했습니다.키, 이거.볼륨()을 가져옵니다.하지만 그렇게 하기 위해서는 미친 해킹 없이 해야 했습니다.그래서 여기 제 해결책이 있습니다.

다른 Object initializer 또는 도우미 기능.

this.viewer = new Autodesk.Viewing.Private.GuiViewer3D(
  this.viewerContainer)
var viewer = this.viewer;
viewer.updateToolbarButtons =  this.updateToolbarButtons(viewer);

다른 개체에서 기능합니다.

updateToolbarButtons = function(viewer) {
  var _viewer = viewer;
  return function(width, height){ 
blah blah black sheep I can refer to this.anything();
}
};

모든 상황에서 효과가 있을지는 확실하지 않지만, 우리의 경우에는, 우리가 그들을 무시하려고 했던 것입니다.describe이름을 파싱하고 전체를 건너뛸 수 있도록 Jest에서 기능합니다.describe일부 기준을 충족하면 차단합니다.

우리에게 도움이 된 것은 다음과 같습니다.

function describe( name, callback ) {
  if ( name.includes( "skip" ) )
    return this.describe.skip( name, callback );
  else
    return this.describe( name, callback );
}

여기서 중요한 두 가지 사항:

  1. 화살표 기능은 사용하지 않습니다.() =>.

    화살표 함수는 참조를 다음으로 바꿉니다.this그리고 우리는 그것이 파일의 것이 되기 위해 필요합니다.this.

  2. 의 사용.this.describe그리고.this.describe.skip만이 아니라describe그리고.describe.skip.

다시 말하지만, 그것이 누구에게도 가치가 있는지는 확실하지 않지만, 우리는 원래 매튜 크럼리의 훌륭한 답을 피하려고 했지만, 우리의 방법을 함수로 만들고 조건에서 그것들을 해석하기 위해 매개변수를 받아들여야 했습니다.

언급URL : https://stackoverflow.com/questions/296667/overriding-a-javascript-function-while-referencing-the-original

반응형