setter/getter not working for Number literal

女生的网名这么多〃 提交于 2019-12-30 11:08:32

问题


I thougt it would be fun to rewrite my zero padding extension to the Number.prototype into a genuine getter/setter pattern. Not very difficult. I ended up with this code (addSetter and addGetter are just wrapper functions using 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;
  }
);

Works fine for real Number Objects:

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

But not for Number literals:

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

So, doesn't b reach the setter? Or if it reaches the setter, isn't it a Number?

I logged this in the console from within the setter function:

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

Or is the getter not reached, or when it's reached would the literal not be an instance of Number? I logged the same within the getter. All fine and true too.

So, what may be the reason that we are not able to use this pattern using a Number literal? Or have I missed something?

Note: this doesn't occur if I use this prototype extension ('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

[edit] I still wonder if we have to call this a bug, or if it's following the/a standard. Anyway, I deviced my own object for this now:

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

回答1:


A literal number is not a Number:

typeof 3
// "number"

typeof new Number(3)
// "object"

So there is no prototype to modify for numeric literals.

However, when you try to set a property on a numeric literal, it looks like the literal is wrapped in a Number object first. Then, the setter is called on that object and this will be an object inside the setter function. And then, the literal is unwrapped when the setter returns and this unwrapping leaves the property (which was set on the object wrapper) behind.

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/

I get four alerts out of the above in several browsers.

Sorry but I don't have an authoritative reference for this behavior, just empirical evidence.




回答2:


var b = 9; means that b is a reference to a primitive type, not an object of type Number.

var b = new Number(9) creates an object of type Number, which will contain the function added to the Number prototype, not a primitive number type.



来源:https://stackoverflow.com/questions/6050289/setter-getter-not-working-for-number-literal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!