14

我正在尝试使用 Javascript 的一些更高级的 OO 功能,遵循 Doug Crawford 的“超级构造函数”模式。但是,我不知道如何使用 Javascript 的本机类型系统从我的对象中设置和获取类型。这是我现在的样子:

function createBicycle(tires) {
    var that = {};
    that.tires = tires;
    that.toString = function () {
        return 'Bicycle with ' + tires + ' tires.';
    }
}

如何设置或检索新对象的类型?type如果有正确的方法,我不想创建属性。

有没有办法覆盖我的自定义对象的typeofor运算符?instanceof

4

5 回答 5

15

运算符在instanceof内部,在收集两个操作数值之后,使用[[HasInstance]](V)依赖于原型链的抽象操作。

您发布的模式仅包含增强对象,并且根本不使用原型链。

如果你真的想使用instanceof操作符,你可以结合 Crockford 的另一种技术,原型继承超级构造函数,基本上是从 继承Bicycle.prototype,即使它是一个空对象,只是为了愚弄instanceof

// helper function
var createObject = function (o) {
  function F() {}
  F.prototype = o;
  return new F();
};

function Bicycle(tires) {
    var that = createObject(Bicycle.prototype); // inherit from Bicycle.prototype
    that.tires = tires;                         // in this case an empty object
    that.toString = function () {
      return 'Bicycle with ' + that.tires + ' tires.';
    };

    return that;
}

var bicycle1 = Bicycle(2);

bicycle1 instanceof Bicycle; // true

更深入的文章:

于 2009-12-17T05:34:18.720 回答
3

如果你Bicycle这样声明,instanceof将起作用:

function Bicycle(tires) {
  this.tires = tires;
  this.toString = function () {
    return 'Bicycle with ' + tires + ' tires.';
  }
}

var b = new Bicycle(2);
console.log(b instanceof Bicycle);
于 2009-12-17T03:43:58.037 回答
2

如果您使用的是构造函数,比 instanceOf 更好的解决方案是:

Object.toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}


toType({a: 4}); //"object"
toType([1, 2, 3]); //"array"
(function() {console.log(toType(arguments))})(); //arguments
toType(new ReferenceError); //"error"
toType(new Date); //"date"
toType(/a-z/); //"regexp"
toType(Math); //"math"
toType(JSON); //"json"
toType(new Number(4)); //"number"
toType(new String("abc")); //"string"
toType(new Boolean(true)); //"boolean"
toType(new CreateBicycle(2)); //"createbicycle"

为什么这是最好的方法的解释依赖于这篇文章。

于 2014-05-22T03:06:34.603 回答
1

仅在 Firefox 中,您可以使用该__proto__属性来替换对象的原型。否则,您无法更改已创建对象的类型,您必须使用new关键字创建新对象。

于 2009-12-17T03:41:13.313 回答
0

在我看来,在正确设计的类型层次结构中,您不需要知道各个对象的类型。但在这一点上,我似乎是少数。

如果您必须有类型标识,请明确说明。

MyClass.prototype.type = "MyClass";

它可靠且便携,至少对于您的对象而言。它也适用于不同的上下文。DOM 对象是另一回事,尽管您可以使用

window.type = "窗口";

等等。

我相信上面的引述是Douglas Crockford写的。

于 2009-12-17T03:45:17.037 回答