setter / getter不适用于Number literal

时间:2011-05-18 19:56:50

标签: javascript numbers getter-setter

我认为将Number.prototype的零填充扩展名重写为真正的getter / setter模式会很有趣。不是很难。我最终得到了这段代码(addSetteraddGetter只是使用prototype.__defineGetter__ / __defineSetter__的包装函数。

Number.addSetter('leftPad0',
  function(v){
    var  len = (String(v).length - String(this).length)+1;
    this._leftPad0 = new Array(len).join('0')+this;
  }
);

Number.addGetter('leftPad0',
  function(){
    return this._leftPad0;
  }
);

适用于实际数字对象:

var a = new Number(977);
a.leftPad0 = 10000;
alert('a => '+a.leftPad0); // a => 00977

但不是数字文字:

var b = 977;
b.leftPad0 = 10000;
alert('b => '+b.leftPad0); // b => undefined

那么,是不是达到了二传手?或者,如果它到达了设定者,是不是数字?

我在setter函数中将其记录在控制台中:

this.constructor === Number // true
this instanceof Number //true

或者是没有达到吸气剂,或者当它到达时,文字不是数字的实例?我在getter中记录了相同的内容。一切都很好,也是如此。

那么,可能是因为我们无法使用数字文字来使用此模式?或者我错过了什么?

注意:如果我使用此原型扩展('monkey patch'),则不会发生这种情况:

Number.prototype.leftPad = function(base){
  var  len = (String(base).length - String(this).length)+1;
  return new Array(len).join('0')+this;
}

alert( (977).leftPad(10000) ); // 00977

[编辑]我仍然想知道我们是否必须将此称为错误,或者是否遵循/ a标准。无论如何,我现在为此设计了自己的对象:

function NumPL(val,pval,chr){
   if (!(this instanceof NumPL)){
      return new NumPL(val,pval,chr);
   }
   this._value = new Number(val||0);
   this._padValue = pval || 10;
   this.chr = chr || '0';
}

NumPL.prototype = {
    get value(){
        return this._value;
    },
    set padValue(v) {
        this._padValue = v%10 === 0 ? v : 10;
    },
    set value(v) {
        this._value = v;
    },
    get padLeft(){
       var  len = (String(this._padValue).length - 
                   String(this._value).length)+1;
       return new Array(len).join(this.chr)+this._value;
    }
}
// Usage
var a = NumPL(977,10000);
alert(a.padLeft); //=> 00977
// or a real world example
var dat = new Date,
    datshort = [dat.getFullYear(),
                NumPL(dat.getMonth()+1).padLeft,
                NumPL(dat.getDate()).padLeft]
               .join('/');
 alert(datshort); //=> 2011/05/19

2 个答案:

答案 0 :(得分:4)

字面数不是Number

typeof 3
// "number"

typeof new Number(3)
// "object"

因此没有可以修改数字文字的原型。

但是,当您尝试在数字文字上设置属性时,看起来文字首先包装在Number对象中。然后,在该对象上调用setter,this将成为setter函数内的对象。然后,当setter返回时,文本被解包,这个展开将属性(在对象包装器上设置)留下。

Number.prototype.__defineSetter__('leftPad0',
    function(v) {
        alert('In setter: ' + v + ' ' + (this instanceof Number));
        var len = (String(v).length - String(this).length) + 1;
        this._leftPad0 = new Array(len).join('0') + this;
    }
);

var a = new Number(977);
a.leftPad0 = 10000;
alert('a => ' + a._leftPad0);

var b = 977;
b.leftPad0 = 10000;
alert('b => ' + b._leftPad0);

http://jsfiddle.net/ambiguous/H77qk/2/

我在几个浏览器中收到了上述四个警告。

很抱歉,但我没有这种行为的权威参考,只是经验证据。

答案 1 :(得分:2)

var b = 9;表示b是对基本类型的引用,而不是Number类型的对象。

var b = new Number(9)创建一个Number类型的对象,包含添加到Number原型的函数,而不是原始数字类型。