小熊奶糖(BearCandy)
小熊奶糖(BearCandy)
发布于 2025-10-05 / 0 阅读
0
0

JavaScript获取所有对象属性和方法

在JavaScript中,有多种方式可以获取对象的所有方法和属性。以下是常用的几种方法:

  1. Object.keys()

获取对象自身的可枚举属性(不包括原型链上的属性)

const obj = {
  name: 'John',
  age: 30,
  sayHello() {
    console.log('Hello');
  }
};

// 添加一个不可枚举属性
Object.defineProperty(obj, 'hiddenProp', {
  value: 'hidden',
  enumerable: false
});

console.log(Object.keys(obj)); // ['name', 'age', 'sayHello']
  1. Object.getOwnPropertyNames()

获取对象自身的所有属性(包括不可枚举属性,但不包括Symbol属性)

console.log(Object.getOwnPropertyNames(obj)); 
// ['name', 'age', 'sayHello', 'hiddenProp']
  1. Object.getOwnPropertySymbols()

获取对象自身的所有Symbol属性

const sym = Symbol('description');
obj[sym] = 'symbol value';

console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(description)]
  1. Reflect.ownKeys()

获取对象自身的所有属性(包括字符串键、Symbol键,无论是否可枚举)

console.log(Reflect.ownKeys(obj)); 
// ['name', 'age', 'sayHello', 'hiddenProp', Symbol(description)]
  1. for...in 循环

遍历对象及其原型链上的可枚举属性

function Person(name) {
  this.name = name;
}
Person.prototype.sayHello = function() {
  console.log('Hello');
};

const person = new Person('John');
person.age = 30;

for (let key in person) {
  console.log(key); // 'name', 'age', 'sayHello'
}

// 只获取自身属性
for (let key in person) {
  if (person.hasOwnProperty(key)) {
    console.log(key); // 'name', 'age'
  }
}
  1. 区分方法和属性
function getAllMethods(obj) {
  return Object.getOwnPropertyNames(obj)
    .filter(key => {
      return typeof obj[key] === 'function';
    });
}

function getAllProperties(obj) {
  return Object.getOwnPropertyNames(obj)
    .filter(key => {
      return typeof obj[key] !== 'function';
    });
}

const example = {
  name: 'Test',
  value: 100,
  method1() {},
  method2() {}
};

console.log('Methods:', getAllMethods(example)); // ['method1', 'method2']
console.log('Properties:', getAllProperties(example)); // ['name', 'value']
  1. 获取包括原型链上的所有方法
function getAllMethodsIncludingPrototype(obj) {
  const methods = new Set();
  
  // 遍历当前对象及其原型链
  let current = obj;
  while (current && current !== Object.prototype) {
    Object.getOwnPropertyNames(current)
      .filter(key => typeof current[key] === 'function')
      .forEach(method => methods.add(method));
    current = Object.getPrototypeOf(current);
  }
  
  return Array.from(methods);
}

class Parent {
  parentMethod() {}
}

class Child extends Parent {
  childMethod() {}
}

const instance = new Child();
console.log(getAllMethodsIncludingPrototype(instance)); 
// ['childMethod', 'parentMethod']
  1. 完整的工具函数
function inspectObject(obj) {
  console.log('=== 对象检查 ===');
  console.log('Object.keys():', Object.keys(obj));
  console.log('Object.getOwnPropertyNames():', Object.getOwnPropertyNames(obj));
  console.log('Object.getOwnPropertySymbols():', Object.getOwnPropertySymbols(obj));
  console.log('Reflect.ownKeys():', Reflect.ownKeys(obj));
  
  console.log('\n=== 方法列表 ===');
  const methods = Object.getOwnPropertyNames(obj)
    .filter(key => typeof obj[key] === 'function');
  console.log('Methods:', methods);
  
  console.log('\n=== 属性列表 ===');
  const properties = Object.getOwnPropertyNames(obj)
    .filter(key => typeof obj[key] !== 'function');
  console.log('Properties:', properties);
}

// 使用示例
const testObj = {
  prop1: 'value1',
  prop2: 123,
  method1() {},
  method2() {}
};

inspectObject(testObj);

注意事项

  1. 可枚举性:Object.keys() 和 for...in 只返回可枚举属性
  2. 原型链:for...in 会遍历原型链,其他方法只返回自身属性
  3. Symbol属性:需要使用专门的方法来获取
  4. 性能考虑:在性能敏感的场景中,避免频繁使用这些反射方法

根据你的具体需求选择合适的方法来获取对象的属性和方法。


评论