最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

arrays - Javascript: How to get the parent key inside a function? - Stack Overflow

programmeradmin7浏览0评论

I've some functions, stored in a collection/array and would like to get the key (function-name) without retyping it. Is there any short way to access it?

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);
    }
}

Edit: I'd like to avoid retyping the "function_x" inside the function itself and prefer to call it like this.key.

Sorry for the weird topic and thanks in advance!

Solution: A lot of good answers, but I was just looking for this snipped:

Object.keys(this)

I've some functions, stored in a collection/array and would like to get the key (function-name) without retyping it. Is there any short way to access it?

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);
    }
}

Edit: I'd like to avoid retyping the "function_x" inside the function itself and prefer to call it like this.key.

Sorry for the weird topic and thanks in advance!

Solution: A lot of good answers, but I was just looking for this snipped:

Object.keys(this)
Share Improve this question edited Jun 6, 2013 at 7:49 Mr. B. asked Jun 4, 2013 at 18:36 Mr. B.Mr. B. 8,70716 gold badges74 silver badges119 bronze badges 6
  • can you give the use case, why you need this? – itz2k13 Commented Jun 4, 2013 at 18:39
  • @itz2k13 There are some CSS-classes named as the functions. Inside the function I need to use them like $(".function_x .button").html("123"); and would like to keep my code as clean as possible. – Mr. B. Commented Jun 4, 2013 at 18:43
  • 1 You can call var name = Object.keys(this) (or use getOwnPropertyNames) to get a list of the keys in the object. Won't get you just the parent key unless there is only one ? – adeneo Commented Jun 4, 2013 at 18:46
  • 1 Why don't you use your CSS-class name as a parameter for a function? – Artyom Neustroev Commented Jun 4, 2013 at 18:57
  • @adeneo your answer is all I need, I guess. Why did you just post a ment instead of an answer? – Mr. B. Commented Jun 4, 2013 at 18:57
 |  Show 1 more ment

5 Answers 5

Reset to default 4

I'm not sure it's what you want but you can do this :

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

I'm not really sure it's better. But depending on your (unspecified) goal, there's probably a better solution.

To get the name of the objects keys, you can use Object.getOwnPropertyNames(this) or in newer browsers just Object.keys(this), and that will get you an array of all and any keys the this object has :

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

FIDDLE

In my opinion you´d need to change you above code since you are having anonymous functions which have no name - a change like this should work:

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

see http://jsfiddle/9cN5q/1/

There are several ways you could go here. Some are good ideas, some are not.

First, some bad ideas

  1. Bad idea: arguments.callee.name

    This translates most directly to what you ask. arguments.callee is a reference to the function you're currently in. However, it's considered bad practice, and you should avoid using it unless you have a really good reason.

  2. Bad idea: Currying

    After constructing the function, bind its own name into it as a parameter:

    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);
        }
    }
    

    Currying is useful for lots of things in JavaScript, and it's a great idea in many situations. Not here, though, and I'll explain why below.

  3. Bad idea: Use a local parameter and iterate through the containing object

    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);
        }
    }
    

    Of course, the obvious problem with this one is that you might not want to call every function in the collection at once. The more fundamental problem is that it continues the trend of dangerously tight coupling. This is a bad thing, potentially a Very Bad Thing that will cost you all kinds of headaches down the line.

Now the "right" way

Change your whole approach. Forget trying to recycle class names from your HTML; just keep it simple.

  1. Good idea: Use a local variable

    Who cares what you name your functions? If you know which HTML classes you want them to touch, just code them that way.

    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. Good idea: Pass a parameter

    You're already calling the function, right? So there's probably already code somewhere with access to the name you want.

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

    Now you can use function_x on any class in your HTML, even if it doesn't match the function name:

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

    I've saved the simplest for last because I think you're making a mistake by trying to be "clever", if that makes sense. There are significant risks in your approach, and the payoff isn't going to be worth it.

Why the bad ideas are bad and the good ideas are good

Other than the arguments.callee.name option, the reason 2 and 3 are bad in this case is tight coupling. You're coupling function_x to the structure of functions_collection; you're coupling behavior to a variable name; and worst of all, you're coupling JS variables to the class names of HTML elements. This will make your code extremely fragile, and when you want to change something (and you will), get ready for a world of hurt.

For example, what happens if you reorganize your HTML? The page probably breaks, since the structure of your JS has to match the classes in your HTML/CSS. You'll have to rename or rewrite functions_collection and all others like it, or else you'll have to carefully plan new HTML around the JS you already have.

What happens if you want to use a JS minifier? Depends, but if you allow it to change member names in object literals, it pletely breaks everything and you have to start over with one of the "good" ideas.

Now, what do you get in exchange for this inflexibility? You save an extra line at the beginning of each function. Not worth it, IMHO. Just bite the bullet and keep it simple.

Supposing that the variable name has the same name as its containing function:

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

And there you have it, an array with all the function names.

发布评论

评论列表(0)

  1. 暂无评论