Javascript 数字原型(prototype)直接设置值

标签 javascript numbers prototype

<分区>

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

this 一个数字对象,也是一个对象。但我想不是引用。 (?)

我有这个:

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]] 作为数字。

最佳答案

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

为了清楚起见(您可能知道这一点):JavaScript 有数字原语数字 对象。通常,您正在处理原语。 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);被执行时,数字primitive被转换为一个临时的Number对象,您的 bitSet 方法被调用,然后结果就是您的 bitSet 方法返回的任何内容;除非 bitSet 做了一些事情来将 this 存储在某个地方,否则临时对象将被丢弃。 (这就是理论;事实上,如果您的 JavaScript 引擎可以确定您的函数中的代码只使用该数字,就好像它是原始数字一样,那么它可能会完全优化对象。)

所以假设在我上面的代码中,我们做了一些事情来改变 x.bitSet(2) 行中的 Number 对象的状态。因为那个对象是临时的并且没有存储在任何地方(除非我们存储它;它不在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 函数。 toString 在 JavaScript 引擎需要将您的数字对象转换为字符串时调用。

或者在 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 中是不可变的”是一个合理的速记声明,即使不是完全正确。

关于Javascript 数字原型(prototype)直接设置值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37878330/

相关文章:

javascript - 在输入框中禁用多个完全相同数字的用户

javascript - 如何检测正则表达式中的下划线?

javascript - 调用另一个类的函数

c# - 格式化带有公制前缀的数字?

javascript - 在 Nodejs 中调用 Array 原型(prototype)上的自定义方法

javascript - Parse Cloud httpRequest 不返回响应

java - 循环 "If Else Statement"java

c - 在 c 中搜索数字的出现

java - Spring:如何实例化一个带有运行时参数的 Spring bean?

javascript - 我将如何通过嵌套函数将元素作为参数传递?