JSON.parse(str) 以某种方式检索到原始对象 __proto__ 的非常具体的信息,这些信息不在 JSON 字符串 (=str) 中。如何?
JSON.parse(str) somehow retrieved very specific information of __proto__ of original object, which is not in the JSON string(=str). How?
在 JavaScript 中,JSON.parse(str);
将 JSON 字符串转换为 JavaScript 对象。
我发现奇怪的是,即使 JSON 字符串不包含任何关于 Object
的 __proto__
的信息,JSON.parse(str)
有时会设法恢复 [=20] 的嵌套属性=] 属性.
示例(运行 直接在 Brave 浏览器的开发者工具控制台中):
{
let user1 = {
name: "John",
surname: "Smith",
isAdmin: false,
"birthday": new Date(2000, 2, 3),
"friends": [0,1,2,3]
};
user1.__proto__.age = 30;
const str1 = JSON.stringify(user1, null, 2);
user1.__proto__ = null;
user1 = null;
const user2 = JSON.parse(str1);
console.log(str1);
console.log(user2);
const str2 = `{
"name": "John",
"surname": "Smith",
"isAdmin": false,
"birthday": "2000-03-02T15:00:00.000Z",
"friends": [
0,
1,
2,
3
]
}`;
const user3 = JSON.parse(str2);
console.log(user3);
}
在这里,user1 是用这样那样的属性创建的。然后在其 proto 上我指定年龄:30 属性。
从 user1 我用 JSON.stringify
制作了它的 JSON 字符串,并将它保存在 str1
中。现在我删除了 user1
及其 __proto__
。
只是为了确保,我打印 str1
并且它 没有关于 __proto__
和 age:30 的信息,正如预期的那样。
但是,当我使用 JSON.parse
从 str1
创建 user2
时,__proto__
的 age:30 被恢复 。这怎么可能?
现在我什至用变量名 str2 制作完全相同的 JSON 字符串,并用 str2 创建另一个对象。结果是一样的。这太疯狂了。
console.log(str1) 的输出;
{
"name": "John",
"surname": "Smith",
"isAdmin": false,
"birthday": "2000-03-02T15:00:00.000Z",
"friends": [
0,
1,
2,
3
]
}
console.log(user2) 的输出;
{name: 'John', surname: 'Smith', isAdmin: false, birthday: '2000-03-02T15:00:00.000Z', friends: Array(4)}
birthday: "2000-03-02T15:00:00.000Z"
friends: (4) [0, 1, 2, 3]
isAdmin: false
name: "John"
surname: "Smith"
[[Prototype]]: Object
age: 30
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
__proto__: (...)
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
console.log(user3) 的输出;
{name: 'John', surname: 'Smith', isAdmin: false, birthday: '2000-03-02T15:00:00.000Z', friends: Array(4)}
birthday: "2000-03-02T15:00:00.000Z"
friends: (4) [0, 1, 2, 3]
isAdmin: false
name: "John"
surname: "Smith"
[[Prototype]]: Object
age: 30
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
__proto__: (...)
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
顺便说一下,我关闭并打开了浏览器并重新运行 代码块以确保它不是某些预分配变量的结果。结果是一样的,它(年龄:30)不是来自预先分配的变量或缓存值。
我还打开了一个新选项卡并执行了以下较小的代码块。
{
const str2 = `{
"name": "John",
"surname": "Smith",
"isAdmin": false,
"birthday": "2000-03-02T15:00:00.000Z",
"friends": [
0,
1,
2,
3
]
}`;
const user3 = JSON.parse(str2);
console.log(user3);
}
在这种情况下, proto 中的 age: 30 属性 不存在,这是第一个示例发生的原始预期结果,至少对于我.
具有较小代码块的输出:
{name: 'John', surname: 'Smith', isAdmin: false, birthday: '2000-03-02T15:00:00.000Z', friends: Array(4)}
birthday: "2000-03-02T15:00:00.000Z"
friends: (4) [0, 1, 2, 3]
isAdmin: false
name: "John"
surname: "Smith"
[[Prototype]]: Object
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
__proto__: (...)
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
看来我误用了prototype。
删除年龄的正确方法:30 是
两者都
delete user1.__proto__.age;
或
delete Object.prototype.age;
与这里的user1=null
无关。
出于某种原因 user1.__proto__ = null
没有取得任何成就,如果有人提示我原因就太好了
编辑:user1.__proto__ = null
确实删除了用户 1 的 proto,但它不影响 Object.prototype。我认为它只会将 user1 从原型链中分离出来。
在 JavaScript 中,JSON.parse(str);
将 JSON 字符串转换为 JavaScript 对象。
我发现奇怪的是,即使 JSON 字符串不包含任何关于 Object
的 __proto__
的信息,JSON.parse(str)
有时会设法恢复 [=20] 的嵌套属性=] 属性.
示例(运行 直接在 Brave 浏览器的开发者工具控制台中):
{
let user1 = {
name: "John",
surname: "Smith",
isAdmin: false,
"birthday": new Date(2000, 2, 3),
"friends": [0,1,2,3]
};
user1.__proto__.age = 30;
const str1 = JSON.stringify(user1, null, 2);
user1.__proto__ = null;
user1 = null;
const user2 = JSON.parse(str1);
console.log(str1);
console.log(user2);
const str2 = `{
"name": "John",
"surname": "Smith",
"isAdmin": false,
"birthday": "2000-03-02T15:00:00.000Z",
"friends": [
0,
1,
2,
3
]
}`;
const user3 = JSON.parse(str2);
console.log(user3);
}
在这里,user1 是用这样那样的属性创建的。然后在其 proto 上我指定年龄:30 属性。
从 user1 我用 JSON.stringify
制作了它的 JSON 字符串,并将它保存在 str1
中。现在我删除了 user1
及其 __proto__
。
只是为了确保,我打印 str1
并且它 没有关于 __proto__
和 age:30 的信息,正如预期的那样。
但是,当我使用 JSON.parse
从 str1
创建 user2
时,__proto__
的 age:30 被恢复 。这怎么可能?
现在我什至用变量名 str2 制作完全相同的 JSON 字符串,并用 str2 创建另一个对象。结果是一样的。这太疯狂了。
console.log(str1) 的输出;
{
"name": "John",
"surname": "Smith",
"isAdmin": false,
"birthday": "2000-03-02T15:00:00.000Z",
"friends": [
0,
1,
2,
3
]
}
console.log(user2) 的输出;
{name: 'John', surname: 'Smith', isAdmin: false, birthday: '2000-03-02T15:00:00.000Z', friends: Array(4)}
birthday: "2000-03-02T15:00:00.000Z"
friends: (4) [0, 1, 2, 3]
isAdmin: false
name: "John"
surname: "Smith"
[[Prototype]]: Object
age: 30
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
__proto__: (...)
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
console.log(user3) 的输出;
{name: 'John', surname: 'Smith', isAdmin: false, birthday: '2000-03-02T15:00:00.000Z', friends: Array(4)}
birthday: "2000-03-02T15:00:00.000Z"
friends: (4) [0, 1, 2, 3]
isAdmin: false
name: "John"
surname: "Smith"
[[Prototype]]: Object
age: 30
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
__proto__: (...)
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
顺便说一下,我关闭并打开了浏览器并重新运行 代码块以确保它不是某些预分配变量的结果。结果是一样的,它(年龄:30)不是来自预先分配的变量或缓存值。
我还打开了一个新选项卡并执行了以下较小的代码块。
{
const str2 = `{
"name": "John",
"surname": "Smith",
"isAdmin": false,
"birthday": "2000-03-02T15:00:00.000Z",
"friends": [
0,
1,
2,
3
]
}`;
const user3 = JSON.parse(str2);
console.log(user3);
}
在这种情况下, proto 中的 age: 30 属性 不存在,这是第一个示例发生的原始预期结果,至少对于我.
具有较小代码块的输出:
{name: 'John', surname: 'Smith', isAdmin: false, birthday: '2000-03-02T15:00:00.000Z', friends: Array(4)}
birthday: "2000-03-02T15:00:00.000Z"
friends: (4) [0, 1, 2, 3]
isAdmin: false
name: "John"
surname: "Smith"
[[Prototype]]: Object
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
__proto__: (...)
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
看来我误用了prototype。 删除年龄的正确方法:30 是
两者都
delete user1.__proto__.age;
或
delete Object.prototype.age;
与这里的user1=null
无关。
出于某种原因 user1.__proto__ = null
没有取得任何成就,如果有人提示我原因就太好了
编辑:user1.__proto__ = null
确实删除了用户 1 的 proto,但它不影响 Object.prototype。我认为它只会将 user1 从原型链中分离出来。