为什么XMLHttpRequest对象的属性只能通过console.log()打印?

时间:2018-05-24 10:21:27

标签: javascript xmlhttprequest

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()打印,但不是由任何上述函数返回?

我已尝试使用constructor functionobject.create()(使用enumerable:false),Object.assign(),使用getters创建对象,从类中设置,启动来自扩展班等

10 个答案:

答案 0 :(得分:4)

这与WhatWG import io.github.bonigarcia.wdm.WebDriverManager; specification有关:

实现如何打印args取决于实现,但是实现应该用空格或类似的东西来分隔对象,因为这已经成为开发人员的期望。

该规范使输出格式非常模糊,具体取决于实现方式来决定要打印什么。

答案 1 :(得分:3)

您可以使用称为Symbol的新数据类型来创建JavaScript对象的键。

链接: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"}

答案 2 :(得分:3)

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}

答案 3 :(得分:1)

如何在javascript中创建这样的对象,该对象的属性仅使用console.log(obj)打印,而上述任何函数均未返回?

我发现的一个封闭解决方案下面的。这将使用console.log(obj)打印属性。但是obj是代理。

在chrome控制台上,结果与XMLHttpRequest的输出相同(类为Proxy)。在firefox控制台上,它是Proxy类的表示形式,因此并不完全相同。


    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:
代理{prop1:“ value1”,prop2:“ value2”}

console.log(obj.prop1) / obj.prop1="newValue"仍然有效。

答案 4 :(得分:0)

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)

答案 5 :(得分:0)

这是因为原型在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)

您将看到:

console prints

答案 6 :(得分:0)

为什么XMLHttpRequest对象的属性只能通过console.log()打印?

那不是真的

var obj = new XMLHttpRequest();
for(var key in obj) console.log(key);

说明中的问题答案

如何在javascript中创建这样的对象,该对象的属性仅使用

打印
  var obj = Object.create({ foo: "foo", constructor: function() {} });

如果您想从for in隐藏属性,则应将enumerable属性设置为false以获取所需属性:

Object.defineProperty(obj, 'foo', {
  value: 42,
  enumerable: false
});

答案 7 :(得分:0)

我认为这是最实用的方法。它将对您有帮助

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)

这是铬的编译版本的结果 enter image description here

答案 8 :(得分:0)

这应该可以解决问题。

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);

答案 9 :(得分:-1)

您可以这样做:

<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="stackoverflow.labeltest.Controller">
    <children>
        <HBox AnchorPane.rightAnchor="0" AnchorPane.leftAnchor="0">
            <children>
                <Label fx:id="label"/>
            </children>
        </HBox>
    </children>
</AnchorPane>

具体而言,Object.defineProperty(obj, 'key', { enumerable: false, value: '123' }); thingie隐藏了该属性。

有关详情,请参阅此页:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

<强>更新

下面的方法(上面的改进版本)似乎隐藏了所有提到的检查的属性,虽然它有点冗长:

enumerable