能否手动打破JS中预定义的Numbers、Strings、Boolean、Arrays原型链或重新赋值

Can we break the pre-defined prototype chain of Numbers, Strings, Boolean, Arrays in JS Manually or Reassign Values

时,我们新建一个number类型的变量(比如num1),它的__proto__指向Number Object。它的 __proto__ 将再次指向 Object Core,它的 __proto__ 指向 null,从而结束原型链。

我想做的是通过尝试将 __proto__ link 从 Number Object 更改为某个字符串来在中间覆盖此链。我不能中断链,因为在我分配后它仍然指向 Object Core 结构。

我是不是做错了什么来打破这个原型链,或者是不可能打破浏览器中预定义的原型链!

Number.__proto__ = "abc"; 
let num4 = 8;
console.log(num4.__proto__);//returns Number Object
console.log(num4.__proto__.__proto__)//should return string "abc"

输出:

但是,我知道我可以通过以下代码在链的中间添加某些项目(比如在 Number-Object 中):

Number.prototype.alpha = "def";
let num5 = 99; 
console.log(num5.__proto__);

输出:

修改基本对象的 built-in 原型,或 built-in 原型链,在一般情况下是一个非常糟糕的主意。我强烈建议不要这样做。

Number.__proto__Number 函数的原型, 不是 Number 对象的原型(即 Number.prototype ).

此外,JavaScript 同时具有数字基元和数字对象。大多数时候,您正在处理一个数字基元。当您在数字原语 (n = 42) 上使用属性(包括方法)时,例如 toString,JavaScript 引擎从 Number.prototype 获取这些属性,即使 n是原语。

可以改变Number.prototype的原型。例如,您可以将其设置为 null,以便 Number 对象不再继承自 Number.prototype 以外的任何对象(用 Object.prototype 打破 link),意思是 属性 对数字基元的查找不再从 Object.prototype 中找到属性和方法:

const n = 8;
console.log(typeof n.hasOwnProperty);           // function
console.log(Object(n) instanceof Number);       // true
console.log(Object(n) instanceof Object);       // true
Object.setPrototypeOf(Number.prototype, null);
console.log(typeof n.hasOwnProperty);           // undefined
console.log(Object(n) instanceof Number);       // true
console.log(Object(n) instanceof Object);       // false

(Object(n) returns 原始数字 nNumber 对象。我在那里使用它是因为 instanceof 总是 false对于基元 [n instanceof Numberfalse,例如。为了检查继承,我们临时需要一个对象。)

如您所见,Number 对象和 Object 之间的 link 已经断开。

同样,在一般情况下这是一个非常糟糕的主意,因为它往往会破坏事物。仅仅因为我们可以这样做并不意味着我们应该.

However, I know I can add certain item in the middle of chain (like in Number-Object) by following code:

Number.prototype.alpha = "def";
let num5 = 99; 
console.log(num5.__proto__);

这只是在 Number.prototype 上添加了一个 属性,而不是在原型链中插入一些东西。但是也可以插入到原型链中,因为我们可以更改 Number.prototype:

的原型

function Custom() {
}
// Change `Custom.prototype` to an object whose prototype
// is the prototype of `Number.prototype` (which will be
// `Object.prototype` in an unsullied environment).
// (`Object.create` creates an object setting its prototype
// to the given object.)
Object.defineProperty(Custom, "prototype", {
    value: Object.create(Object.getPrototypeOf(Number.prototype)),
    writable: true,
});
Object.defineProperty(Custom.prototype, "constructor", {
    value: Custom,
    writable: true,
    configurable: true,
});
Object.defineProperty(Custom.prototype, "example", {
    value() {
        return "hi there";
    },
    writable: true,
    configurable: true,
});
Object.setPrototypeOf(Number.prototype, Custom.prototype);

const n = 8;
console.log(n.example());                 // "hi there"
console.log(Object(n) instanceof Custom); // true

我在那里使用了一个构造函数,这样我们就可以很容易地使用 instanceof 来检查继承,但是您可以插入一个没有构造函数的原型。这是没有一个的相同代码:

const custom = Object.create(Object.getPrototypeOf(Number.prototype));
Object.defineProperty(custom, "example", {
    value() {
        return "hi there";
    },
    writable: true,
    configurable: true,
});
Object.setPrototypeOf(Number.prototype, custom);

const n = 8;
console.log(n.example()); // "hi there"


注意 1:最好避免改变现有对象的原型(例如,Object.setPrototypeOf)。 JavaScript 引擎优化的假设(通常是正确的)对象的原型一旦创建就不会改变。更改它会破坏该假设,从而从对象中删除这些优化。

注 2: 您会注意到我没有使用 __proto__ accessor property anywhere above. It's deprecated and should not be used in new code, use Object.getPrototypeOf and (if absolutely necessary) Object.setPrototypeOf。对于不从 Object.prototype 继承的任何对象,它也会失败,因为那是定义 __proto__ 访问器 属性 的地方。