如何归纳两个不同JavaScript构造函数的属性?及getDamage方法问题
问题解答
嘿,我来帮你搞定这两个问题,咱们一个个来:
一、怎么归纳总结两个不同构造函数的属性?
首先得明确,构造函数生成的实例,属性分两类:自有属性(就是在构造函数里用this.xxx定义的,每个实例自己独有的)和原型属性/方法(挂载在构造函数的prototype上,所有实例共享的)。要归纳两个不同构造函数的属性,你可以这么做:
- 先单独提取每个构造函数实例的属性:
- 拿自有属性:用
Object.keys(实例),它会返回实例自己拥有的可枚举属性数组,比如你创建的bow实例,自有属性就是name和damage。 - 拿所有可枚举属性(包括原型上的):用
for...in循环遍历,再配合hasOwnProperty()判断哪些是自有属性,哪些是原型上的。
- 拿自有属性:用
- 然后对比两个构造函数的属性集合:看看哪些是各自独有的,哪些是共有的(比如
Weapon和Character都有toString方法,但逻辑不一样)。
举个实际的例子,针对你的代码:
Weapon实例:自有属性是name、damage;原型属性是toStringCharacter实例:自有属性是health、basicDamage、name、weapon;原型属性是setWeapon、getDamage、toString
二、修复你的getDamage方法和代码里的小问题
先说说你代码里的几个小bug:
getDamage里你写了this.damage,但武器的伤害存在this.weapon.damage里,所以这会拿不到值toString里的this.heroDamage根本没定义,而且武器的toString也没正确调用createArcher里new Character少了括号,应该是new Character()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
相关产品推荐
相关产品推荐

