修改回调中传递的变量

时间:2017-09-19 18:46:24

标签: javascript scope

如何修改/更新回调内传递的变量?

示例:

function App() {
  this.components = {};
  this.queue = {};
}

App.prototype.import = function (name, cb) {

  if (this.components[name]) {
    return cb(this.components[name]);
  }

  if (!this.queue[name]) {
    this.queue[name] = [];
  }

  // push to queue
  this.queue[name].push(cb);

};

App.prototype.export = function (name, data) {
  
  let that = this;

  // set components instance
  this.components[name] = data;

  // call queue ?
  if (this.queue[name]) {

    // call each import request
    this.queue[name].forEach(function (cb) {
      cb(that.components[name]);
    });

    // clean up
    delete this.queue[name];

  }
};

App.prototype.reload = function (name, data) {
  console.log("Reload module %s", name);
  delete this.components[name];
  this.components[name] = data;
};


var app = new App();

app.import("module1", function(data){
  console.log("Imported module1");
  setInterval(function(){
    console.log(data, app.components["module1"]);  
  }, 1000);  
});

setTimeout(function(){
  app.export("module1", {data: "Hello World"})
}, 1000);

setTimeout(function(){
  app.reload("module1", {data: "Changed data"});
}, 5000);

如果您运行此snipet,您可以看到: app.components.module1已更新,但不是更新回调范围。 我该如何解决这个问题?

我想如果app.components.module1也更新了cb中的变量。

1 个答案:

答案 0 :(得分:0)

您无法删除对象,因为您将丢失参考。但是你可以改变它:

App.prototype.reload = function (name, data) {
  console.log("Reload module %s", name);
  Object.keys(this.components[name]).forEach(key =>{
    delete this.components[name][key];
  });
  Object.assign(this.components[name],data);
};

(不适用于原始类型,不是最好的代码设计)

或者你实现类似于侦听器模式:

class Listener {
 constructor(){
    this.listeners = new Map();
  }
  on(event,handler){
    if( this.listeners.has(event) ){
      this.listeners.get(event).push(handler);
    }else{
      this.listeners.set(event,[handler]);
    }
  }

  trigger(event, ...params){
    (this.listeners.get(event) || []).forEach( handler => handler(...params));
  }
}

所以可以这样做:

const loader = new Listener();
loader.on("sth",console.log);

loader.trigger("sth",{a:1});