【问题标题】:"Faking" a JavaScript Constructor [closed]“伪造”一个JavaScript构造函数[关闭]
【发布时间】:2011-09-23 01:18:47
【问题描述】:

上下文

我正在努力提高我的 JavaScript 技能,并且我正在学习更多关于原型设计的知识。我想更好地理解这个问题中的代码以及它的任何限制或问题。

还有一件不明显的事情是定义更复杂的构造函数,这些构造函数不仅仅是简单的初始化。我想要做的是有一个类在创建时调用 Web 服务,而无需在初始化后立即调用方法。

我所做的是创建一个属性并为其分配一个自调用匿名方法。它似乎像我想要的那样工作,但我不知道是否有更好的方法。

守则

function AsyncOrderLine(productID) {

    var context = this;

    this.autoValue;
    this._productID = productID;
    this._asyncRequestComplete = false;


    this.hello = function () {
        alert("hello world");
    }

    this.constructor = (function () {
        context.hello();
        context.autoValue = "testing: " + productID + "(" +        context._asyncRequestComplete + ")";
    })()

}

结果

 var _asyncOrderLine = new AsyncOrderLine(1001);

显示警报:“Hello World”

 _asyncOrderLine.autoValue = testing: 1001(false)
 _asyncOrderLine.constructor = 'undefined'

在这种情况下,我希望构造函数在创建对象后保持未定义。

问题

有没有更好的方法来做到这一点?使用这种方法会不会有任何不可预见的副作用?

【问题讨论】:

  • 一般来说,你所做的一切都很好。您根本不需要公开一个名为构造函数的属性。您可以让函数在 AsyncOrderLine 中运行。然后你可以避免将 undefined 分配给你的 _instance.constructor。但是,这个问题非常广泛,很难正式回答。有无数种方法可以完成您所做的事情。
  • "我所做的是创建一个属性并为其分配一个自调用匿名方法。" - 你为什么这样做?
  • @ŠimeVidas 我打算将其称为构造函数以外的名称并为其赋值。我为这个问题重命名了它。问题是我希望在创建对象时运行一个函数。
  • @dmck 但是为什么要将代码放在嵌套函数中,为什么要将函数的返回值分配给实例的属性呢?
  • context 变量命名不当,它是对实例的引用(即构造函数创建的普通对象)。为什么不称它为 asyncOrderLine,因为它就是这样(如果构造函数名称是描述性的)。

标签: javascript function-prototypes


【解决方案1】:

没有必要把这样的事情复杂化。你可以在构造函数中运行任何你想要的代码:

function AsyncOrderLine(productID) {

    this.autoValue;
    this._productID = productID;
    this._asyncRequestComplete = false;

    this.hello = function () {
        alert("hello world");
    }

    // Run whatever arbitrary code you want...    
    this.hello();
    this.autoValue = "testing: " + productID + "(" + context._asyncRequestComplete + ")";
}

【讨论】:

    【解决方案2】:

    正如其他人所说,构造函数属性没有理由。您可以在函数体中运行您想要的任何代码,它将在对象初始化时运行。如果您想运行异步代码(如 ajax 调用),那么您可能需要将完成函数传递给构造函数,以便对象的创建者可以知道对象初始化的异步部分何时实际完成,因为它不会当对象从它的初始化返回时是完整的。看起来像这样:

    function function AsyncOrderLine(productID, fn) {
        // initialization code for the object here
        this._asyncRequestComplete = false;
        ...
    
        // kick of asychronous networking call here
        var context = this;
        $.getJSON(url, function(data) {
            // process the data response into our object here
            context.whatever = data;
    
            context._asyncRequestComplete = true;
            // call the completion function with `this` set to point to our object here 
            // so the creator of this object can know when the async part of
            // initialization is actually done
            fn.call(context);
        });
    }
    

    然后,调用者会做这样的事情:

    var x = new AsyncOrderLine(id, function() {
        // can reference new object and it's methods and properties via "this"
        alert("orderLine object is now completely initialized");
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多