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

时间:2020-12-10 00:42:00

I have a javascript function (class) that takes a function reference as one paremter.

我有一个javascript函数(类),它将函数引用作为一个paremter。

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.

由于我不会进入这里的原因,我需要通过将它包含在匿名函数中来附加函数,但是我能够弄清楚如何做到这一点的唯一方法是添加一个公共函数MyClass将callBack函数作为参数并返回修改后的版本。

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? 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.

将callBack函数作为参数传递给类时,是否可以使这个工作成功?当将它作为参数传递时尝试以这种方式修改函数似乎只影响它在类中的实例,但这似乎不是一个有效的假设,因为函数是javascript中的对象,因此通过参考。

Update: as crescentfresh pointed out (and I failed to explain well), I want to modify the callBack function in-place. I'd rather not call a second function if it's possible to do all of this when the class is instantiated.

更新:正如crescentfresh指出的那样(我没能很好地解释),我想在原地修改callBack函数。如果在实例化类时可以执行所有这些操作,我宁愿不调用第二个函数。

4 个解决方案

#1


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. That means that changing the value of an argument variable to a new one won't affect the original one at all.

函数对象不提供修改它们的方法。因此,您想要做的事情是不可能的。这与Jon Skeet喜欢指出Java的相同:对象并不是真正通过引用传递,而是通过值传递指向它们的指针。这意味着将参数变量的值更改为新变量将不会影响原始变量。

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. 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.

只有两种方法可以在Java和JavaScript等按值调用语言中执行您想要的操作:第一种方法是使用(函数)对象的方法来修改它。正如我已经说过的那样,函数对象没有那些。另一个是将函数对象作为属性的对象作为第二个参数传递,并将相应的属性设置为包装旧函数的新函数。

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.

这也适用于全局函数:它们是窗口对象的属性。

#2


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. So this may limit the usefulness of this approach for you a little.

这样做你想要的,但是必须在ModifyCallbackClass中使用相同的名称引用函数“modifiableCallback”,否则不会应用闭包。所以这可能会限制这种方法对你有用的一点。

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();

}

#3


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;
}

#4


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();

#1


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. That means that changing the value of an argument variable to a new one won't affect the original one at all.

函数对象不提供修改它们的方法。因此,您想要做的事情是不可能的。这与Jon Skeet喜欢指出Java的相同:对象并不是真正通过引用传递,而是通过值传递指向它们的指针。这意味着将参数变量的值更改为新变量将不会影响原始变量。

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. 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.

只有两种方法可以在Java和JavaScript等按值调用语言中执行您想要的操作:第一种方法是使用(函数)对象的方法来修改它。正如我已经说过的那样,函数对象没有那些。另一个是将函数对象作为属性的对象作为第二个参数传递,并将相应的属性设置为包装旧函数的新函数。

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.

这也适用于全局函数:它们是窗口对象的属性。

#2


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. So this may limit the usefulness of this approach for you a little.

这样做你想要的,但是必须在ModifyCallbackClass中使用相同的名称引用函数“modifiableCallback”,否则不会应用闭包。所以这可能会限制这种方法对你有用的一点。

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();

}

#3


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;
}

#4


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();