创建具有返回值的对象

Create an object with a return value

本文关键字:对象 返回值 创建      更新时间:2023-09-26

我想知道这是否可能。

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,但这会很好。

第一个return num;在你的代码中不起作用。函数返回的对象是 this 。如果构造函数没有显式返回对象,它将始终隐式返回this(请参阅 MDN 文档中的步骤 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

也就是说,如果您只想为基元类型创建一个包装器,请不要这样做。

正如 pimvdb 在他的评论中提到的那样,严格的比较会失败(例如)。这是意料之中的,也是避免使用基元值(NumberStringBoolean)的对象版本的原因之一(即 "foo" === new String("foo")也是false)。对象的行为根本不像基元,混合这些对象会产生更复杂的代码。

给它一个"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

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

var number = function(n) {
  var num = n;
  this.add = function(x){
    return num + x;
  };
  this.value = function() {
      return num;
  };
}

覆盖toString

number = function(n){
  var num = n;
  this.add = function(x){
    return num + x;
  };
  this.toString = function(){
    return num;
  };
  return num;
}

如果我做对了,你想让一个对象表现得像一个对象,除了当它传递给函数时? 示例中的变量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本机类型(字符串,数字,对象,函数...

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中的闭包,对象和构造函数。