一尘不染

在JavaScript原型函数中保留对“ this”的引用

javascript

我刚刚开始使用原型JavaScript,并且在弄清楚this范围更改时如何从原型函数内部保留对主对象的引用时遇到了麻烦。让我说明一下我的意思(我在这里使用jQuery):

MyClass = function() {
  this.element = $('#element');
  this.myValue = 'something';

  // some more code
}

MyClass.prototype.myfunc = function() {
  // at this point, "this" refers to the instance of MyClass

  this.element.click(function() {
    // at this point, "this" refers to the DOM element
    // but what if I want to access the original "this.myValue"?
  });
}

new MyClass();

我知道我可以通过在以下内容的开头保留对主对象的引用myfunc

var myThis = this;

然后myThis.myValue用于访问主要对象的属性。但是,当我拥有一大堆原型函数时会发生什么MyClass?我是否必须this在每个文件的开头都保存对它的引用?似乎应该有一种更清洁的方法。那么这样的情况呢:

MyClass = function() {
  this.elements $('.elements');
  this.myValue = 'something';

  this.elements.each(this.doSomething);
}

MyClass.prototype.doSomething = function() {
  // operate on the element
}

new MyClass();

在那种情况下,我无法创建对主对象的引用,varmyThis=this;因为即使this上下文中的原始值doSomething也是一个jQuery对象,而不是一个MyClass对象。

有人建议我使用全局变量来保存对原始文件的引用this,但这对我来说似乎是个坏主意。我不想污染全局名称空间,这似乎会使我无法实例化两个不同的MyClass对象而又不会相互干扰。

有什么建议?有什么干净的方法可以做我想要做的事吗?还是我的整个设计模式有缺陷?


阅读 283

收藏
2020-04-25

共1个答案

一尘不染

为了保留上下文,该bind方法非常有用,它是最近发布的ECMAScript5thEdition规范的一部分,此函数的实现很简单(只有8行):

// The .bind method from Prototype.js 
if (!Function.prototype.bind) { // check if native implementation available
  Function.prototype.bind = function(){ 
    var fn = this, args = Array.prototype.slice.call(arguments),
        object = args.shift(); 
    return function(){ 
      return fn.apply(object, 
        args.concat(Array.prototype.slice.call(arguments))); 
    }; 
  };
}

您可以在示例中使用它,如下所示:

MyClass.prototype.myfunc = function() {

  this.element.click((function() {
    // ...
  }).bind(this));
};

另一个例子:

var obj = {
  test: 'obj test',
  fx: function() {
    alert(this.test + '\n' + Array.prototype.slice.call(arguments).join());
  }
};

var test = "Global test";
var fx1 = obj.fx;
var fx2 = obj.fx.bind(obj, 1, 2, 3);

fx1(1,2);
fx2(4, 5);

在第二个示例中,我们可以观察到更多有关的行为bind

它基本上会生成一个新函数,它将负责调用我们的函数,并保留函数上下文(this值),该上下文定义为的第一个参数bind

其余参数仅传递给我们的函数。

请注意,在此示例中,函数fx1的调用没有任何对象上下文_(obj.method()),就像简单的函数调用一样,在这种类型的调用中,this内部关键字将引用全局对象,它将警告“全局测试”。

现在,方法fx2是该bind方法生成的新函数,它将调用我们的函数以保留上下文并正确传递参数,它将警告“ obj test
1,2,3,4,5”,因为我们调用了该函数将其添加了两个论据,它已经 绑定 了前三个。

2020-04-25