保存上下文

时间:2018-05-12 12:31:15

标签: javascript this prototype

我发现了一些有趣的问题。任务是为所有子函数创建包装器,这会延迟实现。

function someFunc() {
  console.log(this.someProp);
}

var obj1 = {
  someProp: 1,
  method1: someFunc,
};

var obj2 = {
  someProp: 2,
  method2: someFunc,
};
Function.prototype.defer = function(ms) {
  let self = this;
  setTimeout(self, ms) //<<-- lose context(obj1, obj2)
};
obj1.method1(); // 1
obj2.method2(); // 2
obj1.method1.defer(1000); // 1 after 1 sec, now is undefined
obj2.method2.defer(1000); // 2 after 1 sec, now is undefined

2 个答案:

答案 0 :(得分:0)

尝试使用bind保留执行上下文。 bind()允许在调用函数或方法时设置将哪个特定对象绑定到this

function someFunc() {
  console.log(this.someProp);
}

var obj1 = {
  someProp: 1,
  method1: someFunc,
};

var obj2 = {
  someProp: 2,
  method2: someFunc,
};
Function.prototype.defer = function(ms) {
  setTimeout(this, ms) //<<-- lose context(obj1, obj2)
};
obj1.method1(); // 1
obj2.method2(); // 2
obj1.method1.bind(obj1).defer(1000); // 1 after 1 sec, now is undefined
obj2.method2.bind(obj2).defer(1000); // 2 after 1 sec, now is undefined

答案 1 :(得分:0)

对'obj.method'的直接调用有效,因为当一个函数作为一个对象的方法被调用时,它被设置为调用该方法的对象。

defer函数不是作为对象的方法调用的,它被称为Function的一个方法,它是从它获取它的方法

对代码的最小修改'修复'是:

function someFunc() {
  console.log(this.someProp);
}

var obj1 = {
  someProp: 1,
  method1: someFunc
};

var obj2 = {
  someProp: 2,
  method2: someFunc
};
Object.prototype.defer = function(func, ms) {
  typeof this[func] === 'function' && setTimeout(this[func].bind(this), ms) //<<-- lose context(obj1, obj2)
};
obj1.method1(); // 1
obj2.method2(); // 2
obj1.defer('method1', 1000); // 1 after 1 sec
obj2.defer('method2', 1000); // 2 after 1 sec

根据您的实际用例,除了向内置类型添加方法之外,可能有更好的方法。例如,使obj1,obj2成为您声明的新类的实例,这些类在您的代码中扩展基类,您可以在其中提供诸如defer()函数之类的常用方法。