You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何归纳两个不同JavaScript构造函数的属性?及getDamage方法问题

问题解答

嘿,我来帮你搞定这两个问题,咱们一个个来:

一、怎么归纳总结两个不同构造函数的属性?

首先得明确,构造函数生成的实例,属性分两类:自有属性(就是在构造函数里用this.xxx定义的,每个实例自己独有的)和原型属性/方法(挂载在构造函数的prototype上,所有实例共享的)。要归纳两个不同构造函数的属性,你可以这么做:

  • 先单独提取每个构造函数实例的属性:
    • 拿自有属性:用Object.keys(实例),它会返回实例自己拥有的可枚举属性数组,比如你创建的bow实例,自有属性就是name和damage。
    • 拿所有可枚举属性(包括原型上的):用for...in循环遍历,再配合hasOwnProperty()判断哪些是自有属性,哪些是原型上的。
  • 然后对比两个构造函数的属性集合:看看哪些是各自独有的,哪些是共有的(比如Weapon和Character都有toString方法,但逻辑不一样)。

举个实际的例子,针对你的代码:

  • Weapon实例:自有属性是name、damage;原型属性是toString
  • Character实例:自有属性是health、basicDamage、name、weapon;原型属性是setWeapon、getDamage、toString

二、修复你的getDamage方法和代码里的小问题

先说说你代码里的几个小bug:

  1. getDamage里你写了this.damage,但武器的伤害存在this.weapon.damage里,所以这会拿不到值
  2. toString里的this.heroDamage根本没定义,而且武器的toString也没正确调用
  3. createArcher里new Character少了括号,应该是new Character()
  4. getDamage不需要传heroDamage参数,它的逻辑就是返回基础伤害加武器伤害(如果有武器的话)

下面是修正后的完整代码,我标了关键修改的地方:

function Weapon(name, damage) {
  this.name = name;
  this.damage = damage;
}
Weapon.prototype.toString = function () {
  return `${this.name} (${this.damage} damage)`; // 优化了输出格式,看起来更清楚
};
const bow = new Weapon('Golden Bow', 20);

function Character() {
  this.health = 100;
  this.basicDamage = 10;
}

// 把toString移到原型上,不用每个实例都创建一遍,省内存
Character.prototype.toString = function () {
  // 判断有没有武器,有的话就显示武器信息
  const weaponInfo = this.weapon ? `, 装备了 ${this.weapon}` : '';
  const totalDamage = this.getDamage();
  return `${this.name} - 生命值: ${this.health}, 总伤害: ${totalDamage}${weaponInfo}`;
};

// 修复工厂方法的写法,加了括号
Character.createArcher = function () {
  const hero = new Character();
  hero.name = "Legolas";
  return hero;
};

Character.prototype.setWeapon = function (weapon) {
  this.weapon = weapon;
  return this; // 支持链式调用,比如archer.setWeapon(bow).toString()
};

// 彻底修复getDamage的逻辑
Character.prototype.getDamage = function () {
  // 如果有武器,就基础伤害加武器伤害;没有的话只返回基础伤害
  return this.basicDamage + (this.weapon ? this.weapon.damage : 0);
};

// 工厂方法不用加new,它本身就返回实例
const archer = Character.createArcher();
archer.setWeapon(bow);
console.log(archer.toString());
// 输出:Legolas - 生命值: 100, 总伤害: 30, 装备了 Golden Bow (20 damage)

我再给你讲讲关键修改点:

  • getDamage:去掉了多余的参数,加了判断武器是否存在的逻辑,这样没武器的时候也能正确返回基础伤害
  • toString:重新写了逻辑,正确调用武器的toString方法,输出的信息也更完整
  • createArcher:修正了new Character()的写法,调用的时候不用加new,更符合工厂函数的用法
  • 把Character的toString移到原型上,避免每个实例都重复创建这个方法,节省内存

额外小工具:自动归纳属性的函数

如果你想更方便地归纳不同构造函数的属性,可以写个小工具函数:

function getInstancePropertyInfo(instance) {
  // 提取自有属性
  const ownProps = Object.keys(instance);
  // 提取原型链上的属性
  const protoProps = [];
  let currentProto = Object.getPrototypeOf(instance);
  
  // 遍历原型链,直到Object.prototype
  while (currentProto !== Object.prototype) {
    protoProps.push(...Object.keys(currentProto));
    currentProto = Object.getPrototypeOf(currentProto);
  }

  return {
    自有属性: ownProps,
    原型属性: protoProps
  };
}

// 测试一下
console.log(getInstancePropertyInfo(bow));
// { 自有属性: ['name', 'damage'], 原型属性: ['toString'] }
console.log(getInstancePropertyInfo(archer));
// { 自有属性: ['health', 'basicDamage', 'name', 'weapon'], 原型属性: ['toString', 'setWeapon', 'getDamage'] }

这个函数能帮你快速提取实例的自有属性和原型属性,对比两个构造函数的属性就很方便啦~

内容的提问来源于stack exchange,提问作者Igor Shvets

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:29:05