Сеттер / геттер не работает для числового литерала - PullRequest
2 голосов
/ 18 мая 2011

Думаю, было бы интересно переписать моё расширение дополнения нулями в Number.prototype в подлинный шаблон получения / установки.Не очень сложно.Я закончил с этим кодом (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;
  }
);

Работает нормально для реальных объектов Number:

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? Я записал то же самое в получателе. Все тоже хорошо и верно.

Итак, что может быть причиной того, что мы не можем использовать этот шаблон с использованием числового литерала? Или я что-то пропустил?

Примечание: этого не произойдет, если я использую этот прототипрасширение ('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 ] Я все еще задаюсь вопросом, должны ли мы назвать это ошибкой, или она соответствует стандарту / 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 ]

4 голосов
/ 19 мая 2011

Литеральное число не является Number:

typeof 3
// "number"

typeof new Number(3)
// "object"

Таким образом, нет прототипа для изменения числовых литералов.

Однако при попытке установить свойствочисловой литерал, похоже, что литерал сначала оборачивается в объект Number.Затем для этого объекта вызывается установщик, и this будет объектом внутри функции установщика.И затем, литерал разворачивается, когда возвращается установщик, и это развертывание оставляет свойство (которое было установлено в обертке объекта) позади.из вышеперечисленного в нескольких браузерах.

Извините, но у меня нет авторитетной ссылки на это поведение, только эмпирические доказательства.

2 голосов
/ 19 мая 2011

var b = 9; означает, что b является ссылкой на примитивный тип, а не объект типа Number.

var b = new Number(9) создает объект типа Number, который будет содержать функцию, добавленную к прототипу Number, а не тип простого числа.

...