0

Is there a more succinct way to express this than three distinct, procedural operations? Something more object notation-like, or at least all within the body of the Name function?

Problem:

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

Name.prototype = new String;

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

Test:

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'
}));

Expected output:

< "dean, jimmy"
< true
< true
< true
< "dean, jimmy"
< "dean, jimmy"
3
  • Nitpicking; do you mean partFirst instead? Commented Dec 21, 2011 at 21:09
  • 1
    @pimvdb—sometimes it's better to just edit the question for small typos. Commented Dec 22, 2011 at 0:28
  • I don't understand why you want the prototype to be an instance of String. As long as toString returns a string (which seems to be sensible), then you can call any method that would be inherited from String without the assignment of a string to the constructor's prototype. Commented Dec 22, 2011 at 0:33

3 Answers 3

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();
Sign up to request clarification or add additional context in comments.

11 Comments

Your method does not inherit its prototype from the String constructor any more. Side note: A valueOf method has to be defined, to prevent the following error: String.prototype.valueOf called on incompatible Object (FF 8.0, using ""+(new Name()) as a test case).
noted, but explicitly calling .toString() as the OP intends to works fine. And wouldn't a parameter-less constructor call for Name be a programmer error? Updated link above to show (new Name("first", "last") + "")
new Name, new Name() and new Name(void 0, void 0) are equivalent and valid (void 0 === undefined, by the way). As for the error, it occurs when using the OP's inheritance concept: jsfiddle.net/wKvqQ/4
@RobW found that the String.toString() uses the valueOf so all you have to do is define the valueOf. check link above again.
Just define both methods, if you like the current way: this.valueOf = this.toString = .., to also account for an explicit .toString() call. However, setting a prototype instead of using this.____ = is more efficient and readable.
|
0

Here's how I do it:

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";
}

Comments

0

Sure. Use 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");

Now ES5 is a bit ugly, so you can use some mechanism for ES5 OO sugar, let's take pd as an example:

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'
}));

Of course output is as expected Live Example

4 Comments

This is far uglier and verbose then the OP's own solution, not to mention the added need for a polyfill to account for any IE < 9 ...developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
@jondavidjohn it can be polyfilled to work in IE6+ and all other major browsers
+1 for posting the obvious alternative. But I agree that the original is more elegant (provided the assignment of a String to Name.prototype is removed). I never understood the need for Object.create, it's a Crockfordism.
@RobG I prefer to not think in terms of constructors. Constructors are ugly, all you need is a prototype object. The only thing that's ugly with the Object.create solution is that instantiation and initialization is a two step thing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.