Могу ли я установить тип объекта Javascript? - PullRequest
14 голосов
/ 17 декабря 2009

Я пытаюсь использовать некоторые из более продвинутых OO-функций Javascript, следуя шаблону Дуга Кроуфорда «супер конструктор». Тем не менее, я не знаю, как устанавливать и получать типы из моих объектов, используя систему родных типов Javascript. Вот как у меня это сейчас:

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

Как я могу установить или получить тип моего нового объекта? Я не хочу создавать атрибут type, если есть правильный способ сделать это.

Есть ли способ переопределить операторы typeof или instanceof для моего пользовательского объекта?

Ответы [ 5 ]

15 голосов
/ 17 декабря 2009

Оператор instanceof внутри, после того, как оба значения операнда собраны, использует абстрактную операцию [[HasInstance]](V), которая опирается на цепочку прототипов.

Шаблон, который вы разместили, состоит просто из дополнения объектов, а цепочка прототипов вообще не используется.

Если вы действительно хотите использовать оператор instanceof, вы можете объединить другую технику Крокфорда, Prototypal Inheritance с суперконструкторами , в основном для наследования от 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

Более глубокая статья:

3 голосов
/ 17 декабря 2009

Если вы объявите 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);
2 голосов
/ 22 мая 2014

если вы используете конструктор, лучшее решение, чем 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"

Объяснение ПОЧЕМУ это лучший способ сделать это, опираясь на Этот пост.

1 голос
/ 17 декабря 2009

Только в Firefox вы можете использовать свойство __proto__ для замены прототипа для объекта. В противном случае вы не можете изменить тип объекта, который уже был создан, вы должны создать новый объект, используя ключевое слово new.

0 голосов
/ 17 декабря 2009

На мой взгляд, в правильно оформленном тип heirarchy, вам не нужно знать типы отдельных объектов. Но я, кажется, в меньшинстве на этот момент.

Если вы должны иметь идентификацию типа, сделайте это явным.

MyClass.prototype.type = "MyClass";

Это надежный и портативный, по крайней мере для ваших объектов. Это также работает через контексты. DOM-объекты - это другое важно, хотя вы можете сделать вещи проще для себя с

window.type = "window";

и т. Д.

Я полагаю, что приведенная выше цитата была написана Дугласом Крокфордом .

...