我对 JavaScript 为什么以某种方式工作感到困惑。
如果我有一个对象被设置为变量obj,并且如果我想列出对象中的所有键,则会这样说
Object.keys(obj)
为什么不是下面这样呢?
obj.keys()
如果我正在使用数组,那么应该使用arr.pop()。 那么为什么在 obj.keys() 中不使用相同的语法呢?为什么它必须是 Object.keys(obj)?
我对 JavaScript 为什么以某种方式工作感到困惑。
如果我有一个对象被设置为变量obj,并且如果我想列出对象中的所有键,则会这样说
Object.keys(obj)
为什么不是下面这样呢?
obj.keys()
如果我正在使用数组,那么应该使用arr.pop()。 那么为什么在 obj.keys() 中不使用相同的语法呢?为什么它必须是 Object.keys(obj)?
你可以在Object.prototype
上定义一个keys
方法使其符合你的预期,但这不是一个好主意。
Object.prototype.keys = function() {
return Object.keys(this);
};
const obj = {
prop: 'val'
};
const keys = obj.keys();
console.log(keys);
使用对象键的问题在于,对象通常可以具有任何类型的键。该对象甚至可能具有名为keys
的键。例如:
const obj = {
name: 'building 1',
keys: 'foo'
}
在这里,如果你执行obj.keys()
,你会得到一个TypeError
,因为keys
属性是指对象直接拥有的属性,而不是Object.prototype
方法。
Object.prototype.keys = function() {
return Object.keys(this);
};
const obj = {
name: 'building 1',
keys: 'foo'
};
const keys = obj.keys();
console.log(keys);
Object
上作为静态方法,而不是原型方法Object.prototype
上,以避免可能的名称冲突。另一方面,普遍期望数组具有特定的几个方法(如push
),而且没有其他内容。数组不是通用对象 - 你几乎总是期望一个数组只有数组方法,而且数组几乎从不会添加任意键(如果您看到有这样的代码,那么它可能值得重构)。因此,对于数组,不存在像通用对象那样的数组方法导致名称冲突的实际可能性。因此,有Array.prototype.push
没有问题,但Object.prototype.keys
很容易引起问题。除了假设的 keys()
方法可能被隐藏外,还有可能该值根本不是Object
实例。
考虑以下示例:
// properly define your suggested method
Object.defineProperty(Object.prototype, 'keys', {
configurable: true,
writable: true,
value: function keys () { return Object.keys(this); }
})
const obj = { foo: 'bar', hello: 'world' };
console.log(obj instanceof Object);
// okay
console.log(obj.keys());
const value = Object.create(
null,
Object.getOwnPropertyDescriptors(obj)
);
console.log(value instanceof Object);
// existing approach still works
console.log(Object.keys(value));
// suggested approach fails
console.log(value.keys());