setter/getter 不适用于数字文字

发布于 2024-11-08 07:30:37 字数 2263 浏览 5 评论 0原文

我认为将 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 不会到达设置器吗?或者如果它到达设置器,它不是一个数字吗?

我从设置器函数中将其记录在控制台中:

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

或者是获取器未达到,或者达到时,文字不会是 Number 的实例吗?我在 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

[编辑]我仍然想知道我们是否必须称其为错误,或者如果它遵循/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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寄居人 2024-11-15 07:30:37

文字数字不是 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/ambigously/H77qk/2/

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

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

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.

停顿的约定 2024-11-15 07:30:37

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文