【问题标题】:Call the method of a method if it exists如果存在,则调用方法的方法
【发布时间】:2015-07-02 00:44:06
【问题描述】:

首先我应该指出,我是 JS 和 node.js 的新手。我正在尝试编写一个 node.js 聊天机器人,目前正在使用命令。

我的问题是调用方法的方法.. 如果可能的话。 这是相关部分:

    var text; // received message from user
    var userId; // Id of the user, number.
    if (cmd.hasOwnProperty(text.split(' ')[0])) { // Message will be a string, it should be ignore if the first word is not a command name.
        console.log("[Inc]" + userId + ": " + text)
        if (text.split(' ').length === 1) { // If the command name is not followed by any arguments then the only argument passed should be the userID(used to send replies to the user).
            cmd[text.split(' ')[0]](userId)
        } else {
            var args = [] // Placing all args in  an array because the commands will take different number of arguments, a calculator command for example could take a lot of args.
            for (var i = 1; i < text.split(' ').length; i++) {
                args.push(text.split(' ')[i])
            }
            console.log(args)
            cmd[text.split(' ')[0]](userId, args)
        }   
    } else {
        console.log("Command not found, try again");    
    }
    var cmd = {
        help : function () {
            cookies : function () { // 
                console.log('Cookies recipe')
            }
            if (arguments.length === 1) {
            console.log('General help text');
            } else if (help.hasOwnProperty(arguments[1])) { 
                this[arguments[0]](); // Seems my problem was here, this was creating the reference error.
            } else {
                console.log('Requested topic not found')
            }   
        },
        invite : function(id) { 
            send_PRIVGRP_INVITE(id)
        }   

    }

任何想法我可以如何使这项工作,或者有更好的方法,更清洁的方法来做到这一点。另外我应该提到我选择使用命令作为对象和方法,因为有些命令会更复杂,我打算给他们他们的 on file.js 并将其导出到 main.js 文件,这样添加起来会容易得多无需编辑主文件的命令。

请记住,我对此很陌生,详细的解释将有很长的路要走,谢谢。

【问题讨论】:

  • 注释为“我的第一个问题在这里...”的行并没有按照您的想法进行。你不能像这样组合函数和对象定义。 (它不会抛出语法错误只是因为完全巧合这是有效的语法,但与您的预期完全不同。)
  • 嗯,它会按照我的意图去做,但不是什么时候,那是我的问题 :)
  • @Trax 肯定不是;你有一个带有块的标签。你没有“呼叫”任何东西。
  • 对 -- cookies 是一个标签,但您的行为就像您期望它在此处采用 JSON 样式表示法一样。你在一个函数的中间。 cookies 应该怎么称呼?
  • 如果你想有条件地调用一些东西,然后将它包装在一个条件中,就像你已经在你的标记代码块之后完成了代码一样。

标签: javascript node.js


【解决方案1】:

我认为下面的代码给出了您正在寻找的行为,但它非常反模式。这有点像看起来的面向对象,但实际上并非如此,因为它在每次调用包含函数时都以相同的方式定义cookies 函数。您可能希望 cookies 继续使用 cmd,但这不是您的问题。

我认为你最终会慢慢地做一些真正的面向对象的东西,你会have a constructor set up all the properties for your functions within functions。也就是说,您需要保留 JSON 表示法,并将其作为“真实代码”运行在对象构造函数中,返回 cmd 的实例,您可能会以不同的方式进行初始化(可能使用 JSON 表示法!)。

如果这不是您想要的,请发表评论,我会修改。同样,我实际上不会在生产中使用此代码。反模式。

var cmd = {
    help: function () {
        var context = this.help;
        context.cookies = function () {
            console.log('Cookies recipe');
        };

        if (arguments.length === 0) {
            console.log('General help text');
        } else if (context.hasOwnProperty(arguments[0])) {
            context[arguments[0]]();
        } else {
            console.log('Requested topic not found');
        }
    },

    invite: function(id) {
        //send_PRIVGRP_INVITE(id);
        console.log("send_PRIVGRP_INVITE(" + id + ");");
    }
};

cmd.help();
cmd.help("cookies");
cmd.help("milk");
cmd.invite("wack");
cmd.help("invite");

这将产生这个输出:

General help text
Cookies recipe
Requested topic not found
send_PRIVGRP_INVITE(wack);
Requested topic not found

编辑:这里有一些关于如何使用this 的好信息:

快速带回家的是this 引用函数的执行上下文,如the SO answer quotes...

ECMAScript 标准将其定义为“评估 当前执行上下文的 ThisBinding 的值" (§11.1.1)。

因此,如果您没有将任何东西附加到对象,window(或任何您的全局上下文;在浏览器中,它是window)是this。除非您使用严格模式...否则this 是调用对象。例如,当调用 bar 时,foo.bar() 应该在 this 中包含 foo

您可以使用函数callapply 在调用函数时显式设置this 中的上下文。但这一切都在这些链接中进行了详细解释。

一个面向对象的解决方案

对于如何使用 OO,我可能会做类似...

function Cmd(helpInfo, executableFunctions) {
    var functionName;

    // Note that we're no longer redefining the cookies function
    // with every call of cmd.help, for instance.
    this.help = function (helpTopic) {
        if (undefined === helpTopic) {
            console.log('General help text');
        } else if (helpInfo.hasOwnProperty(helpTopic)) {
            console.log(helpInfo[helpTopic]);
        } else {
            console.log('Requested topic not found');
        }
    };

    for (functionName in executableFunctions)
    {
        if (executableFunctions.hasOwnProperty(functionName))
        {
            this[functionName] = executableFunctions[functionName];
        }
    }
}

// Set up initialization info for your new command object.
var helpInfoCooking = {
    cookies: "Cookies recipe",
    brownies: "Brownies recipe",
    cake: "Cake receipe"
};

var executableFunctions = {
    invite: function(id) {
        //send_PRIVGRP_INVITE(id);
        console.log("send_PRIVGRP_INVITE(" + id + ");");
    },
    say: function(message) {
        console.log("you'd probably say \"" + message + "\" somehow");
    }
};

// Create an instance of Cmd.
var cmd = new Cmd(helpInfoCooking, executableFunctions);

cmd.help();
cmd.help("cookies");
cmd.help("milk");
cmd.help("cake");
cmd.invite("wack");
cmd.help("invite");

cmd.say("This is a message");

结果:

General help text
Cookies recipe
Requested topic not found
Cake receipe
send_PRIVGRP_INVITE(wack);
Requested topic not found
you'd probably say "This is a message" somehow

YMMV 等。如果您正在执行单例设置,可能会有些矫枉过正,但重新安排成真正的单例设置也不难。

【讨论】:

  • 据我所知,有一个小问题'this'指的是 Cmd 而不是我想的帮助功能,如果使用现有方法的参数调用它,它会使帮助命令出现故障就像'邀请。在调用帮助邀请而不是回复“未找到请求的主题”时,它实际上是在调用邀请()。
  • 对不起,那是愚蠢的。固定的。虽然我真的认为你会想要为这个用例使用真正的 OO 设置(甚至是an abbreviated one)。稍后我会尝试提出一些建议。那么this 和关闭问题会更有意义。
  • 是的,这行得通,我只是假设“this”将始终指代它包含在非主对象中的任何块。当您说真正的面向对象时,您的意思是我应该做类似的事情: var Cmd = new Object(); Cmd.invite = function(id) { send_PRIVGRP_INVITE(id) } 而不是直接在 cmd 对象中写入所有“命令”?
  • 好的,很快就尝试解决this 问题(全是关于“执行上下文”),并且快速使用 OO 进行此操作。
  • 所以让我看看我是否明白你在这里做了什么,你创建了 2 个对象,1 个包含帮助文件,而另一个包含可执行函数,你创建了一个名为 Cmd 的对象构造函数,最多需要 2 个arguments 并且它有一个名为 help 的方法,它接受 1 个可选参数,即主题名称。如果可选参数被传递给它,那么它会检查第一个参数是否传递给 Cmd,例如 foo 有一个名为任何 helpTopic 变量包含的属性,如 foo.hasOwnProperty(bar) 并将帮助信息打印到控制台。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-10
  • 1970-01-01
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多