我刚刚开始使用原型JavaScript,并且在弄清楚this范围更改时如何从原型函数内部保留对主对象的引用时遇到了麻烦。让我说明一下我的意思(我在这里使用jQuery):
this
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:
myfunc
var myThis = this;
然后myThis.myValue用于访问主要对象的属性。但是,当我拥有一大堆原型函数时会发生什么MyClass?我是否必须this在每个文件的开头都保存对它的引用?似乎应该有一种更清洁的方法。那么这样的情况呢:
myThis.myValue
MyClass
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对象。
varmyThis=this;
doSomething
jQuery
有人建议我使用全局变量来保存对原始文件的引用this,但这对我来说似乎是个坏主意。我不想污染全局名称空间,这似乎会使我无法实例化两个不同的MyClass对象而又不会相互干扰。
有什么建议?有什么干净的方法可以做我想要做的事吗?还是我的整个设计模式有缺陷?
为了保留上下文,该bind方法非常有用,它是最近发布的ECMAScript5thEdition规范的一部分,此函数的实现很简单(只有8行):
bind
// 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内部关键字将引用全局对象,它将警告“全局测试”。
fx1
obj.method()
现在,方法fx2是该bind方法生成的新函数,它将调用我们的函数以保留上下文并正确传递参数,它将警告“ obj test 1,2,3,4,5”,因为我们调用了该函数将其添加了两个论据,它已经 绑定 了前三个。
fx2