二传手/吸盘器不适用于数字文字

setter/getter not working for Number literal

本文关键字:适用于 数字 文字 不适用 二传手      更新时间:2023-09-26

我认为将我对 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

那么,b不是到达二传手吗?或者如果它到达二传手,它不是一个数字吗?

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

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

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

那么,我们无法使用数字文字使用此模式的原因可能是什么?还是我错过了什么?

注意:如果我使用此原型扩展("猴子补丁"),则不会发生这种情况:

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

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

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

文字数字不是Number

typeof 3
// "number"
typeof new Number(3)
// "object"

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

但是,当您尝试在数字文本上设置属性时,看起来文本首先包装在 Number 对象中。然后,在该对象上调用 setter,this 将是 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/

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

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

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

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