调用方法的方法(如果存在)

时间:2015-04-23 17:06:51

标签: javascript node.js

首先我应该指出我在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)
        }   

    }

任何想法如何使我的工作,或有更好的方法,更清洁的方式来做到这一点。另外我应该提到我选择使用命令作为对象和方法,因为一些命令会更复杂,我正计划将它们放在file.js上并将其导出到main.js文件中,这将更容易添加没有编辑主文件的命令。

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

1 个答案:

答案 0 :(得分: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是调用对象。例如,当foo.bar()被调用时,foo应该this bar

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

一个OO解决方案

关于如何使用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等。如果您正在进行单身人士设置,可能会有些过分,但重新排列成真正的单例设置并不难。