我写一些代码来扩展Object
,我想遍历对象中的方法。当我输出this.constructor
的值,我看到我想(在下面的例子中我看到test
)的方法。然而,当我环并且使用为这些方法,它只显示方法getType
。我怎样才能得到class A
的只是方法?
Object.prototype.getType = function () {
// Outputs correct class and methods
console.log(this.constructor)
for (let i in this.constructor) {
// Outputs wrong methods
console.log(i)
}
}
class A {
test() {console.log('hello')}
}
new A().getType()
两个问题:
class
定义一个方法,默认是不可枚举。 (Object.prototype.getType
,在另一方面,是枚举,因为这是默认的,当您通过分配的属性。)test
非静态的方法是构造函数的prototype
财产(A.prototype
)的性质,而不是构造函数本身(A.test
不是一回事)。你可以找到与Object.getOwnPropertyNames
功能不可枚举的属性:
Object.prototype.getType = function () {
for (let name of Object.getOwnPropertyNames(this.constructor.prototype)) {
console.log(name)
}
}
请注意,这不仅包括自己的属性 - 性能直接在物体上 - 所以,如果你想包括继承的方法,你就必须去检查原型链。
function* getAllPropertyNames(obj) {
do {
yield* Object.getOwnPropertyNames(obj)
} while (obj = Object.getPrototypeOf(obj))
}
Object.prototype.getType = function () {
for (let name of getAllPropertyNames(this.constructor.prototype)) {
console.log(name)
}
}
如果你要包括直接在物体上的属性,你就必须从这里开始(希望this.constructor.prototype
是Object.getPrototypeOf(this)
)。
Object.prototype.getType = function () {
for (let name of getAllPropertyNames(this)) {
console.log(name)
}
}
另外,不要延长Object.prototype
。特别是没有枚举的属性。管理不负责,当你做到这一点,在神秘的方式打破依赖。
也许不是最完美的解决方案,但要做到这一点的一种方式是通过调用Object.getOwnPropertyNames()
,传递对象实例__proto__
参考。
Object.prototype.getType = function () {
/*
// Outputs correct class and methods
console.log(this.constructor)
for (let i in this.constructor) {
// Outputs wrong methods
console.log(i)
}
*/
for(let j of Object.getOwnPropertyNames(this.__proto__)
.filter(method => method !== 'constructor'))
{
// Outputs properties of prototype, without constructor method
console.log(j);
}
}
class A {
test() {console.log('hello')}
}
new A().getType()
对GetType名字似乎不合适,你要找的是什么性质,所以getAllProperties似乎一个更好的名字。
正如其他人所说,你需要去了[[Prototype]]
链有许多原因:
所述[[Prototype]]
链在零结束,这是原型的Object.prototype是所有原型的层次结构的顶部。该函数也应删除重复,可在每个原型发生(例如构造,并且长度是很常见)。
function getAllProperties(obj) {
// Recursively get properties up [[Prototype]] chain
function loop(obj) {
let props = Object.getOwnPropertyNames(obj);
let proto = Object.getPrototypeOf(obj);
// Stop at null
if (proto !== null) {
return props.concat(loop(proto));
}
return props;
}
let allProps = loop(obj);
// Remove duplicates
return allProps.filter((prop, i) => !allProps.includes(prop, i+1));
}
console.log(getAllProperties('a'))
如果你只想方法,然后过滤,你去typeof x == 'function'
:
function getAllMethods(obj) {
// Recursively get properties up [[Prototype]] chain
function loop(obj) {
// Get all properties, filter for functions
let props = Object.getOwnPropertyNames(obj).filter((prop, i, props) => typeof props[prop] == 'function');
let proto = Object.getPrototypeOf(obj);
// Stop at null
if (proto !== null) {
return props.concat(loop(proto));
}
return props;
}
let allMethods = loop(obj);
// Remove duplicates
return allMethods.filter((prop, i) => !allMethods.includes(prop, i + 1));
}
console.log(getAllMethods('a'))