为什么 XMLHttpRequest 对象的属性只能通过 console.log() 打印?
Why properties of an XMLHttpRequest object are only printable through console.log()?
var obj = new XMLHttpRequest();
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj))
console.log("Object.entries():",Object.entries(obj))
console.log("JSON.stringify():",JSON.stringify(obj))
console.log("console.log:"); console.log(obj)
输出:
Object.keys(): []
Object.getOwnPropertyNames(): []
Object.entries(): []
JSON.stringify(): {}
console.log:
XMLHttpRequest {onreadystatechange: null, readyState: 0, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}
如何在 javascript 中创建这样一个对象,其属性仅使用 console.log(obj)
打印,但不会由上述函数的 any 返回?
我已经尝试使用 constructor function
、object.create()
(使用 enumerable:false
)、Object.assign()
、使用 getters
、从 class,从扩展 class e.t.c
实例化
你可以这样做:
Object.defineProperty(obj, 'key', {
enumerable: false,
value: '123'
});
具体来说,enumerable
东西隐藏了 属性。
有关详细信息,请参阅此页面:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
更新:
以下方法(上述方法的改进版本)似乎隐藏了所有提到的检查的属性,尽管它有点冗长:
var proto = {};
Object.defineProperty(proto, "key", {
get: function () { return 123; }
});
var obj = Object.create(proto);
console.log(obj); // {}
console.log(Object.getOwnPropertyNames(obj)); // []
console.log(obj.key); // 123
Object.keys:只给出对象自身的可枚举属性.
Object.getOwnPropertyNames:给出直接在给定对象中找到的可枚举和不可枚举属性。
Object.entries:给出对象自己的可枚举字符串键控 属性 对。
JSON.stringify:只考虑对象的可枚举属性。
创建您自己的此类对象
您可以使用 Object.create 创建一个新对象,使用现有对象作为新创建对象的原型。
obj1 = {
key1: 'some key'
};
var obj = Object.create(obj1);
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj))
console.log("Object.entries():",Object.entries(obj))
console.log("JSON.stringify():",JSON.stringify(obj))
console.log("console.log:"); console.log(obj)
这是因为原型制作在Javascript中起作用,这才是真正的原因。
当您从原型创建对象实例时,__proto__
中的属性将不会显示(不可枚举的属性)
例如,尝试:
function MyXMLHttpRequest(){};
MyXMLHttpRequest.prototype.name = "Edward"
var obj = new MyXMLHttpRequest();
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj))
console.log("Object.entries():",Object.entries(obj))
console.log("JSON.stringify():",JSON.stringify(obj))
console.log("console.log:"); console.log(obj)
console.log(obj.name)
您将看到:
您可以使用名为 Symbol 的新数据类型为 JavaScript 对象创建键。
Link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
我附上了示例代码,您可以在控制台中看到输出。
let nameSymbol = Symbol('name');
function Person (name) {
this[nameSymbol] = name;
}
Person.prototype.toString = function toPersonString() {
var symArr = Object.getOwnPropertySymbols(this);
for (let sym of symArr) {
this[sym.description] = this[sym];
delete this[sym];
}
return this;
}
const dummyObject = new Person('random value');
console.log("Object.keys():",Object.keys(dummyObject)); // []
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(dummyObject)) // []
console.log("Object.entries():",Object.entries(dummyObject)) // []
console.log("JSON.stringify():",JSON.stringify(dummyObject)) // {}
console.log("console.log:", dummyObject.toString()); // {name: "random value"}
这与 WhatWG 有关 console.log
specification:
How the implementation prints args is up to the implementation, but implementations should separate the objects by a space or something similar, as that has become a developer expectation.
规范使输出格式非常模糊,由实现决定打印什么。
Why properties of an XMLHttpRequest object are only printable through console.log()?
这不是真的
var obj = new XMLHttpRequest();
for(var key in obj) console.log(key);
根据描述回答问题
How can I create such an object in javascript, whose properties are only printed using
var obj = Object.create({ foo: "foo", constructor: function() {} });
如果您想从 for in
中隐藏 属性,您应该将 enumerable
属性设置为 false
以获得所需的 属性:
Object.defineProperty(obj, 'foo', {
value: 42,
enumerable: false
});
我认为这是最实用的方法,对你有帮助
class User {
//this is a private field
#name
get Name() {
return this.#name
}
set Name(val) {
this.#name = val
}
}
var obj = new User()
obj.Name = 'test'
console.log('Object.keys():', Object.keys(obj))
console.log('Object.getOwnPropertyNames():', Object.getOwnPropertyNames(obj))
console.log('Object.entries():', Object.entries(obj))
console.log('JSON.stringify():', JSON.stringify(obj))
console.log('console.log:')
console.log(obj)
console.log(obj.Name)
这是编译后的代码
function _classPrivateFieldSet(receiver, privateMap, value) {
var descriptor = privateMap.get(receiver)
if (!descriptor) {
throw new TypeError('attempted to set private field on non-instance')
}
if (descriptor.set) {
descriptor.set.call(receiver, value)
} else {
if (!descriptor.writable) {
throw new TypeError('attempted to set read only private field')
}
descriptor.value = value
}
return value
}
function _classPrivateFieldGet(receiver, privateMap) {
var descriptor = privateMap.get(receiver)
if (!descriptor) {
throw new TypeError('attempted to get private field on non-instance')
}
if (descriptor.get) {
return descriptor.get.call(receiver)
}
return descriptor.value
} // Try edit message
class User {
constructor() {
_name.set(this, { writable: true, value: void 0 })
}
get Name() {
return _classPrivateFieldGet(this, _name)
}
set Name(val) {
_classPrivateFieldSet(this, _name, val)
}
}
var _name = new WeakMap()
var obj = new User()
obj.Name = 'test'
console.log('Object.keys():', Object.keys(obj))
console.log('Object.getOwnPropertyNames():', Object.getOwnPropertyNames(obj))
console.log('Object.entries():', Object.entries(obj))
console.log('JSON.stringify():', JSON.stringify(obj))
console.log('console.log:')
console.log(obj)
console.log(obj.Name)
这是chromium上编译版本的结果
XMLHttpRequest 实例上的所有属性都是继承属性,我的意思是它们不存在于实例本身,而是存在于它的原型链上。
这解释了为什么
const x = new XMLHttpRequest()
// all these methods consider only instance properties (owned properties) and thats why they return empty results
console.log(Object.keys(x)) // []
console.log(Object.getOwnPropertyNames(x)) // []
console.log(Object.entries(x)) // []
console.log(JSON.stringify(x)) // {}
// however if you try this you will get the results you want
console.log(Object.keys(x.__proto__)) // will not return symbol keys
console.log(Object.getOwnPropertyDescriptors(x.__proto__)) // will return descriptiors of every property whether its symbol or not
// you can see these results also by logging the xmlRequest, and looking at its __proto__ property in the console
// i will be calling the XMLHttpRequest instance for short as xmlRequest
您可以像这样简单地创建这样一个对象
class A {}
A.prototype.someProperty = 10
const a = new A()
// again if you try these you will get results like the XMLHttpRequest instance
console.log(Object.keys(a)) // []
console.log(Object.getOwnPropertyNames(a)) // []
console.log(Object.entries(a)) // []
console.log(JSON.stringify(a)) // {}
然而,当您尝试 console.log(a)
时,您将不会像使用 xmlRequest 实例那样看到 someProperty
,这是预期的,因为它是继承的 属性。您在记录 xmlRequest 时看到这些属性的原因是该对象正在接受特殊处理。
幸运的是,您可以使用 chrome custom object formatters 重新创建这种特殊处理,为此您必须从 chrome 开发人员工具设置
启用自定义格式化程序
window.devtoolsFormatters = [{
header: function(obj){
if (!(obj instanceof A)){
return null;
}
// to get the exact results like the xmlRequest, you need to remove quotes from the object keys in the json string, can be done with a regex
return ["div",{}, JSON.stringify(obj.__proto__)]
},
hasBody: function(){
return false;
}
}]
class A {}
A.prototype.someProperty = 10
console.log(new A()) // {"someProperty":10}
How can I create such an object in javascript, whose properties are only printed using console.log(obj), but not returned by any of the above functions?
一个接近的解决方案 我找到的是下面。这将打印带有 console.log(obj)
的属性。但是 obj 是一个代理。
在 chrome 控制台上,结果与 XMLHttpRequest
输出相同(class 为 Proxy
)。在 firefox 控制台上,它表示 Proxy
class,因此它并不完全相同。
const obj = new Proxy({prop1:"value1", prop2: "value2"}, {ownKeys: _=>[]});
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj))
console.log("Object.entries():",Object.entries(obj))
console.log("JSON.stringify():",JSON.stringify(obj))
console.log(obj)
结果:
Object.keys(): []
Object.getOwnPropertyNames(): []
Object.entries(): []
JSON.stringify(): {}
console.log:
Proxy {prop1: "value1", prop2: "value2"}
和console.log(obj.prop1) / obj.prop1="newValue"
仍然有效。
这应该可以解决问题。
var obj = Object.create({
get name(){
return 'I go only to console.log()';
}
});
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj));
console.log("Object.entries():",Object.entries(obj));
console.log("JSON.stringify():",JSON.stringify(obj));
console.log("console.log:", obj);
var obj = new XMLHttpRequest();
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj))
console.log("Object.entries():",Object.entries(obj))
console.log("JSON.stringify():",JSON.stringify(obj))
console.log("console.log:"); console.log(obj)
输出:
Object.keys(): []
Object.getOwnPropertyNames(): []
Object.entries(): []
JSON.stringify(): {}
console.log:
XMLHttpRequest {onreadystatechange: null, readyState: 0, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}
如何在 javascript 中创建这样一个对象,其属性仅使用 console.log(obj)
打印,但不会由上述函数的 any 返回?
我已经尝试使用 constructor function
、object.create()
(使用 enumerable:false
)、Object.assign()
、使用 getters
、从 class,从扩展 class e.t.c
你可以这样做:
Object.defineProperty(obj, 'key', {
enumerable: false,
value: '123'
});
具体来说,enumerable
东西隐藏了 属性。
有关详细信息,请参阅此页面:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
更新:
以下方法(上述方法的改进版本)似乎隐藏了所有提到的检查的属性,尽管它有点冗长:
var proto = {};
Object.defineProperty(proto, "key", {
get: function () { return 123; }
});
var obj = Object.create(proto);
console.log(obj); // {}
console.log(Object.getOwnPropertyNames(obj)); // []
console.log(obj.key); // 123
Object.keys:只给出对象自身的可枚举属性.
Object.getOwnPropertyNames:给出直接在给定对象中找到的可枚举和不可枚举属性。
Object.entries:给出对象自己的可枚举字符串键控 属性 对。
JSON.stringify:只考虑对象的可枚举属性。
创建您自己的此类对象
您可以使用 Object.create 创建一个新对象,使用现有对象作为新创建对象的原型。
obj1 = {
key1: 'some key'
};
var obj = Object.create(obj1);
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj))
console.log("Object.entries():",Object.entries(obj))
console.log("JSON.stringify():",JSON.stringify(obj))
console.log("console.log:"); console.log(obj)
这是因为原型制作在Javascript中起作用,这才是真正的原因。
当您从原型创建对象实例时,__proto__
中的属性将不会显示(不可枚举的属性)
例如,尝试:
function MyXMLHttpRequest(){};
MyXMLHttpRequest.prototype.name = "Edward"
var obj = new MyXMLHttpRequest();
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj))
console.log("Object.entries():",Object.entries(obj))
console.log("JSON.stringify():",JSON.stringify(obj))
console.log("console.log:"); console.log(obj)
console.log(obj.name)
您将看到:
您可以使用名为 Symbol 的新数据类型为 JavaScript 对象创建键。
Link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
我附上了示例代码,您可以在控制台中看到输出。
let nameSymbol = Symbol('name');
function Person (name) {
this[nameSymbol] = name;
}
Person.prototype.toString = function toPersonString() {
var symArr = Object.getOwnPropertySymbols(this);
for (let sym of symArr) {
this[sym.description] = this[sym];
delete this[sym];
}
return this;
}
const dummyObject = new Person('random value');
console.log("Object.keys():",Object.keys(dummyObject)); // []
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(dummyObject)) // []
console.log("Object.entries():",Object.entries(dummyObject)) // []
console.log("JSON.stringify():",JSON.stringify(dummyObject)) // {}
console.log("console.log:", dummyObject.toString()); // {name: "random value"}
这与 WhatWG 有关 console.log
specification:
How the implementation prints args is up to the implementation, but implementations should separate the objects by a space or something similar, as that has become a developer expectation.
规范使输出格式非常模糊,由实现决定打印什么。
Why properties of an XMLHttpRequest object are only printable through console.log()?
这不是真的
var obj = new XMLHttpRequest();
for(var key in obj) console.log(key);
根据描述回答问题
How can I create such an object in javascript, whose properties are only printed using
var obj = Object.create({ foo: "foo", constructor: function() {} });
如果您想从 for in
中隐藏 属性,您应该将 enumerable
属性设置为 false
以获得所需的 属性:
Object.defineProperty(obj, 'foo', {
value: 42,
enumerable: false
});
我认为这是最实用的方法,对你有帮助
class User {
//this is a private field
#name
get Name() {
return this.#name
}
set Name(val) {
this.#name = val
}
}
var obj = new User()
obj.Name = 'test'
console.log('Object.keys():', Object.keys(obj))
console.log('Object.getOwnPropertyNames():', Object.getOwnPropertyNames(obj))
console.log('Object.entries():', Object.entries(obj))
console.log('JSON.stringify():', JSON.stringify(obj))
console.log('console.log:')
console.log(obj)
console.log(obj.Name)
这是编译后的代码
function _classPrivateFieldSet(receiver, privateMap, value) {
var descriptor = privateMap.get(receiver)
if (!descriptor) {
throw new TypeError('attempted to set private field on non-instance')
}
if (descriptor.set) {
descriptor.set.call(receiver, value)
} else {
if (!descriptor.writable) {
throw new TypeError('attempted to set read only private field')
}
descriptor.value = value
}
return value
}
function _classPrivateFieldGet(receiver, privateMap) {
var descriptor = privateMap.get(receiver)
if (!descriptor) {
throw new TypeError('attempted to get private field on non-instance')
}
if (descriptor.get) {
return descriptor.get.call(receiver)
}
return descriptor.value
} // Try edit message
class User {
constructor() {
_name.set(this, { writable: true, value: void 0 })
}
get Name() {
return _classPrivateFieldGet(this, _name)
}
set Name(val) {
_classPrivateFieldSet(this, _name, val)
}
}
var _name = new WeakMap()
var obj = new User()
obj.Name = 'test'
console.log('Object.keys():', Object.keys(obj))
console.log('Object.getOwnPropertyNames():', Object.getOwnPropertyNames(obj))
console.log('Object.entries():', Object.entries(obj))
console.log('JSON.stringify():', JSON.stringify(obj))
console.log('console.log:')
console.log(obj)
console.log(obj.Name)
这是chromium上编译版本的结果
XMLHttpRequest 实例上的所有属性都是继承属性,我的意思是它们不存在于实例本身,而是存在于它的原型链上。
这解释了为什么
const x = new XMLHttpRequest()
// all these methods consider only instance properties (owned properties) and thats why they return empty results
console.log(Object.keys(x)) // []
console.log(Object.getOwnPropertyNames(x)) // []
console.log(Object.entries(x)) // []
console.log(JSON.stringify(x)) // {}
// however if you try this you will get the results you want
console.log(Object.keys(x.__proto__)) // will not return symbol keys
console.log(Object.getOwnPropertyDescriptors(x.__proto__)) // will return descriptiors of every property whether its symbol or not
// you can see these results also by logging the xmlRequest, and looking at its __proto__ property in the console
// i will be calling the XMLHttpRequest instance for short as xmlRequest
您可以像这样简单地创建这样一个对象
class A {}
A.prototype.someProperty = 10
const a = new A()
// again if you try these you will get results like the XMLHttpRequest instance
console.log(Object.keys(a)) // []
console.log(Object.getOwnPropertyNames(a)) // []
console.log(Object.entries(a)) // []
console.log(JSON.stringify(a)) // {}
然而,当您尝试 console.log(a)
时,您将不会像使用 xmlRequest 实例那样看到 someProperty
,这是预期的,因为它是继承的 属性。您在记录 xmlRequest 时看到这些属性的原因是该对象正在接受特殊处理。
幸运的是,您可以使用 chrome custom object formatters 重新创建这种特殊处理,为此您必须从 chrome 开发人员工具设置
启用自定义格式化程序window.devtoolsFormatters = [{
header: function(obj){
if (!(obj instanceof A)){
return null;
}
// to get the exact results like the xmlRequest, you need to remove quotes from the object keys in the json string, can be done with a regex
return ["div",{}, JSON.stringify(obj.__proto__)]
},
hasBody: function(){
return false;
}
}]
class A {}
A.prototype.someProperty = 10
console.log(new A()) // {"someProperty":10}
How can I create such an object in javascript, whose properties are only printed using console.log(obj), but not returned by any of the above functions?
一个接近的解决方案 我找到的是下面。这将打印带有 console.log(obj)
的属性。但是 obj 是一个代理。
在 chrome 控制台上,结果与 XMLHttpRequest
输出相同(class 为 Proxy
)。在 firefox 控制台上,它表示 Proxy
class,因此它并不完全相同。
const obj = new Proxy({prop1:"value1", prop2: "value2"}, {ownKeys: _=>[]});
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj))
console.log("Object.entries():",Object.entries(obj))
console.log("JSON.stringify():",JSON.stringify(obj))
console.log(obj)
结果:
Object.keys(): []
Object.getOwnPropertyNames(): []
Object.entries(): []
JSON.stringify(): {}
console.log:
Proxy {prop1: "value1", prop2: "value2"}
和console.log(obj.prop1) / obj.prop1="newValue"
仍然有效。
这应该可以解决问题。
var obj = Object.create({
get name(){
return 'I go only to console.log()';
}
});
console.log("Object.keys():",Object.keys(obj));
console.log("Object.getOwnPropertyNames():",Object.getOwnPropertyNames(obj));
console.log("Object.entries():",Object.entries(obj));
console.log("JSON.stringify():",JSON.stringify(obj));
console.log("console.log:", obj);