1

新手问题。考虑

var foo = function(func) {
console.log(func.arguments);
}

“foo”函数接受一个参数,即一个函数。如何在运行时访问与“func”函数一起传递的参数?

编辑:我不想动态地将参数设置为 func,我想找出 func 传入的参数,以便我可以用它们做其他事情。基本上我想将传递给 func 的参数作为键存储,并将 func 的结果作为值存储,并将它们存储在哈希对象中......最终目标是根据什么来记住运行“func”的各种结果参数被传入。虽然我现在对如何访问/存储这些参数感到好奇。

4

6 回答 6

2

您无法在运行时访问它们,foo就像从未调用foo运行时一样。func

foo(function(){
    console.log('This is never executed');
});

如果您确实在其中执行funcfoo那么您当时必须有权访问参数:

var foo = function(func) {
    func(1, 2, 3); // Now func is called, and you know what the arguments are
}
于 2013-08-12T17:49:55.083 回答
0

你想要这样的东西吗?

var foo = function(func) {
    return func.args;
},
bar = function(){
    bar.args = arguments;
};
bar('a','b');
foo(bar); // Arguments object ['a','b']
于 2013-08-12T18:01:23.240 回答
0
//
// Function.memo
//
;
( function ( _host_ ) {

    var
        t    = !0,
        f    = !t,
        pn   = String( this ),
        mmfn = function ( fn, mem_read_callback, mem_write_callback ) {

            return ( function( input, output, mrcb, mwcb, k, v ) {

                    // capture original fns
                    var
                        origFn = this,

                        // define 'memo' fn
                        mmfn   = function ( /*...params*/ ) {

                            // capture passed arguments
                            var inputArgs = slc( arguments );

                            // reset the flag,
                            // -1 indicates that passed arguments haven't been proccessed yet.
                            k = -1;

                            // see if args have been already processed
                            // scan inputs[]
                            each( input, function ( input_args, pos ) {
                                // update k to point to memoized args
                                return ( is_same_arrays( inputArgs, input_args ) ) ? ( k = pos, f ) : t;
                            } );

                        // if k is -1 passed args are processe for the 1st time
                        //   execute original fn,
                        //   store result in output[],
                        //   store arguments[] in inputs[],
                        //   call provided ( optional ) 'mem_write_callback',
                        //   return result
                        // else
                        // call provided ( optional )'mem_read_callback',
                        // return memoized result
                        return  ( k == -1 ) ?
                                (
                                    v = origFn.apply( this, inputArgs ),
                                    input.push( inputArgs ),
                                    output.push( v ),
                                    ( isfn( mwcb ) && mwcb.call( this, inputArgs, v ) ),
                                    v
                                ):
                                ( isfn( mrcb ) && mrcb.call( this, inputArgs, output[k] ), output[k] );

                    };

                // optionaly provide access to cache
                mmfn.cache = {
                                inputs  : input,
                                outputs : output
                             };

                mmfn.mclear = function () {
                    input.splice(  0, input.length  );
                    output.splice( 0, output.length );
                };

                // return memoizer
                return mmfn;

            } ).call( fn, [], [], mem_read_callback, mem_write_callback );
        };





    // #helpers
    function is_same_arrays( a1, a2 ) {
        var flg = t;
        return ( each( a1, function ( v, k ) { return ( v === a2[k] ) ? t: ( flg = f ) ; } ), flg );
    }
    function each( arr, fn ) {
        for ( var l = arr.length, i = 0; i < l; i++ )
            if ( ( fn.call( arr, arr[i], i ) ) === f ) break;
        return arr;
    }
    function slc( args, i, j ) {
        return Array.prototype.slice.call( args, i, j );
    }
    function isfn( fn ) {
        return typeof fn === 'function';
    }



    // attach 'memo' fn to host obj
    _host_[pn] = mmfn;

} ).call( new String('memo'),  ( typeof context === 'undefined' ? Function : context ) );



var
f1 = Function.memo(
                    function ( v ) { return v*v; },
                    function ( inpArr, res ) { console.log('cache read: ', inpArr.join(''),', ', res);  },
                    function ( inpArr, res ) { console.log('cache write: ', inpArr.join(''),', ', res);  }
                );

f1(1);
f1(2);
f1(1);
f1(2);
f1(1);
f1(3);
//
// logs
//
// cache write, 1 , 1
// cache write, 2 , 4
// cache read, 1 , 1
// cache read, 2 , 4
// cache read, 1 , 1
// cache write, 3 , 9
//
于 2013-08-26T20:55:01.817 回答
0
//
//     var
//         base_fn    = function(){}, 
//         tracer_fn  = tracer( base_fn );
//
function tracer( fn ) { 

   return ( function( argsCache, F, _s ){ 


               // define new fn that will have that capability
               // it's a wrapper for original fn

               var
                   fn2    = function(/*...params*/) {

                              var

                                // temporary stores original fn's result
                                out, 

                                // capture passed arguments
                                theArgs = _s.call( arguments ), 


                                //
                                //  you can implement 'memo' functionality here
                                //  if that's your goal, 
                                //  by 'scaning' already processed inputs
                                //  in argsCache array
                                //  and optionaly runing original fn, 
                                //  if no match is found
                                //

                                // save input and output of fn as h-map
                                argsIO  = {
                                            input  : theArgs, 
                                            output : null
                                          };

                                // execute original fn 
                                // pass it captured arguments
                                // 'remember' it's result
                                out = F.apply( this, theArgs );

                                // save calculated value
                                argsIO.output = out;

                                // 'push' fn input-output record on the cache
                                argsCache.push( argsIO );

                                // return whatever original fn returned
                                return out;

                            };

                  // provide 'static' access to 'closured' cache
                  // use the array to inspect 'arguments history'
                  fn2.args = argsCache;

                  // provide a way to empty cache
                  fn2.clear = function () { 
                      fn2.args.splice( 0, fn2.args.length );
                      return fn2.args;
                  };

                  // return fn 'upgrade'
                  return fn2;

   } )( [], fn, Array.prototype.slice );

}


function basefn() {

   // doStuff( arguments );
   // returning value, as well as arguments, 
   // are recorded by tracer fn

   return arguments.length;
}


// get the 'tracer' fn
var
   fn = tracer( basefn );



// run it couple of times 
// passing arbitrary arguments
fn( 12345, new XMLHttpRequest() );
fn('a', 'z', /^[a-z]+$/ );
fn( {}, [1,2,3] );
fn( location, document );
fn( Math );

//
// access 'args history' through fn.args ( array ) property
//
//   var
//       lastCallIO = fn.args[ fn.args.length - 1 ];
//

console.log( fn.args );

//
// empty cache, free some memory
//
//   fn.clear();
//
//
于 2013-08-12T19:40:11.890 回答
0

func 被调用时不能访问它的参数,但可以返回一个新函数,该函数包装 func 并在调用该函数时执行任何附加处理。foo 中的局部变量在返回的函数的所有调用之间共享,因此可用于实现记忆化。

var foo = function(func) {
    return function() {
        // Get arguments from func.
        console.log("Calling func", arguments);
        // Call func with arguments.
        return func.apply(null, arguments);
    };
};

var bar = function(x) {
    return x * 2;
};

var foobar = foo(bar);

console.log(foobar(10));
console.log(foo(bar)(20));
于 2013-08-12T20:46:42.443 回答
0

如果您将函数作为参数传递,则该函数没有随它一起传递的参数。您正在传递对必须在函数内部调用的函数的引用,然后您将有参数。

您几乎可以说 is 的参数funcundefined因为您还没有调用该函数。并且从 的范围内foo,您将能够将参数设置为您想要的任何内容。

于 2013-08-12T17:50:02.787 回答