1

I'd like to know if this is possible.

number = function(n){

  var num = n;

  this.add = function(x){
    return num + x;
  }

  return num;

}

alert(number(7)); //returns 7

seven = new number(7);
alert(seven.add(3)); // returns 10
alert(seven); // want this to return 7, but will return [object Object]

I don't need number(7) to return 7, but it would be nice.

5
  • You may want to know about function factory pattern: developer.mozilla.org/en/JavaScript/Guide/Closures Commented Jun 9, 2012 at 13:51
  • 2
    You want to have both a number value and it having properties such as .add? Commented Jun 9, 2012 at 13:53
  • Reminds me to pythons decorator pattern. Commented Jun 9, 2012 at 13:54
  • @pimvdb yes, exactly. Not limited to numbers either, if possible. Commented Jun 9, 2012 at 13:55
  • 1
    @user1446253: Ah OK; the answers provided will work but you won't be able to conveniently work with them in code, e.g. seven === 7 is false. Commented Jun 9, 2012 at 13:57

5 Answers 5

7

First return num; has no effect in your code. The object returned by the function is this. If a constructor function does not return an object explicitly, it will always implicitly return this (see step 3 in the MDN documentation).

That said, there are two methods you could override, namely, toString [MDN] and valueOf [MDN]:

function MyNumber(n){
  this.num = n;
}

MyNumber.prototype.add = function(x){
    return this.num + x; // or `this + x` since we implemented `valueOf`
};

// Is called whenever the object has to be converted to a string
// e.g. alert(myNumber) ; myNumber + " is the answer to all questions"
MyNumber.prototype.toString = function() {
    return this.valueOf().toString(); // or `this.num.toString()`
};

// Is called whenever the object has to be converted to a primitive value
// e.g. myNumber + 42 ; myNumber == 42
MyNumber.prototype.valueOf = function() {
    return this.num;
};

The added benefit of overwriting valueOf is that JavaScript will call this method also internally the convert to object to a primitive value.

For example, using an instance as operand in normal addition would work too (instead of calling .add):

> var n = new MyNumber(7);
> n + 10
  17

That said, if you just want to create a wrapper for primitive types, then don't do that.

As pimvdb mentions in his comment, strict comparison would fail (for example). That is to be expected and one of the reasons why to avoid the object versions of primitive values (Number, String, Boolean) (i.e. "foo" === new String("foo") is false as well). Objects simply don't behave like primitives and mixing these creates more complicated code.

Sign up to request clarification or add additional context in comments.

2 Comments

return num has an effect if I am just calling it as a function though right? And no adverse effect when I don't?
Yes, if you simply call it as a function, then it would return the number you passed to it (with return num;). But by doing so, add would be assigned to the global object (window) so you really should not call it as a normal function.
4

Give it a "toString":

number = function(n){

  var num = n;

  this.add = function(x){
    return num + x;
  }

  this.toString = function() {
    return num + "";
  };

  return num;

}

You can also give it a "valueOf" function:

  this.valueOf = function() { return num; }

That will let you do:

alert(seven + 7); // 14

Comments

2

To be able to reuse the Number you'll need to return the reference to the function in the constructor:

var number = function(n) {

  var num = n;

  this.add = function(x){
    return num + x;
  };

  this.value = function() {
      return num;
  };
}

2 Comments

@Pointy: Not strictly true. A constructor returns this unless an object is explicitly returned. (It doesn't work for numbers because they're not objects, but you can return a Number.)
Ah OK - yes I think somewhere in my head I knew that; it's not the kind of code I would ordinarily write!
1

Override toString:

number = function(n){

  var num = n;

  this.add = function(x){
    return num + x;
  };

  this.toString = function(){
    return num;
  };

  return num;

}

Comments

1

If I get this right, you want an object to behave as, well, an object except for when it is passed to a function? the variable seven in your example is an object, so there's no way it'll simply return 7 when referenced anywhere.

What's more, num is essentially a private variable. So using for...in and JSON.stringify trickery won't do you any good. What you should do is either make the num variable an object property (this.num) or create a member function (this.getNum(){return num};).

After that, you can use the property/method freely:

alert(seven.num);//alerts 7, but requires num to be declared as a property
alert(seven.getNum());//alerts 7, requires the method

I'd suggest using a method in this case, since you're obviously using this function both as a constructor and a regular function (Which, might I add, isn't a very good idea).
On a slightly pedantic note: it is custom to capitalize the first letter of a constructor, and not to use names that might collide with JS native types (String, Number, Object, Function...)

function MyNumber(n)
{
    this.num = n;//as a property
    this.add = function(x)
    {
        return this.num + x;
    }
}

var seven = new MyNumber(7);
alert(seven.num);//alerts 7

Though, if num shouldn't be altered -I'm guessing that's the case here- an extra function is the route I'd take:

function MyNumber(n)
{
    var num = n;
    this.add = function(x)
    {
        return num + x;
    };
    this.getNum = function()
    {
        return num;
    };
}
alert(seven.getNum());

If you're still planning on using the constructor as a regular function, you're best of checking how the function/constructor was called:

function MyNumber(n)
{
    var num = n;
    if (!(this instanceof MyNumber))
    {//not called as constructor
        return num;//or a function, or something else (treat this as a closure)
    }
    //Same code as above goes here
}

I might be going a bit off topic here, but I can't help but think that you might want to read up on closures, objects and constructors in JavaScript.

Comments

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.