Можно ли задать тип объекта Javascript?
Я пытаюсь использовать некоторые из более продвинутых функций OO Javascript, следуя шаблону "супер конструктора" Дуга Кроуфорда. Тем не менее, я не знаю, как устанавливать и получать типы из моих объектов с использованием собственной системы Javascript. Вот как это у меня сейчас:
function createBicycle(tires) {
var that = {};
that.tires = tires;
that.toString = function () {
return 'Bicycle with ' + tires + ' tires.';
}
}
Как установить или получить тип моего нового объекта? Я не хочу создавать атрибут type
, если есть правильный способ сделать это.
Есть ли способ переопределить операторы typeof
или instanceof
для моего пользовательского объекта?
Ответы
Ответ 1
Оператор instanceof
, внутри, после того как оба значения операнда собраны, использует абстрактный [[HasInstance]](V)
, которая опирается на цепочку прототипов.
Образец, который вы разместили, состоит только в добавлении объектов, а цепочка прототипов вообще не используется.
Если вы действительно хотите использовать оператор instanceof
, вы можете комбинировать другую технику Crockford, 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
Более подробная статья:
Ответ 2
Если вы объявите 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);
Ответ 3
если вы используете конструктор, лучшее решение, чем 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"
Объяснение ПОЧЕМУ это лучший способ сделать это, полагается в Это сообщение.
Ответ 4
Только в Firefox вы можете использовать свойство __proto__
для замены прототипа для объекта. В противном случае вы не можете изменить тип объекта, который уже был создан, вы должны создать новый объект, используя ключевое слово new
.
Ответ 5
По-моему, в правильно спроектированном типа, вам не нужно знать типы отдельных объектов. Но я, кажется, в меньшинстве эта точка.
Если у вас есть идентификация типа, сделайте это явным.
MyClass.prototype.type = "MyClass";
Он надежный и портативный, по крайней мере для ваших объектов. Он также работает контексты. Объектами DOM являются другие материя, хотя вы можете делать вещи проще для себя с помощью
window.type = "window";
и т.д.
Я считаю, что приведенная выше цитата была написана Дуглас Крокфорд.