调用 .apply() 后如何保留原始函数的 this 上下文?

问题描述 投票:0回答:1

我有一个函数A,它接受一个函数作为参数。我想在 functionA 中操作该函数的参数并将其作为 functionC 返回。我发现我可以使用 .apply() 来做到这一点,但是 functionB 的原始上下文丢失了,而是被 functionA 取代了。

例如:

var factory = {
   return {
       fnB: function() {}  
   }
};

fnA(fn) {
    return fnC(params) {
        var customparams = [params, {something: else}]
        return method.apply(null, customparams);
     }
}

var load = fnA(factory.fnB);
load(params);

但是,当我执行 load(params) 时,我丢失了 functionB 的上下文。 FunctionB 被定义为工厂中的方法。我该怎么办?

javascript
1个回答
3
投票

我将假设

method
实际上是
fn
,并且
functionB
是分配给对象属性的函数,并且实际代码中不存在各种语法错误:

var obj = {
    name: "foo",
    functionB: function() {
        console.log(this.name); // <== Using `this` to refer to `obj`
    }
};

function functionA(fn) {
    return function functionC(params) {
        var customparams = [params, {something: "else"}];
        return fn.apply(null, customparams);
    };
}

var load = functionA(obj.functionB);
load("a", "b"); // Fails because `this` in the call to `functionB` isn't `obj`

如果是这样,您可以通过几次修复来修复它:

1) 通过使用

Function#bind
functionB
传递到
functionA
:

var load = functionA(obj.functionB.bind(obj));
load("a", "b"); // Works

var obj = {
  name: "foo",
  functionB: function() {
    snippet.log(this.name); // <== Using `this` to refer to `obj`
  }
};

function functionA(fn) {
  return function functionC(params) {
    var customparams = [params, {
      something: "else"
    }];
    return fn.apply(null, customparams);
  };
}

var load = functionA(obj.functionB.bind(obj));
load("a", "b"); // Works
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

2) 通过向

functionA
添加第二个参数,如 Bergi 建议,在调用
fn
时使用(参见代码片段)——例如,许多 ES5
Array
方法都使用这种方法:

var obj = {
  name: "foo",
  functionB: function() {
    snippet.log(this.name);
  }
};

function functionA(fn, thisArg) {           // <=== Accepting thisArg
  return function functionC(params) {
    var customparams = [params, {
      something: "else"
    }];
    return fn.apply(thisArg, customparams); // <=== Using it
  };
}

var load = functionA(obj.functionB, obj);   // <=== Passing it
load("a", "b"); // Works
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

© www.soinside.com 2019 - 2024. All rights reserved.