/    Sign up×
Community /Pin to ProfileBookmark

Another dumb question about scope

Hi there,

Sorry for the dumb question, I’ve been googling all over and I can’t find an answer to ths.

I notice that if I do this:

[CODE]
var fnc = function() {
var a = 10;
fnc.b = 10;
}
fnc.c = 4
alert(fnc.a);
alert(fnc.b);
alert(fnc.c);[/CODE]

the first two alerts show undefined and the third shows 4. Presumably c is defined as an attribute of fnc. My question is, why are a and b not attributes of fnc.

Sorry again for the dumb question ๐Ÿ˜ฎ

to post a comment
JavaScript

21 Comments(s) โ†ด

Copy linkTweet thisAlerts:
@goldfidgetauthorApr 04.2011 โ€”ย Also, is there a way to declare a such that it is accessible from fnc.a?
Copy linkTweet thisAlerts:
@skinicodApr 04.2011 โ€”ย hi,

You have effectively declared a variable "a" and an associative array "fnc.b", which are both local to a function. You never return anything from that function and you are not trying to populate already declared (and therefore global variables) - hence when you try to call on these they are null. You then globally set an associative array "fnc.c", which is why this is the only one that gives output when you run your alerts.

If you had declared the associations fnc.a, fnc.b and fnc.c before your function call, then you could indeed set them within the function.

hope that makes sense,

skinicod.
Copy linkTweet thisAlerts:
@goldfidgetauthorApr 04.2011 โ€”ย Thanks skinicod,

As far as I can see though, fnc is and remains a variable of type function. If I do:

[CODE]
var fnc = function() {
}
fnc.c = 4
alert(fnc)
alert(fnc.c);
[/CODE]


the function literal is displayed. When I set fnc.c I think I'm setting it on the function itself. My question is then, is there a way from within the function literal to access fnc.c? Surely functions can access their own members?
Copy linkTweet thisAlerts:
@skinicodApr 04.2011 โ€”ย Hi goldfidget,

I'm not really sure why you're trying to do what your doing, but I think the reason you are not being able to set fnc.c was returning null, is that you have only ever defined the function literal and not actually called it.

If you call it, it will set correctly, and be useable outside the function e.g.

[CODE]
var fnc = function fnc() {
fnc.c = 5;
}

fnc();

alert(fnc)
alert(fnc.c);
[/CODE]


Does this help?

Cheers,

Skinicod
Copy linkTweet thisAlerts:
@KorApr 04.2011 โ€”ย You confound functions with objects. A function can be used to create an object (or can be handled as an object), but an object is not a function. An object have members. A function has no literal members, or better say, the declarations, expressions, variables, etc defined inside a function are not members of that function , even if treated as an object.

If you want to access literally the members of an object, either you should write literally that object
<i>
</i>var fnc = {
a:10,
b:10
}
fnc.c = 4;

Or you may use another function as a constructor
<i>
</i>var Constructor = function(a,b,c){
this.a=a;
this.b=b;
this.c=c;
}
fnc = new Constructor(10,10,4);


A function is, in fact an object generated by the[B] Function()[/B] native constructor.

And something else. In you code you have used a [I]function expression[/I]:
<i>
</i>var fnc = function(){
}

That does nothing but to assign an anonymous function to a variable.

A function can be invoked [I]from inside[/I], if this is what you are looking for, using the combination of the function's properties [B]arguments [/B]and [B]callee[/B]
<i>
</i>var fnc = function(){
alert(arguments.callee.c);
}
fnc.c=4;
fnc();


More about functions (and Function) scope:

https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope
Copy linkTweet thisAlerts:
@goldfidgetauthorApr 04.2011 โ€”ย Thanks Kor,

My assumption, coming from Ruby, was that functions are a type of object.

[CODE]var str = "Hello";
str.a = "Hi There";
alert(str.a);
// => undefined[/CODE]


[CODE]var fnc = function() {}
fnc.a = "Hi There";
alert(fnc.a);
// => "Hi There"[/CODE]


Do I take it then that in Javascript, only objects are object. Strings are not objects, functions are not objects, etc?

If so, then why the different behaviour for the two examples above?

Thanks ?
Copy linkTweet thisAlerts:
@skinicodApr 04.2011 โ€”ย Hi goldfidget,

This is my third attempt to reply to you, but unfortunately my replies are going into ether..

Anyway - you can give a function literal members (though I'm not entirely sure why you would). The only reason you haven't been having success, is that you haven't actually called the function - you've only set it. if you call add 'fnc();' after you declare the literal, any member declarations within it will be processed.

Cheers,

skinicod.
Copy linkTweet thisAlerts:
@KorApr 04.2011 โ€”ย Everything is or can be treated as an object in JavaScript. But not everything is an [B]Object[/B]. ? What I wanted to emphasize is that [I]the expressions[/I] written literal inside a function [I]are not members of the function[/I].

In JavaScript the strings are primitives, and derive from the native String object/method. But you can set them as Objects, by using straight the [I]source[/I] of their derivation (the String() method):
<i>
</i>var str = new String("Hello")
str.a="Hi There"
alert(str.a)


It is the same as we saw in declaring the functions.
<i>
</i>var str="Hello"; [COLOR="Blue"]// this is an expression, the result is a primitive String[/COLOR]
var str = new String("Hello"); [COLOR="Blue"]// this is a construction, the result is an object String[/COLOR]


Coming back to the primitives: if you want to add custom members to a primitive, you can do it by alter its [B]prototype[/B].
<i>
</i>String.prototype.a="Hi There";
var str = "Hello";
alert(str.a);

But that method (extended prototype) will add a member [I]to all the strings[/I] declared on the document.
Copy linkTweet thisAlerts:
@KorApr 04.2011 โ€”ย 
Anyway - you can give a function literal members (though I'm not entirely sure why you would). The only reason you haven't been having success, is that you haven't actually called the function - you've only set it. if you call add 'fnc();' after you declare the literal, any member declarations within it will be processed.[/QUOTE]

Yes and no. It will work in this case:
<i>
</i>var fnc=function(){
fnc.a=10
}
fnc();
alert(fnc.a)

But that would be the long equivalent of:
<i>
</i>var fnc=function(){
}
fnc.a=10
alert(fnc.a)

Which does not change the essence of the [I]function expression[/I].
Copy linkTweet thisAlerts:
@goldfidgetauthorApr 04.2011 โ€”ย Ah, that's interesting, the String constructor wraps a string primitive in an object.

The primitive still has methods though, I can do this:

[CODE]alert("Hello".charAt(2));
=> l[/CODE]
Copy linkTweet thisAlerts:
@goldfidgetauthorApr 04.2011 โ€”ย Ah I see, that makes sense. The code is not evaluated until the function is run, so until I call fnc(), fnc.c does not exist...

Hi goldfidget,

I'm not really sure why you're trying to do what your doing, but I think the reason you are not being able to set fnc.c was returning null, is that you have only ever defined the function literal and not actually called it.

If you call it, it will set correctly, and be useable outside the function e.g.

[CODE]
var fnc = function fnc() {
fnc.c = 5;
}

fnc();

alert(fnc)
alert(fnc.c);
[/CODE]


Does this help?

Cheers,

Skinicod[/QUOTE]
Copy linkTweet thisAlerts:
@KorApr 04.2011 โ€”ย 
The primitive still has methods though
[/quote]

Yes. Some JavaScript primitives have their native properties and their methods. But JavaScript makes a difference between native properties/methods and custom properties/methods in case of Primitives (and not only primitives, and not all the Primitives).

One says that "JavaScript primitive values, Booleans, numbers, and strings, are [I]pseudo-objects[/I]". They have native properties and methods, but they can not individually gain custom properties/methods. They may gain only "collective" native properties/methods, by altering the [B]prototype[/B] of their source of derivation (their "wrapper") - ex [B]String[/B] for strings, [B]Number[/B] for numbers, [B]Boolean[/B] for booleans.

The other two primitive groups in javascript (after string, number and boolean) are [B]null[/B] and [B]undefined[/B]. Interesting enough, [B]null[/B] is an object, but it has no properties/methods (it is a sort of anti-object = an object which "measures" the existence, or better say, the non-existence of an object), while undefined it is not an object at all, it is a pure primitive value.
Copy linkTweet thisAlerts:
@goldfidgetauthorApr 04.2011 โ€”ย 
More about functions (and Function) scope:

https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope[/QUOTE]


Ah, sorry, I missed your link. Functions are objects, string literals are not. ?
Copy linkTweet thisAlerts:
@KorApr 04.2011 โ€”ย Let's put all these together in a brief:

Literal strings, numbers and booleans are primitives. That means they are not objects stricto sensu. But they derived from their correspondent native wrappers: [B]String[/B], [B]Number[/B] and [B]Boolean[/B], which [I]are[/I] objects, with native properties and methods. Therefor, they inherit those properties/methods through their wrapper's [B]prototype[/B]. To be more precise it is a [I]delegation[/I], not an inheritance.

But if the wrapper is invoked as a constructor (ex: var mystring= new String()), the variable becomes the [I]reference of a plain object[/I], thus it can gain later individual members, same as any other Object.

Sounds more clear, now? ?
Copy linkTweet thisAlerts:
@KorApr 04.2011 โ€”ย Despite primitives, [I]functions are objects[/I]. But their content is not a member of that object. Their content is a piece of code, a sub-routine which has to be run whenever the function is called.
Copy linkTweet thisAlerts:
@goldfidgetauthorApr 04.2011 โ€”ย Despite primitives, [I]functions are objects[/I]. But their content is not a member of that object. Their content is a piece of code, a sub-routine which has to be run whenever the function is called.[/QUOTE]

Ahhhh, ahhhh, yes wonderful ?
Copy linkTweet thisAlerts:
@goldfidgetauthorApr 04.2011 โ€”ย So, given the above, is there a way for a function to refer to itself outside of a constructor without necessarily knowing its own name?
Copy linkTweet thisAlerts:
@KorApr 04.2011 โ€”ย So, given the above, is there a way for a function to refer to itself outside of a constructor without necessarily knowing its own name?[/QUOTE]
Yes, I have already mentioned that:
<i>
</i>function fnc(){
var thisFunction=[COLOR="Blue"]arguments.callee[/COLOR];
alert(thisFunction)
}
fnc();

There is a small confusion about the fact that [B]arguments.callee[/B] is or not deprecated. Well, Mozilla stipulates clearly, I think:

"JavaScript 1.4: deprecated arguments, arguments.callee, and arguments.length [I]as properties of Function instances[/I]; [COLOR="Blue"][B]retained[/B] arguments as a local variable of a function and arguments.callee and arguments.length as properties of this variable[/COLOR].
Copy linkTweet thisAlerts:
@goldfidgetauthorApr 05.2011 โ€”ย Thank you both, that was very helpful ?
Copy linkTweet thisAlerts:
@rnd_meApr 06.2011 โ€”ย 
There is a small confusion about the fact that [B]arguments.callee[/B] is or not deprecated. Well, Mozilla stipulates clearly, I think:

"JavaScript 1.4: deprecated arguments, arguments.callee, and arguments.length [I]as properties of Function instances[/I]; [COLOR="Blue"][B]retained[/B] arguments as a local variable of a function and arguments.callee and arguments.length as properties of this variable[/COLOR].[/QUOTE]


the "variable" arguments.callee and the fn.arguments "property" are both removed in ECMA5 strict.

http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/


It's a good idea to name all your functions anyways, so this isn't that big of a deal.

but i will miss argument.callee. nobody seems to talk about it, but as of now, you can even get the caller property:
[CODE]
function one(){
return two();
}

function two(){
return "two says: " + arguments.callee.caller.toString();
}


alert( one() ) [/CODE]

if it's undefined, guess where the function was called from?



ecma5 cleans up a lot of this mess, along with inconsistencies resulting from code like "var arguments" or "return arguments".

i encourage everyone to read the spec, and not just the new parts.

you will find a lot of familiar routines have the same name, but different and more specific steps.
ร—

Success!

Help @goldfidget spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 โ€” BETA 5.28,
whats_new: community page,
up_next: more Davinciโ€ข003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinciโ€ข003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...