创建一个具有返回值的对象

时间:2012-06-09 13:48:00

标签: javascript object

我想知道这是否可行。

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]

我不需要数字(7)来返回7,但它会很好。

5 个答案:

答案 0 :(得分:7)

首先return num;对您的代码无效。函数返回的对象是this。如果构造函数没有显式返回对象,它将始终隐式返回this(参见MDN documentation中的第3步)。

也就是说,您可以覆盖两种方法,即toString [MDN]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;
};

覆盖valueOf的额外好处是JavaScript将在内部调用此方法将对象转换为原始值。

例如,在正常添加中使用实例作为操作数也可以工作(而不是调用.add):

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

那就是说,如果你只是想为原始类型创建一个包装器,那就不要这样做了。

As pimvdb mentions in his comment,严格比较会失败(例如)。这是可以预料的,并且避免原始值的对象版本(NumberStringBoolean)(即"foo" === new String("foo")false的原因之一也是)。对象根本不像基元,混合这些会产生更复杂的代码。

答案 1 :(得分:4)

给它一个“toString”:

number = function(n){

  var num = n;

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

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

  return num;

}

你也可以给它一个“valueOf”函数:

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

那会让你这样做:

alert(seven + 7); // 14

答案 2 :(得分:2)

为了能够重用Number,你需要在构造函数中返回对函数的引用:

var number = function(n) {

  var num = n;

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

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

答案 3 :(得分:1)

覆盖toString

number = function(n){

  var num = n;

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

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

  return num;

}

答案 4 :(得分:1)

如果我做对了,你希望一个对象表现为一个对象,除了它传递给一个函数的时候?您示例中的变量seven是一个对象,因此在任何地方引用它时都无法返回7

更重要的是,num本质上是一个私有变量。因此,使用for...inJSON.stringify欺骗对您没有任何好处。您应该做的是将num变量设为对象属性(this.num)或创建成员函数(this.getNum(){return num};)。

之后,您可以自由使用属性/方法:

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

我建议在这种情况下使用一种方法,因为你显然使用这个函数作为构造函数和常规函数(我可以补充说,这不是一个好主意)。
稍微迂腐的说明:将构造函数的第一个字母大写,而不是使用可能与JS本机类型(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

虽然,如果num不应该被改变 - 我猜这就是这种情况 - 一个额外的功能是我采取的路线:

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

如果您仍然计划将构造函数用作常规函数,那么最好检查函数/构造函数的调用方式:

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
}

我可能会在这里讨论一些主题,但我不禁想到你可能想要阅读JavaScript中的闭包,对象和构造函数。