console.log 或 utils.inspect 的隐藏属性

Hidden properties to console.log or utils.inspect

我正在使用 sails.js waterline orm。现在这不是一个特别的帆问题,但我必须放置一些上下文,所以当你创建一个记录时,你会得到一个 object 和创建的数据。如果该记录关联了其他记录 (collections),则它具有与返回的 object 中的记录相关的键,但这些键是 getters/setters,即使相关的数据不存在objects.

为了突出重点,我简化了一些事情。

这是我的用户模型:

var User = {
 attributes: 
   status: {type:'string'}
   images: {
     collection: 'Image'
   }
}

假设,我在用户模型上执行了创建查询,该模型关联了图像 collection。 userRecord 是查询返回的内容。 如果我 console.log 这个出来它显示了与模型本身相关的属性 但不是关联的记录,即使密钥确实存在,您也可以 访问它但对 console.log 或 utils.inspec 不可见,即使将 show hidden 设置为 true。

console.log(userRecord)

这是返回的内容

{ name: 'zaggen'}

这是应该返回的内容

{ name: 'zaggen',
  images: [{ 
    path: 'some-path/img.png'
  }] 
 }

我可以像这样访问隐藏的 属性:

console.log(userRecord.images[0].path) 
// outputs some-path/img.png

这怎么可能?据我所知,没有办法将信息隐藏到节点中的 console.log,除非在 __proto__ object,但在这种情况下它们不是。

在搜索这个之后我没有找到任何东西而且它很奇怪所以我认为这可能是一个很好的问题。如果我可以 console.log 此信息并获取所有数据,这将对我的工作流程有所帮助,现在我可以使用 lodash 并调用克隆或默认值,并且我得到了 object 它应该的。

Sails 使用定义模型的水线。如果您查看它的源代码,您会看到:

https://github.com/balderdashy/waterline/blob/77fe3a9b9a9b12110a6ba079a84e5cd43a4369db/lib/waterline/model/lib/model.js#L57-L75

/**
 * Log output
 * @return {String} output when this model is util.inspect()ed
 * (usually with console.log())
 */

Object.defineProperty(this, 'inspect', {
  enumerable: false,
  configurable: false,
  writable: false,
  value: function() {
    var output;
    try {
      output = self.toObject();
    } catch (e) {}

    return output ? util.inspect(output) : self;
  }
});

因此他们将 console.log 输出覆盖为 self.toObject()。这是他们的 internal methods 之一,可以执行各种可能导致您看到的输出的事情。例如:

// Don't run toJSON on records that were not populated
if (!self.proto._properties || !self.proto._properties.joins) return;

或:

if (!this.proto._properties.showJoins) return;

我在他们的集成测试中注意到,他们在创建模型时将 { showJoins: true } 作为第二个参数传递。我在文档中找不到任何关于它的信息,但也许你可以试试看?

https://github.com/balderdashy/waterline/blob/48dc007b69a133169651aeb422fa3a61c3c6802c/test/integration/model/save.js#L150

as far as i know there is no way to hide info to the console.log in node, except maybe when the properties are defined in the proto object

在 ES5 中不再如此。在 ES3 中是这样。

请注意,即使在原始 javascript 中,对象和函数也具有隐藏属性,例如 .__proto__.constructor.prototype?就像某些原生 javascript 对象具有这些神奇的功能(比如设置 innerHTML 可以调用 HTML 编译器)。 ES5 通过 Object.defineproperty.

暴露了所有的魔力

console.log() 中隐藏 属性 的具体特征是 enumerable。在 属性 上将其设置为 false 使其对 for..in 隐藏(不再需要 .hasOwnProperty()):

var foo = {a:1}
Object.defineProperty(foo,'b',{
    enumerable: false, // hide it from for..in
    value: 2
})

console.log(foo); // prints out {a:1}
console.log(foo.b); // prints out 2

还有其他有用的功能,例如 getter 和 setter(允许您模拟像 .innerHTML 这样的属性,在您写入时调用函数)和 writable(允许您制作 属性只读)。有关详细信息,请参阅完整文档:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty