setter/getter 不适用于数字文字
我认为将 Number.prototype 的零填充扩展重写为真正的 getter/setter 模式会很有趣。不是很困难。我最终得到了这段代码(addSetter
和addGetter
只是使用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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
文字数字不是
Number
:因此没有可以修改数字文字的原型。
但是,当您尝试在数字文字上设置属性时,看起来该文字首先被包装在 Number 对象中。然后,在该对象上调用 setter,并且
this
将成为 setter 函数内的对象。然后,当 setter 返回时,文字将被展开,并且此展开会将属性(在对象包装器上设置)留在后面。http://jsfiddle.net/ambigously/H77qk/2/
我收到了四个警报以上在几个浏览器中。
抱歉,我没有关于这种行为的权威参考,只有经验证据。
A literal number is not a
Number
: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.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.
var b = 9;
表示b
是对原始类型的引用,而不是Number
类型的对象。var b = new Number(9)
创建一个Number
类型的对象,其中将包含添加到Number
的函数code> 原型,不是原始数字类型。var b = 9;
means thatb
is a reference to a primitive type, not an object of typeNumber
.var b = new Number(9)
creates an object of typeNumber
, which will contain the function added to theNumber
prototype, not a primitive number type.