如何获取js类中的所有属性和方法

  在java,php等一些后端语言中,都有特定的方法获取到类中的所有属性和方法,但是在js中却没有这样的API,随着es的发展预计会在未来出现.但是目前我们也可以自己实现这样的需求,题目如下:

class One {
    constructor() {
        this.nameOne = 'One'
    }
    validateOne() {
        console.log("one")
    }
}

class Two extends One {
    constructor() {
        super()
        this.nameTwo = 'Two'
    }

    validateTwo() {
        console.log("two")
    }
}

class Three extends Two {

    constructor() {
        super()
        this.nameThree = 'three'
    }

    validateThree() {
        console.log("three")
    }
}

类Three继承类Two,而类Two又继承类One,现在实例化一个对象 ,let three = new Three(),如何输出three上面的所有自定义的属性和方法呢?

此时我们可以直接在控制台打印出three对象,看下该实例上面具体含有哪些属性:

从上面打印出的three对象可知,类Three继承类Two,而类Two又继承类One,此时实例化的three对象含有三个属性nameOne,nameTwo和nameThree.其中nameOne,nameTwo这两个属性全部在three对象上,并不在原型链上,但是validateOne,validateTwo,validateThree这三个自定义方法全部在原型链上面.

 

另外我们会想到使用in循环遍历对象three,希望能输出原型链上的方法名,伪代码如下:

for(let key in three){
  console.log(key);
}

输出结果:'nameOne','nameTwo','nameThree';

in循环能够遍历到对象以及其原型链上面的所有可枚举属性,但是它并不能输出方法名,所以我们需要自定义一个工具函数来实现我们的需求,具体调用形式如下,函数名如下findProperties,第一个参数传入要查询的对象实例,后面的“name”和“validate”是我们想要输出的自定义属性和方法的前缀.

const data = findProperties(three, 'name', 'validate');

console.log(data)

findProperties实现如下:

function findProperties(obj,...arg){
  
  function getProperty(new_obj){

    if(new_obj.__proto__ === null){ //说明该对象已经是最顶层的对象
        return [];
    }

    let properties = Object.getOwnPropertyNames(new_obj);

    let arr = [];  
  
    arg.forEach((v)=>{
  
      const newValue = properties.filter((property)=>{
          return property.startsWith(v);
      })
  
      if(newValue.length>0){
          arr = arr.concat(newValue);
      }
  
    })

    return [...arr,...getProperty(new_obj.__proto__)];

  }

  return getProperty(obj);   


}

解析:这里需要格外注意的便是 Object.getOwnPropertyNames() ,该方法返回对象的所有自身属性的属性名(包括不可枚举的属性)组成的数组,但不会获取原型链上的属性.每一次嵌套函数的执行都是获取该层对象上面的所有属性和方法,紧接着将该对象.__proto__作为参数继续传入嵌套函数作为参数,以继续获取该对象的父对象上面的所有属性和方法.

                                                                  

我们可以看一下上面这几行在控制台输入的测试代码,从这几行代码我们可得出一些结论,所有自定义对象的原型链的顶层都是Object的原型对象,即Object.prototype,而Object.prototype.__proto__则为null,我们可以利用此特征作为嵌套函数的中止条件.

 

完整代码如下:

class One {
    constructor() {
        this.nameOne = 'One'
    }
    validateOne() {
        console.log("one")
    }
}

class Two extends One {
    constructor() {
        super()
        this.nameTwo = 'Two'
    }

    validateTwo() {
        console.log("two")
    }
}

class Three extends Two {

    constructor() {
        super()
        this.nameThree = 'three'
    }

    validateThree() {
        console.log("three")
    }
}


function findProperties(obj,...arg){
  
  function getProperty(new_obj){

    if(new_obj.__proto__ === null){ //说明该对象已经是最顶层的对象
        return [];
    }

    let properties = Object.getOwnPropertyNames(new_obj);

    let arr = [];  
  
    arg.forEach((v)=>{
  
      const newValue = properties.filter((property)=>{
          return property.startsWith(v);
      })
  
      if(newValue.length>0){
          arr = arr.concat(newValue);
      }
  
    })

    return [...arr,...getProperty(new_obj.__proto__)];

  }

  return getProperty(obj);   


}


let three = new Three()

const data = findProperties(three, 'name', 'validate');

console.log(data)


 

nodejs运行的效果如下:

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值