7

我有一些函数,存储在集合/数组中,并且想在不重新输入的情况下获取密钥(函数名)。有什么捷径可以访问吗?

var functions_collection = {
    "function_x": function() {
        var name = "function_x";
        // name = this.key; <- how to get the key/function-name "function_x"?

        // some more code like:
        $(".function_x .button").val();

        alert(name);
    }
}

编辑:我想避免在函数本身内重新键入“function_x”,而是更喜欢像 this.key 一样调用它。

抱歉这个奇怪的话题,提前谢谢!

解决方案:很多很好的答案,但我只是在寻找这个剪断:

Object.keys(this)
4

5 回答 5

4

我不确定这是你想要的,但你可以这样做:

    var functions_collection = {};
    (function(name){
       functions_collection[name] = function(){
           // use name, which is the function
           alert(name);
       };
    })("function_x");

我不确定它是否更好。但根据您的(未指定)目标,可能会有更好的解决方案。

于 2013-06-04T18:43:00.477 回答
3

在我看来,您需要更改上面的代码,因为您有没有名称的匿名函数- 这样的更改应该有效:

var functions_collection = {
  'function_x' : function function_x () {
    var myName = arguments.callee.name;
    alert(myName);
  }
}

http://jsfiddle.net/9cN5q/1/

于 2013-06-04T18:40:51.610 回答
3

要获取对象键的名称,您可以Object.getOwnPropertyNames(this)在较新的浏览器中使用 或,这将为您提供对象具有Object.keys(this)的所有键和任何键的数组:this

var functions_collection = {
    function_x: function() {
        var name = Object.keys(this);
        console.log(name);
    }
}

小提琴

于 2013-06-04T19:13:27.287 回答
3

有几种方法可以去这里。有些是好主意,有些则不是。

一、一些不好的想法

  1. 馊主意:arguments.callee.name

    这最直接地转化为您的要求。arguments.callee是对您当前使用的函数的引用。但是,这被认为是不好的做法, 除非您有充分的理由,否则您应该避免使用它。

  2. 坏主意:咖喱

    构造函数后,将自己的名称作为参数绑定到其中:

    var functions_collection = {
        "function_x": function(name) {
            alert(name);
        },
        //more functions
    };
    for (var name in functions_collection) {
        if (typeof functions_collection[name] === "function") {
            functions_collection[name] = 
                functions_collection[name].bind(functions_collection, name);
        }
    }
    

    柯里化对 JavaScript 中的很多东西都很有用,在很多情况下它都是一个好主意。不过,不在这里,我将在下面解释原因。

  3. 坏主意:使用本地参数并遍历包含对象

    var functions_collection = {
         "function_x": function(name) {
             alert(name);
         },
         //more functions
    };
    for (var name in functions_collection) {
        if (typeof functions_collection[name] === "function") {
            functions_collection[name](name);
        }
    }
    

    当然,这个明显的问题是您可能不想一次调用集合中的每个函数。更根本的问题是它延续了危险的紧耦合趋势。这是一件坏事,可能是一件非常糟糕的事情,这会让你感到头疼。

现在是“正确”的方式

改变你的整个方法。忘记尝试从 HTML 中回收类名;保持简单。

  1. 好主意:使用局部变量

    谁在乎你给你的函数起什么名字?如果您知道希望它们接触哪些 HTML 类,只需按这种方式编写代码即可。

    var functions_collection = {
        "function_x": function() {
             var name = "function_x"; //or "button" or any other class name
             alert(name);
         },
         //more functions
    };
    functions_collection.function_x();
    
  2. 好主意:传递一个参数

    你已经在调用这个函数了,对吧?因此,可能已经有代码可以访问您想要的名称。

    var functions_collection = {
        "function_x": function(name) {
             alert(name);
         },
         //more functions
    };
    
    functions_collection.function_x("function_x"); //or any other class name
    

    现在您可以function_x在 HTML 中的任何类上使用,即使它与函数名称不匹配:

    functions_collection.function_x("function_y");
    functions_collection.function_x("class_z");
    functions_collection.function_x("button");
    

    我把最简单的留到最后,因为我认为你试图变得“聪明”是个错误,如果这是有道理的话。您的方法存在重大风险,而且回报不值得。

为什么坏主意是坏的,好主意是好的

除了arguments.callee.name选项之外,在这种情况下,原因 2 和 3 不好是紧耦合。你正在耦合function_x到 ; 的结构functions_collection。您将行为耦合到变量名;最糟糕的是,您将 JS 变量耦合到 HTML 元素的类名。这会让你的代码变得非常脆弱,当你想要改变一些东西时(你会的),准备好迎接一个充满伤害的世界。

例如,如果您重新组织 HTML 会发生什么?该页面可能会中断,因为您的 JS 的结构必须与 HTML/CSS 中的类匹配。您将不得不重命名或重写functions_collection以及所有其他人都喜欢它,否则您将不得不围绕已有的 JS 仔细规划新的 HTML。

如果你想使用 JS 缩小器会发生什么?取决于,但如果你允许它更改对象文字中的成员名称,它会完全破坏一切,你必须从一个“好”的想法重新开始。

现在,你得到什么来换取这种僵化?您在每个函数的开头保存一个额外的行。不值得,恕我直言。咬紧牙关,保持简单。

于 2013-06-04T19:55:57.103 回答
2

假设变量名与其包含函数同名:

var keys = [];
for (var p in functions_collection) {
    if (typeof(functions_collection[p]) == 'function') {
        keys.push(p);
    }
}

你有它,一个包含所有函数名称的数组。

于 2013-06-04T18:43:29.780 回答