RPG Maker MZ插件开发:如何将函数返回值而非函数本身赋值给变量?
问题背景
我正在开发RPG Maker MZ的首个插件,仅有Java开发经验,因JavaScript弱类型系统遇到问题:变量filteredList被赋值为函数本身,而非函数返回值,导致出现TypeError: Cannot read property 'price' of undefined错误。
该代码用于替换游戏中敌人战利品的默认判定逻辑:每个敌人拥有CommonDropWorth属性,表示其普通掉落物品的总价值,通过while循环随机选取物品,直到掉落物品总价值接近该值。每次CommonDropWorth减少后,需要更新filteredList以过滤掉价值超出剩余额度的物品。
问题代码
let actualDropList = new Array; commonItemList.forEach(matchedElement => { commonItemDataList.push($dataItems[matchedElement]); console.log($dataItems[matchedElement]); } ); let CommonDropWorth = this.enemy().meta.HellsCommonDropBase /*+ (enemy.dataObject.meta.HellsCommonDropFlat * (this.enemy.level-1))*/; var filteredList = commonItemDataList.filter(Item => Item.price <= CommonDropWorth); var cleanFilteredList = function(){ return commonItemDataList.filter(Item => Item.price <= CommonDropWorth); }; while (filteredList.length > 0){ let item; if (filteredList.length > 1){ item = filteredList[Math.floor(Math.random()*filteredList.length)]; CommonDropWorth = CommonDropWorth - item.price; } else if(filteredList.length = 0){ item = filteredList[0]; CommonDropWorth = CommonDropWorth - item.price; } actualDropList.push(item); filteredList = cleanFilteredList.apply; } return actualDropList;
我的疑问
- 如何将
filteredList赋值为cleanFilteredList函数的返回值而非函数本身? - 如何避免代码中出现错误类型的对象赋值?
解决方案
问题1:正确获取函数返回值
要拿到函数的返回结果,直接**调用函数(加圆括号())**即可,apply是用来指定函数执行上下文和传递参数的方法,你这里不需要用到它。
把错误的赋值代码:
filteredList = cleanFilteredList.apply;
修改为:
filteredList = cleanFilteredList();
这样filteredList就会被赋值为函数执行后返回的过滤数组,而非函数对象本身。
问题2:避免错误类型赋值及额外代码修正
结合Java背景,针对JS弱类型特性,给出以下避坑方案和代码修正:
杜绝条件里的赋值操作
原代码中else if(filteredList.length = 0)是赋值语句,会把filteredList.length强行设为0,同时这个条件会被判定为false(因为0是假值),导致逻辑完全混乱。另外,while循环的条件是filteredList.length > 0,循环内部不可能出现长度为0的情况,所以这里应该修正为判断长度为1的场景:else if(filteredList.length === 1){ item = filteredList[0]; CommonDropWorth -= item.price; }记住:条件判断永远用
===(严格相等),避免==的隐式类型转换,绝对不要在条件里写=。用
let/const约束变量类型和作用域
用const声明不会被重新赋值的变量(比如cleanFilteredList),用let声明需要重新赋值的变量,替代松散的var,能减少意外的变量覆盖和类型变更:const cleanFilteredList = function(){ return commonItemDataList.filter(Item => Item.price <= CommonDropWorth); };区分函数引用与函数执行
在JS中,不加()的函数名只是指向函数的引用(即函数本身),只有加()才会执行函数并返回结果,这是和Java方法调用的核心区别之一,一定要牢记。其他代码优化
- 数组初始化用
[]替代new Array(),更简洁易读 - 修正
forEach的语法错误(原代码闭合括号位置错误) - 用
CommonDropWorth -= item.price简化赋值逻辑
- 数组初始化用
修正后的完整代码
let actualDropList = []; commonItemList.forEach(matchedElement => { commonItemDataList.push($dataItems[matchedElement]); console.log($dataItems[matchedElement]); }); let CommonDropWorth = this.enemy().meta.HellsCommonDropBase /*+ (enemy.dataObject.meta.HellsCommonDropFlat * (this.enemy.level-1))*/; let filteredList = commonItemDataList.filter(Item => Item.price <= CommonDropWorth); const cleanFilteredList = function(){ return commonItemDataList.filter(Item => Item.price <= CommonDropWorth); }; while (filteredList.length > 0){ let item; if (filteredList.length > 1){ item = filteredList[Math.floor(Math.random() * filteredList.length)]; CommonDropWorth -= item.price; } else if(filteredList.length === 1){ item = filteredList[0]; CommonDropWorth -= item.price; } actualDropList.push(item); filteredList = cleanFilteredList(); } return actualDropList;
内容的提问来源于stack exchange,提问作者Helli

