Javascript Number原型设置值直接

时间:2016-06-17 09:44:31

标签: javascript numbers prototype

我尝试直接从原型方法设置一个数字。 通常,返回一个新值。

这个的数字对象,也是一个对象。但我想不是参考。 (?)

我有这个:

Number.prototype.bitSet = function(bit) {
    return this | (1<<bit);
};

但是想要这个:

Number.prototype.bitSet = function(bit) {
        this.value = this | (1<<bit);
    };

this.value是一个伪属性。因为这可能是数字的参考,没有它,你将覆盖它。但问题是:这真的是源数的参考吗?有可能吗?将值直接分配给调用此方法的数字?

var num = 0; 
num.bitSet(9);
console.log(num); // num = 512

顺便说一下。 chrome控制台为数字打印[[PrimitiveValue]]。

1 个答案:

答案 0 :(得分:3)

TL; DR - 您不能这样做,bitSet的初始版本是您需要定义它的方式。您需要在使用它时保存其返回值,例如x = x.bitSet(2)。但是,如果您愿意,可以创建自己的可变数字对象。 (更多内容见下文。)

为了清楚起见(您可能知道这一点):JavaScript同时包含数字原语Number 对象。通常,你正在处理原语。 Number.prototype工作的原因是在调用方法时使用基元的值创建临时对象。但是,除非明确地保存对象,否则就好像我们只处理原语一样。

JavaScript中的数字不可变。 1 因此,您的bitSet方法无法更改其调用内容的数值;相反,它必须返回一个新的数字与所做的更改(例如,您的原始版本)。

请注意,即使您可以更改Number对象的值,您几乎也不会在已分配给Number.prototype的函数之外的代码中处理数字对象。例如:

Number.prototype.bitSet = function(bit) {
    return this | (1<<bit);
};
var x = 32;
x = x.bitSet(2);
console.log(x); // 36
console.log(typeof x); // "number", not "object"
var o = new Number(36);
console.log(typeof o); // "object"

在上面,当执行x = x.bitSet(2);时,数字原语将转换为临时Number对象,调用您的bitSet方法,然后结果是你的bitSet方法返回的结果;除非bitSet在某处执行存储this的操作,否则临时对象将被丢弃。 (这就是理论;实际上,如果你的JavaScript引擎可以确定函数中的代码只使用数字就好像它是一个原始数字,那么你的JavaScript引擎可能会完全优化对象。)< / p>

因此,假设在上面的代码中,我们做了一些事情来改变Number行中x.bitSet(2)对象的状态。由于该对象是临时并且没有存储在任何地方(除非我们存储它;它不在x中,x包含原始数字),无论我们存储在对象上的是什么丢失。我们甚至可以证明:

Number.prototype.test = function() {
  this.foo = Math.random();
  console.log("this.foo", this.foo); // some number
};
var x = 42;
x.test();
console.log(typeof x);       // "number", not "object"
console.log("x.foo", x.foo); // undefined

this绝对是一个对象,我们为它添加了一个属性并使用了该属性。但是x仍然有原始的。

您可以拥有拥有的可变数字类型,但是:

function MyNumber(value) {
    this.value = typeof value === "number" ? value : 0;
}
MyNumber.prototype.bitSet = function(bit) {
    this.value = this.value | (1 << bit);
};
MyNumber.prototype.valueOf = function() {
    return this.value;
};
MyNumber.prototype.toString = function() {
    return this.value.toString();
};

// Usage:
var m = new MyNumber(42);
m.bitSet(2);
console.log(String(m)); // "46"
var n = m + 5;
console.log(n);         // 51

只要JavaScript引擎需要将您的数字对象转换为数字,就会调用valueOf函数。当JavaScript引擎需要将您的数字对象转换为字符串时,将调用toString

或者在ES2015中:

class MyNumber {
    constructor(value) {
      this.value = typeof value === "number" ? value : 0;
    }
    bitSet(bit) {
      this.value = this.value | (1 << bit);
    }
    valueOf() {
      return this.value;
    }
    toString() {
      return this.value.toString();
    }
}

// Usage:
var m = new MyNumber(42);
m.bitSet(2);
console.log(String(m)); // "46"
var n = m + 5;
console.log(n); // 51

1 “JavaScript中的数字不可变”从技术上讲,这不是真的。 原始数字不可变,但Number个对象是 - 但它们的基础数值(规范称为[[NumberData]])无法更改。 (Number个对象可以有其他属性,可以更改状态,而不是它们的数值。)因此,“数字在JavaScript中不可变”是一个合理的简写语句,如果不完全正确的话。