繁体   English   中英

我们可以手动打破JS中的数字,字符串,Boolean,Arrays的预定义原型链还是重新分配值

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

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

我想要做的是,通过尝试将__proto__链接从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"

Output:

在此处输入图像描述

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

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

Output:

在此处输入图像描述

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

Number.__proto__Number function 的原型,而不是Number对象的原型(即Number.prototype )。

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

可以更改Number.prototype的原型。 例如,您可以将其设置为null以便Number对象不再继承自Number.prototype的任何对象(断开与Object.prototype的链接),这意味着对数字原语的属性查找不会从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)返回一个Number object 用于数字原语n 。我在那里使用它是因为instanceof对于原语总是为false [例如, n instanceof Numberfalse ]。要检查 inheritance,我们暂时需要一个 ZA8CFDE6331C4B96666)

如您所见, Number对象与Object之间的链接已断开。

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

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

 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

我在那里使用了构造函数 function,这样我们就可以轻松地使用instanceof来检查 inheritance,但是您可以在没有构造函数 function 的情况下插入原型。 这是没有相同的代码:

 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 引擎在 object 的原型一旦创建就不会改变的假设(这通常是正确的)进行优化。 更改它会破坏该假设,从而从 object 中删除这些优化。

注意 2:你会注意到我没有在上面的任何地方使用__proto__访问器属性 它已弃用,不应在新代码中使用,请改用Object.getPrototypeOf和(如果绝对必要) Object.setPrototypeOf 对于任何不从 Object.prototype 继承的Object.prototype ,它也会失败,因为这是定义__proto__访问器属性的地方。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM