古树旋律 发表于 2023-2-18 22:31:57

RMMV、MZ插件中常用的call(this)形式解读

在我们使用的一些插件中,经常会遇到Call(this)的形式。比如官方HPConsumeSkill.js插件中的这个:
var _Scene_Boot_start = Scene_Boot.prototype.start;
Scene_Boot.prototype.start = function() {
    _Scene_Boot_start.call(this);//call(this)的目的是什么?
    DataManager.processHpCost();
};


而网上对call()函数的解读又很抽象,对于我们制作RM来说还是云里雾里。所以,这里我举例来说明call(this)的实际意义。





如果查看系统默认的脚本,可以搜索到Scene_Boot.prototype.start是已经有过函数定义的,而且涉及到的东西还不少(知道有这写代码即可,不需要知道实际含义)。
Scene_Boot.prototype.start = function() {
    Scene_Base.prototype.start.call(this);
    SoundManager.preloadImportantSounds();
    if (DataManager.isBattleTest()) {//如果是战斗测试
      DataManager.setupBattleTest();
      SceneManager.goto(Scene_Battle);
    } else if (DataManager.isEventTest()) { //如果是事件测试
      DataManager.setupEventTest();
      SceneManager.goto(Scene_Map);
    } else {//开始普通/new游戏
      this.startNormalGame();
    }
    this.resizeScreen();
    this.updateDocumentTitle();
};

而这个HPConsumeSkill.js(技能消耗生命值)插件,又偏偏需要在启用Scene_Boot.prototype.start函数时,追加一个DataManager.processHpCost()的函数。新插件因为排序在默认脚本之后,所以当然可以重新在写一次Scene_Boot.prototype.start覆盖,最后在加上DataManager.processHpCost(),如下:
Scene_Boot.prototype.start = function() {
    Scene_Base.prototype.start.call(this);
    SoundManager.preloadImportantSounds();
    if (DataManager.isBattleTest()) {//如果是战斗测试
      DataManager.setupBattleTest();
      SceneManager.goto(Scene_Battle);
    } else if (DataManager.isEventTest()) { //如果是事件测试
      DataManager.setupEventTest();
      SceneManager.goto(Scene_Map);
    } else {//开始普通/new游戏
      this.startNormalGame();
    }
    this.resizeScreen();
    this.updateDocumentTitle();
    DataManager.processHpCost();//新加入的部分
};
但是这样会导致插件特别冗长,而且一旦多方面涉及此函数Scene_Boot.prototype.start,j修改会特别繁琐。
这时,插件制作者们会先使用var定义一个名词相近的变量,然后将原函数赋值给这个变量,如:
var _Scene_Boot_start = Scene_Boot.prototype.start;
然后,插件制作者重新对Scene_Boot.prototype.start进行一次定义。即帖子开头部分。
而_Scene_Boot_start.call(this);实际上就是把原先的旧函数内容从函数_Scene_Boot_start中搬运过来(注意插件制作者们一般会用下划线区分)

古树旋律 发表于 2023-2-18 22:35:01

本帖最后由 古树旋律 于 2023-2-18 22:48 编辑

举例说明,将这段代码放入到在线工具频道下的HTML在线运行-RPGMV (rpgmz.com)实际测试一下。
第一个myFunction函数是显示Hello World!,而第二个myFunction函数是显示Hello World!和Hello!。第二个函数因排在下面,所以会覆盖掉第一个函数。如果把_myFunction.call(this);删除,则只显示Hello!

因为网站原因,“点我” 这一行的完整代码应该设置如下:


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试实例</title>
<script>
myFunction = function()
{
    alert("Hello World!");
}

var _myFunction = myFunction;
myFunction = function()
{
      _myFunction.call(this);
    alert("Hello!");
}

</script>
</head>

<body>
<button>点我</button>
</body>
</html>
页: [1]
查看完整版本: RMMV、MZ插件中常用的call(this)形式解读