避免在外部称为原型方法中丢失对象实例

Avoiding loss of object instance in externally called prototypal method

本文关键字:对象 实例 方法 原型 外部      更新时间:2023-09-26

对象在下面c用来克服对象实例丢失的技术b对我来说有点臭。有没有更可接受的方法?

function A()  {
    this.prop = "cat";
}
A.prototype.test = function() {
    console.log(this.prop);
}
function B() {}
B.prototype.test = function(meth) {
    meth();
}
function C() {}
C.prototype.test = function(obj, meth) {
    obj[meth]();
}
var a = new A();
var b = new B();
var c = new C();
//tests
b.test(a.test);     // undefined
c.test(a, 'test');  // cat

复制自: https://stackoverflow.com/a/16063711/1641941

这个变量

在所有示例代码中,你将看到this引用当前实例。

this 变量实际上指的是调用对象,它指的是函数之前的对象。

要澄清,请参阅以下代码:

theInvokingObject.thefunction();

这引用错误对象的实例通常是在附加事件侦听器、回调或超时和间隔时。在接下来的 2 行代码中,我们pass函数,我们不会调用它。传递函数是:someObject.aFunction,调用它是:someObject.aFunction()this值不是指声明函数的对象,而是指向invokes函数的对象。

setTimeout(someObject.aFuncton,100);//this in aFunction is window
somebutton.onclick = someObject.aFunction;//this in aFunction is somebutton

要在上述情况下进行this,请参阅someObject,您可以传递闭包而不是直接传递函数:

setTimeout(function(){someObject.aFuncton();},100);
somebutton.onclick = function(){someObject.aFunction();};

我喜欢定义函数,这些函数在原型上返回闭包函数,以便对闭包范围中包含的变量进行精细控制。

var Hamster = function(name){
  var largeVariable = new Array(100000).join("Hello World");
  // if I do 
  // setInterval(function(){this.checkSleep();},100);
  // then largeVariable will be in the closure scope as well
  this.name=name
  setInterval(this.closures.checkSleep(this),1000);
};
Hamster.prototype.closures={
  checkSleep:function(hamsterInstance){
    return function(){
      console.log(typeof largeVariable);//undefined
      console.log(hamsterInstance);//instance of Hamster named Betty
      hamsterInstance.checkSleep();
    };
  }
};
Hamster.prototype.checkSleep=function(){
  //do stuff assuming this is the Hamster instance
};
var betty = new Hamster("Betty");

不需要传递字符串,您仍然可以传递函数:

C.prototype.test = function(obj, meth) {
    meth.call(obj);
}
// ...
c.test(a, a.test);  // cat

Function#call调用一个函数,明确地将调用中的this设置为您call给出的第一个参数。(还有Function#apply;唯一的区别是你如何为函数传递额外的参数。

但通常(并非总是)这被认为是调用者的问题,他们通常会使用 Function#bind(在支持 ES5 的引擎上或使用填充程序)来解决它:

c.test(a.test.bind(a));

。或使用闭合:

c.test(function() {
    a.test();
});

。在这两种情况下,您只需在C.prototype.test内调用meth()

Function#bind创建一个新函数,该函数在调用时将调用原始函数,并将this设置为您传递给bind的值,然后返回该新函数。

我博客上的相关文章:

  • 神话般的方法
  • 你必须记住this
  • 闭合并不复杂