1

我正在尝试使用这种模式创建一个“构造函数”:

function mything() {
    var a, b, c;
    ...
    return {
        publicFunc: function() {
            //access private vars here
        }
    };
}

//usage

mything1 = mything();
mything2 = mything();

问题是,我还想让它通过instanceof测试:

assert(mything1 instanceof mything === true);

有没有办法做到这一点?使用常规构造函数将不起作用,因为原型函数无法访问私有变量。

4

2 回答 2

4

您需要使用稍微不同的设计模式来拥有私有变量并将其设置为 instanceof mything

function mything() {
    var a, b, c;
    ...
    this.publicFunc = function() {
            //access private vars here
        }
    };
}

//usage

var mything1 = new mything();
mything1.publicFunc();
var mything2 = new mything();
于 2013-03-28T23:07:28.027 回答
1

这在技术上是可行的,但您可以更优雅地解决您的问题(解释如下):

function mything() {
  var a, b, c;

  function PrivateConstructor() {
    this.publicFunc = function() {}
  }

  // this is the magic that makes it happen:
  PrivateConstructor.prototype = mything.prototype; 

  return new PrivateConstructor();

}

mything1 = mything();
assert(mything1 instanceof mything); // passes

或者,使用 EcmaScript 5 功能:

function mything() {
  var a, b, c;

  var object = Object.create(mything.prototype);
  object.publicFunc = function() {}

  return object;
}

mything1 = mything();
assert(mything1 instanceof mything); // passes

解释

instanceof如果右侧操作数是一个函数,并且存储在该函数属性中的对象包含在左侧操作数的原型链中,则运算符将返回true prototype

第一个示例mything.prototype将另一个临时函数作为“原型”属性重用,该函数仅用于生成一个对象(mything.prototype在其原型链中)。第二个示例通过mything.prototype直接从 with继承来创建这样的对象Object.create()

两个对象都继承自mything.prototype并因此将通过object instanceof mything测试。

话虽如此,jfriend00 提出的模式开销更少,并且更易于阅读,同时提供了您想要的功能。

于 2013-03-28T23:25:55.137 回答