4

目前,我通过声明构造(常规函数)在 javascript 中创建对象,然后像这样向原型添加方法

function Test(){
}
Test.prototype.test1 = function(){
    var me = this;
}

但是,我想避免var me = this在每个函数的顶部声明。以下似乎可行,但似乎效率很低:

$(document).ready(function(){
var n = 0;
(function(){

     function createTest(){
        var me;
        function Test(){
            this.n = n;
            this.testArr = [1, 2, 3, 4];
            n++;
        }

        Test.prototype.test1 = function(){
            me.test2();
        };
        Test.prototype.test2 = function(){
            alert(me.n);
            $.getJSON('test.php', {}, function(reply)
                //want to be able to use 'me' here
                me.newField = reply;
            });
        };

        var t = new Test();
        me = t;
        return t;
    }
    window['createTest'] = createTest;
})();

var t = createTest();
t.test1();
var t2 = createTest();
t2.test1();
t.test1();
});

这段代码输出了预期的结果,但它实际上是否像看起来那样低效(每次调用 createTest() 时都会重新声明 Test 对象)?

Anyhoo,这似乎有点hacky......有没有更好的完全不同的方法来做到这一点?

编辑:我想这样做的真正原因是,像 test2 中的回调这样的回调将引用正确的this.

4

3 回答 3

2

我意识到您的问题没有用 jQuery 标记,但是您在示例中使用了它,因此我的解决方案也使用了 jQuery。

我有时使用该$.proxy函数来避免回调上下文。看看这个简单的 jsfiddle 示例。来源如下。

function Test(){
    this.bind();
}

Test.prototype.bind = function(){
    $('input').bind('change', $.proxy(this.change, this)); 
    // you could use $.proxy on anonymous functions also (as in your $.getJSON example)
}
Test.prototype.change = function(event){ 
    // currentField must be set from e.target
    // because this is `Test` instance
    console.log(this instanceof Test);          // true
    console.log(event.target == $('input')[0]); // true
    this.currentField = event.target;           // set new field
};

function createTest(){
    return new Test();
}

$(function(){ // ready callback calls test factory
    var t1 = createTest();
});
于 2011-03-15T21:29:32.413 回答
2

您可以做的是将当前this值绑定到 afunction并将副本存储在某处。(为了效率。)

if (!Function.prototype.bind) {
    // Most modern browsers will have this built-in but just in case.
    Function.prototype.bind = function (obj) {
        var slice = [].slice,
            args = slice.call(arguments, 1),
            self = this,
            nop = function () { },
            bound = function () {
                return self.apply(this instanceof nop ? this : (obj || {}),
                                    args.concat(slice.call(arguments)));
            };
        nop.prototype = self.prototype;
        bound.prototype = new nop();
        return bound;
    };
}

function Test(n) {
    this.n = n;
    this.callback = (function () {
        alert(this.n);
    }).bind(this)
}

Test.prototype.test1 = function () {
    this.test2();
}

Test.prototype.test2 = function () {
    doSomething(this.callback);
}

function doSomething(callback) {
    callback();
}

var t = new Test(2);
t.test1();
于 2011-03-15T20:37:26.077 回答
0

大多数时候,我只是声明一个引用 this 的局部变量,只要我需要在回调中引用 this:

function Foo() {
}

Foo.prototype.bar = function() {
  var that=this;
  setTimeout(function() {
     that.something="This goes to the right object";
  }, 5000);
}

或者,您可以像这样使用 bind():

Function Foo() {
   this.bar = this.bar.bind(this);
   // ... repeated for each function ...
}

Foo.prototype.bar = function() {
}

这给你的是,每次你创建一个新的 Foo 实例时,方法都绑定到当前实例,所以你可以将它们用作 setTimeout() 等的回调函数。

于 2011-03-15T23:37:18.207 回答