来自数组的函数时的 Javascript 作用域问题

标签 javascript scope call apply

作为我正在构建的网络应用程序的一部分,多个命令可以同时从服务器传入。

处理这些命令时,数据往往会更新,然后可能会生成相当繁重的页面 HTML。

当多个相似的命令进来时,程序会对数据进行处理,然后每次都会重新生成部分页面。这可能会导致大量处理时间的浪费。

因此,我正在尝试创建一个调用堆栈,因此当处理命令时,它会查看命令触发的函数是否在堆栈中,如果没有找到,则会添加它。

<小时/>

我的问题是如何将调用堆栈中的被调用函数保持在正确的范围内,同时还能够消除重复项。

基本代码:

var tools = {
  functions:{
    function1: function(){
      return this;
    },
    function2: function(){
    }
  },
  unique: function(arr){
    var returnArr=[],
        x, i;

    for (x=0; x<arr.length; x++){
      for (i=(x+1); i<arr.length; i++){
        if (arr[x]===arr[i]){
          arr.splice(i, 1);
        }
      }
      returnArr.push(arr[x]);
    }

    return returnArr;
  }
}
<小时/>

示例1:

var callstack=[tools.functions.function1, tools.functions.function1];

callstack = tools.unique(callstack);

for (var x=0; x<callstack.length; x++){
  console.log(callstack[x](), "should equal tools.functions");
}

这会失败,因为“this”将返回 [function()]

<小时/>

示例2:

var callstack=[
  (function(){return tools.functions.function1()}),
  (function(){return tools.functions.function1()})
];

callstack = tools.unique(callstack);

for (var x=0; x<callstack.length; x++){
  console.log(callstack[x](), "should equal tools.functions");
}

这会失败,因为您无法确保函数是唯一的,因此它仍然会运行该函数两次。

<小时/>

这可以通过使用两个数组(一个跟踪函数名称,一个保存封装函数)并使它们保持同步来解决,但我忍不住觉得必须有一个更清洁的数组使用 .call 的方式,但我看不到它。

JSFiddle:http://jsfiddle.net/Kj6E8/

最佳答案

一般来说,不可能按照您要求的方式保留 this 的值。一旦将这些函数插入数组,这些函数曾经驻留的对象就会丢失。

如果您仅在单个对象上调用函数,则需要以某种方式将函数绑定(bind)到该对象。有很多方法可以做到这一点,例如,您可以传递对象以将这些函数绑定(bind)到您的唯一函数中。

http://jsfiddle.net/8WAZb/1/

var tools = {
  functions:{
    function1: function(){
      return this;
    },
    function2: function(){
    }
  },
  unique: function(arr, o){
    var returnArr=[],
        x, i;

    for (x=0; x<arr.length; x++){
      for (i=(x+1); i<arr.length; i++){
        if (arr[x]===arr[i]){
          arr.splice(i, 1);
        }
      }
        returnArr.push(this.bind(arr[x], o));
    }

    return returnArr;
  },
  bind: function(f, o) {
      return function () {
          return f.apply(o, arguments);
      }
  }
}

console.info("Example 1:");
var callstack=[tools.functions.function1, tools.functions.function1];
callstack = tools.unique(callstack, tools.functions);
console.log("Callstack:",callstack);
for (var x=0; x<callstack.length; x++){
  console.log(callstack[x](), "should equal tools.functions");
}

如何以及何时推断 this 的值实际上取决于该对象何时处于作用域内。据推测,您更有可能在调用堆栈创建阶段将该对象置于作用域内,并且可能不一定在您希望调用调用堆栈中的函数时将该对象保留在作用域内。如果是这种情况,尽早绑定(bind)(即在减少到所示的唯一调用堆栈期间)似乎是一个明智的选择。

关于来自数组的函数时的 Javascript 作用域问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13175411/

相关文章:

c++ - c++11 lambda 真的支持闭包吗?函数变量中存在语义冲突

javascript - 如何在不返回内部函数的情况下访问函数内部函数

javascript - 使用 ng-repeat 和 ng-model 调用 splice() 时 Angular 重定向到主页

javascript - 使用 Call 从函数继承对象

javascript - Javascript 中的应用/调用方法 : What is the first arguments "this"?

class - 从 Arduino 中的库调用主程序中的函数

javascript - newChat.style.setAttribute ("width"、 "100px"); 有什么问题吗?在内容脚本中?

javascript - Bootstrap 仪表板

javascript - 如何使用 HTML 创建带有下拉菜单的粘性导航栏?

javascript - SAPUI5 中的原型(prototype)和扩展 (Component.js)