Is it legal javascript (ECMAScript) for a function to reference its attributes?

63 views Asked by At

Is it legal javascript (ECMAScript-5) for a function to reference its attributes?

var baz = function(callback) {
  return callback();
};

var foo = function() {
  return foo.bar;
}

foo.bar = 1;

foo(); // 1?

baz(foo);  // 1?

Edit: can you refer me to the part of the ECMA specification that declares this is legal?

4

There are 4 answers

0
ssube On BEST ANSWER

Yes.

Folks often run into a problem with this when using objects, which are evaluated during initialization and don't exist while attempting to reference their properties. This is not a problem with functions, since the property isn't accessed until the function is invoked later.

For example:

let foo = {
  bar: 1,
  baz: foo.bar + 1
};

fails because the object has not been assigned to foo yet, so foo.bar is undefined.

With functions this is not a problem, since foo is a reference to the function and bar would not be accessed until the function is invoked:

function foo() {
  return foo.bar + 1;
}

foo.bar = 1;
0
Benjamin Gruenbaum On

Yes, a function is an object, objects have properties and they may access their properties.

Remember that in JS functions are first class citizens, they can have their own properties. Also remember that property evaluation happens when the function is called and not when it is created so the property can be added later.

You can see this here:

var foo = function() {
  return foo.bar;
}

foo.bar = 1;

alert(foo()); // 1?

0
Marcus On

You could use a nicer pattern, like this:

var baz = function() {
  var myVal = 0;
  return function() {
    //body
  }
}()

That way you have a sort of memo variable inside closure that will keep values for you

3
Mark Reed On

Functions are objects, so sure, they can have properties and access them. Just be aware that the body of a function has no magical access to those properties.

Note that code like this requires the body of the function to know its name:

function foo() {
   return foo.bar;
}

.. but you can take advantage of the arguments property to remove that redundancy/dependency:

function foo() {
  return arguments.callee.bar;
}
foo.bar = 1;
foo();  // 1