JavaScript如何通过子类修改默认函数实现游戏关卡差异化行为?
解决关卡继承差异化行为的问题
嘿,我来帮你梳理下这个问题~你的核心需求是让不同关卡继承基础行为的同时重写特定方法,但原代码的实现有两个关键问题:
- 错误的继承写法:
Level1里给this.prototype赋值完全不对——prototype是构造函数(比如Level1这个函数本身)的属性,不是实例的属性,这么写根本不会让Level1实例继承game的属性和方法。 - 实例未更新:
load方法里new Level1(this)只是创建了一个新的Level1实例,但并没有把原来的game对象替换成这个新实例,所以game始终是LevelBase的实例,调用func自然返回默认的123。
下面给你几种可行的实现方案,按需选择:
方案一:ES6 Class继承(推荐,代码更清晰)
用ES6的类语法糖实现继承,写法更符合面向对象的直觉:
"use strict"; class LevelBase { constructor() { // 这里可以定义所有关卡通用的实例属性 } load(level) { if (level === 1) { return new Level1(); } // 后续可以添加其他关卡的判断,比如level===2时返回Level2 return this; } func() { return 123; // 默认行为 } } class Level1 extends LevelBase { constructor() { super(); // 必须调用super,继承父类的构造逻辑 } func() { return 456; // 重写默认行为 } } // 使用方式 let game = new LevelBase(); game = game.load(1); // 替换为Level1实例 console.log(game.func()); // 输出456
方案二:ES5原型继承
如果需要兼容旧环境,可以用ES5的原生原型继承写法:
"use strict"; function LevelBase() { // 通用实例属性 } // 把通用方法放到原型上,节省内存 LevelBase.prototype.load = function(level) { if (level === 1) { return new Level1(); } return this; }; LevelBase.prototype.func = function() { return 123; }; function Level1() { LevelBase.call(this); // 调用父构造函数,继承实例属性 } // 让Level1原型继承LevelBase原型 Level1.prototype = Object.create(LevelBase.prototype); Level1.prototype.constructor = Level1; // 修正构造函数指向 // 重写方法 Level1.prototype.func = function() { return 456; }; // 使用方式 var game = new LevelBase(); game = game.load(1); console.log(game.func()); // 输出456
方案三:混入模式(不替换实例)
如果不想替换原game实例的引用,可以用混入的方式,直接在原实例上覆盖方法:
"use strict"; function LevelBase() { this.func = function() { return 123; }; this.load = function(level) { if (level === 1) { // 把Level1的方法混入当前实例 Object.assign(this, Level1.prototype); // 如果Level1有初始化逻辑,调用构造函数 Level1.call(this); } }; } function Level1() { // Level1专属的初始化逻辑 } Level1.prototype.func = function() { return 456; }; var game = new LevelBase(); game.load(1); console.log(game.func()); // 输出456
这几种方案都能实现你要的“保留通用默认行为+关卡差异化”的需求,其中ES6 Class的写法最推荐,代码可读性和维护性都更高~
内容的提问来源于stack exchange,提问作者MysteryPancake
相关产品推荐
相关产品推荐

