2011-12-21 2 views
0

Есть ли более краткий способ выразить это, чем три различных процедурных операции? Что-то более похожее на объект, или, по крайней мере, все внутри тела функции Name?Наследование прототипа JavaScript: сжатый синтаксис?

Проблема:

function Name(first, last) { 
    this.first = first; 
    this.last = last; 
} 

Name.prototype = new String; 

Name.prototype.toString = function() { 
    return this.last + ', ' + this.first; 
}; 

Тест:

console.log(new Name("jimmy", "dean").toString()) 
console.log(new Name() instanceof Name); 
console.log(new Name() instanceof String); 
console.log(new Name() instanceof Object); 
console.log(Name.prototype.toString.call(new Name('jimmy', 'dean'))); 
console.log(Name.prototype.toString.call({ 
    first: 'jimmy', 
    last: 'dean' 
})); 

Ожидаемый результат:

< "dean, jimmy" 
< true 
< true 
< true 
< "dean, jimmy" 
< "dean, jimmy" 
+0

Nitpicking; вы имеете в виду 'partFirst' вместо этого? – pimvdb

+1

@ pimvdb - иногда лучше просто отредактировать вопрос для небольших опечаток. – RobG

+0

Я не понимаю, почему вы хотите, чтобы прототип был экземпляром String. Пока * toString * возвращает строку (что кажется разумным), вы можете вызывать любой метод, который будет наследоваться от String без назначения строки прототипу конструктора. – RobG

ответ

1

Example

function Name(first, last) { 
    this.partFirst = first; 
    this.partLast = last; 
    this.valueOf = this.toString = function() { 
     return this.partLast + ', ' + this.partFirst; 
    } 
} 
Name.prototype = new String(); 
+0

Ваш метод больше не наследует его прототип от конструктора 'String'. Сторона примечания: метод 'valueOf' должен быть определен для предотвращения следующей ошибки:' String.prototype.valueOf вызывается несовместимым объектом' (FF 8.0, используя '' "+ (новое имя())' в качестве тестового примера). –

+0

отметил, но явно вызывает '.toString()', поскольку OP намеревается работать нормально. И не будет ли конструктор без конструктора вызывать «Имя» ошибкой программиста? Обновленная ссылка выше, чтобы показать '(новое имя (« первый »,« последний ») +« »)' – jondavidjohn

+0

'new Name ',' new Name() 'и' new Name (void 0, void 0) 'эквивалентны и valid * ('void 0 === undefined', кстати) *. Что касается ошибки, это происходит при использовании концепции наследования OP: http://jsfiddle.net/wKvqQ/4/ –

0

Несомненно. Используйте Object.create.

var Name = Object.create(String.prototype, { 
    toString: { value: function _toString() { 
    return this.partLast + ', ' + this.partFirst; 
    } }, 
    constructor: { value: function _constructor(first, last) { 
    this.partFirst = first; 
    this.partLast = last; 
    return this; 
    } } 
}); 

var name = Object.create(Name).constructor("foo", "bar"); 

Теперь ES5 немного некрасиво, так что вы можете использовать some mechanism for ES5 OO sugar, давайте pd в качестве примера:

var Name = pd.make(String.prototype, { 
    toString: function _toString() { 
    return this.partLast + ', ' + this.partFirst; 
    }, 
    constructor: function (first, last) { 
    this.partFirst = first; 
    this.partLast = last; 
    }, 
    beget: pd.Base.beget 
}); 

console.log(Name.beget("jimmy", "dean").toString()) 
console.log(Name.isPrototypeOf(Name.beget())); 
console.log(String.prototype.isPrototypeOf(Name.beget())); 
console.log(Object.prototype.isPrototypeOf(Name.beget())); 
console.log(Name.toString.call(Name.beget('jimmy', 'dean'))); 
console.log(Name.toString.call({ 
    partFirst: 'jimmy', 
    partLast: 'dean' 
})); 

Конечно выход, как ожидается Live Example

+0

Это гораздо более уродливое и подробное, чем собственное решение OP, не говоря уже о добавленной необходимости полиполя для учета любого IE < 9 ... https: //developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/create#Polyfill – jondavidjohn

+0

Я также не уверен, что полиполк будет работать с пользовательскими объектами ... – jondavidjohn

+0

@jondavidjohn это может быть заполненным для работы в IE6 + и всех других основных браузерах – Raynos

0

Вот как я это делаю :

function subclass(constructor, superConstructor) { 
    function surrogateConstructor() { } 

    surrogateConstructor.prototype = superConstructor.prototype; 

    var prototypeObject = new surrogateConstructor(); 
    prototypeObject.constructor = constructor; 

    constructor.prototype = prototypeObject; 
} 



/* Base object */ 
function BaseItem() { 
    this.type = 'baseitem'; 
    this.obj = null; 
} 
BaseItem.prototype.render = function() { 
    return "foo"; 
} 



/* Sub class */ 
function InteractionArea() { 
    BaseItem.call(this); 
    this.type = 'interactionarea' 
    this.obj = document.createElement('div') 
} 
subclass(InteractionArea, BaseItem); 

//here come the overrides 
InteractionArea.prototype.render = function() { 
    return "foobar"; 
} 
InteractionArea.prototype.render2 = function() { 
    return "foobar"; 
} 



/* Sub-sub class */ 
function InteractionArea2() { 
    InteractionArea.call(this); 
    this.type = 'interactionarea2'; 
    this.obj = false; 
} 
subclass(InteractionArea2, InteractionArea); 

InteractionArea2.prototype.render = function() { 
    return "bar"; 
} 
Смежные вопросы