开发者

Is there anything bad about attaching a variable to a function in Javascript?

开发者 https://www.devze.com 2023-01-09 08:23 出处:网络
I\'m writing some Javascript code and I need to keep track of a global state. The state is only ever changed by a single function, but it needs to be widely accessible from other functions.

I'm writing some Javascript code and I need to keep track of a global state. The state is only ever changed by a single function, but it needs to be widely accessible from other functions.

I'm currently doing it in this manner:


function foo(bar) {
    var self = arguments.callee;
    if (!self.state) {
        self.state = 0; // 开发者_高级运维called 0 times
    } else {
        self.state++; // increase the number of times i've been called
    }
}

Is it sensible to bind the global state variable to the function like this? It's nifty but I'm worried that there's something dangerous that I've missed.


There's nothing wrong with assigning properties to function objects. What you should worry about is that arguments.callee is deprecated in ECMAScript 5, which is the most recent language specification that's currently making its way into the mainstream browsers. In strict mode, referring to arguments.callee will give an error.


It's fine. People do it all the time with constructor functions. A built-in example would be String.fromCharCode

If however other functions don't need to reference the state, I would prefer doing the following:

var foo = (function () {
  var state = 0;
  return function (bar) {
    state++;
  };
}) ();

Even if they do need to reference it, I would probably try to make the above code work in some way. Or even use objects and avoid the singleton-like usage.


I've done things like this before. I think it is slightly messy, but it won't cause World War III.

Instead of doing this, could you define that function inside a closure, and have the 'state' variable local to that closure?

var foo = (function() {
  var state = 0;
  return function(bar) {
    state++;
  };
}());

foo(bar);


It's fine, except that your state variable will never be > 0. Try this instead:

function foo(bar) {
    var self = arguments.callee;
    if (!self.state) { // Or, as trinithis suggested: if (self.state === undefined) {
        self.state = 1; // called once
    } else {
        self.state++; // increase the number of times i've been called
    }
}


Rather than a public field, you could make the counter read-only. Assuming you want to count calls to multiple functions, you could even define a utility method to wrap functions with this behaviour:

function countCallsToFunc(func) {
  var count = 0;
  var self = function() {
    count++;
    func.apply(this, arguments);
  };
  self.getCount = function() {
    return count;
  };
  return self;
}

var foo = countCallsToFunc(function(bar) {
  // do something
});

foo();
foo();
alert(foo.getCount());
0

精彩评论

暂无评论...
验证码 换一张
取 消