简体   繁体   English

扩展作为参数传递的Javascript函数

[英]Extend Javascript Function passed as parameter

I have a javascript function (class) that takes a function reference as one paremter. 我有一个javascript函数(类),该函数将一个函数引用作为一个参数。

function MyClass ( callBack ) {
  if (typeof callBack !== 'function')
    throw "You didn't pass me a function!"
}

For reasons I won't go in to here, I need to append something to the function by enclosing it in an anonymous function, but the only way I've been able to figure out how to do it is by adding a public function to MyClass that takes the callBack function as a parameter and returns the modified version. 出于某种原因,我将不进行介绍,我需要通过将其包含在匿名函数中来向该函数添加一些内容,但是我唯一能弄清楚如何做到这一点的方法是在该函数中添加一个公共函数。以callBack函数为参数并返回修改后的版本的MyClass

function MyClass () {
    this.modifyCallBack = function ( callBack ) {
       var oldCallBack = callBack;
       callBack = function () {
           oldCallBack(); // call the original functionality
           /* new code goes here */
       }
       return callBack;
    }
}

/* elsewhere on the page, after the class is instantiated and the callback function defined */
myCallBackFunction = MyClassInstance.modifyCallBack( myCallBackFunction );

Is it possible to make this work when passing the callBack function as a parameter to the class? 将callBack函数作为参数传递给类时,是否可以使此项工作? Attempting to modify the function in this manner when passign it as a parameter seems to only affect the instance of it in within the class, but that doesn't seem like it's a valid assumption since functions are Objects in javascript, and are hence passed by reference. 当尝试将函数作为参数传递时,尝试以这种方式修改函数似乎只影响类中的实例,但这似乎不是一个有效的假设,因为函数是javascript中的Objects,因此被传递参考。

Update: as crescentfresh pointed out (and I failed to explain well), I want to modify the callBack function in-place. 更新:正如crescentfresh指出的(我未能很好地解释),我想就地修改callBack函数。 I'd rather not call a second function if it's possible to do all of this when the class is instantiated. 如果在实例化类时可以执行所有这些操作,我宁愿不调用第二个函数。

Function objects don't provide methods to modify them. 函数对象不提供修改它们的方法。 Therefore, what you want to do is impossible the way you want to do it. 因此,您想做的事情是您做不到的。 It's the same thing Jon Skeet likes to point out about Java: Objects are not really passed by reference, but instead a pointer to them is passed by value. 乔恩·斯基特(Jon Skeet)指出Java是同样的事情:对象并不是真正通过引用传递的,而是通过值传递指向它们的指针的。 That means that changing the value of an argument variable to a new one won't affect the original one at all. 这意味着将参数变量的值更改为新变量根本不会影响原始变量。

There are only two ways to do what you want in call-by-value languages like Java and JavaScript: The first one would be to use the (function) object's methods to modify it. 在Java和JavaScript这样的按值调用语言中,只有两种方法可以完成您想要的事情:第一种是使用(函数)对象的方法进行修改。 As I already stated, function objects don't have those. 正如我已经说过的,函数对象没有那些。 The other one is to pass the object of which the function object is a property as a second argument and set the appropriate property to a new function which wraps the old one. 另一种方法是将函数对象是属性的对象作为第二个参数传递,并将适当的属性设置为一个新函数,该函数将旧的函数包装起来。

Example: 例:

var foo = {};
foo.func = function() {};

function wrapFunc(obj) {
    var oldFunc = obj.func;
    obj.func = function() {
        // do some stuff
        oldFunc.call(obj, _some_argument__);
    };
}

wrapFunc(foo);

This works for global functions as well: they are properties of the window object. 这也适用于全局函数:它们是window对象的属性。

As Javascript uses lexical scoping on variables the following is possible: 由于Javascript对变量使用词法作用域,因此可能出现以下情况:

var modifiableCallback=function() { alert('A'); };


function ModifyCallbackClass(callback)
{
    modifiableCallback=function() { callback(); alert('B'); };  
}


function body_onload()
{

    var myClass=new ModifyCallbackClass(modifiableCallback);

    modifiableCallback();

}

This does what you want, however the function "modifiableCallback" must be referred to with the same name inside ModifyCallbackClass, otherwise the closure will not be applied. 这可以满足您的要求,但是必须在ModifyCallbackClass中使用相同的名称引用函数“ modifiableCallback”,否则将不使用闭包。 So this may limit the usefulness of this approach for you a little. 因此,这可能会稍微限制这种方法的用处。

Using eval (performance may suffer a bit) it is also possible to make this approach more flexible: 使用eval(性能可能会有所下降),还可以使此方法更加灵活:

var modfiableCallback1=function() { alert('A'); };

var modfiableCallback2=function() { alert('B'); };

var modfiableCallback3=function() { alert('C'); };

function ModifyCallbackClass(callbackName)
{
    var temp=eval(callbackName);
    var temp2=eval(callbackName);

    temp= function() { temp2(); alert('Modified'); };

    eval(callbackName + " = temp;");
}


function body_onload()
{

    var myClass=new ModifyCallbackClass("modfiableCallback1");

    modfiableCallback1();

    myClass=new ModifyCallbackClass("modfiableCallback2");

    modfiableCallback2();

    myClass=new ModifyCallbackClass("modfiableCallback3");

    modfiableCallback3();

}

I assume you are saving this callback somewhere... Any reason this won't work? 我假设您将回调保存在某处...任何原因都行不通吗?

function MyClass ( callBack ) {
  var myCallBack;

  if (typeof callBack !== 'function')
    throw "You didn't pass me a function!"

  var oldCallBack = callBack;
  callBack = function () {
    oldCallBack(); // call the original functionality
     /* new code goes here */
  }
  myCallBack = callback;
}

You want to do something like: 您想要执行以下操作:

function MyClass () {
    this.modifyCallBack = function ( callBack ) {
        var oldCallBack = callBack;
        callBack = function () {
            oldCallBack(); // call the original functionality
            alert("new functionality");
        }
        return callBack;
    }
}

/* elsewhere on the page, after the class is instantiated and the callback function defined */
var myCallBackFunction = function () {alert("original");};
var MyClassInstance = new MyClass();
myCallBackFunction = MyClassInstance.modifyCallBack( myCallBackFunction );
myCallBackFunction();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM