[英]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 Number
为false
]。要检查 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.