How JavaScript assigns `name` attribute of function? - javascript

In JavaScript, when I define function like this
function aaa(){}
I can later access the name by name attribute:
aaa.name
which will return
"aaa"
However, when I define function via var, it technically should be anonymous function without name attribute:
var aaa=function(){}
But instead it assumes that aaa is function name and assigns it to name attribute:
aaa.name
will also return
"aaa"
How JavaScript decides what should be the name, especially considering the fact that assignments could use more complicated scenarios:
var aaa=bbb=function(){}
or
var aaa=arr[0]=function(){}
?

Javascript declares the name variable of the function by taking the left-hand side argument that is equal to the function, which is 'aaa' in all basic cases. In the first complex definition, you declared state above Javascript will take the variable ab and assign it to a function making the name 'ab'. In the final example, you provided it sets the function equal to a pointer in memory, which is not a defined variable, this sets the name property to an empty string because arr[0] is not a variable name but a pointer to memory.
Here is a JSFiddle displaying this.

Something like this:
Inferred function names
Variables and methods can infer the name of an anonymous function from
its syntactic position (new in ECMAScript 2015).
var f = function() {};
var object = {
someMethod: function() {}
};
console.log(f.name); // "f"
console.log(object.someMethod.name); // "someMethod"
Read the entire blog. It will clear all your queries.

Related

typeof name returns string even though number was assigned

This is really tearing apart my JS concept. What's wrong at all here?
const NAME = 'chusss';
var name = 123;
console.log(typeof name); // string, wasnt it supposed to print number?
console.log(name); // 123
The name variable actually belongs to window.name which lets you set the name of the window.
From MDN
The name of the window is used primarily for setting targets for
hyperlinks and forms.
Further down it's written:
Don't set the value to something unstring since its get method will
call the toString method.
Thus you always get a string returned.
If you still want to use the name variable but dont want to have the collision with window.name, then wrap your code inside a immediate invoked function expression (IIFE) and benefit from the functional scope.
Demo
(function() {
var name = 123;
console.log(typeof name);
console.log(name);
})();
If you run this code in node.js you won't observe that behaviour as name is not a property of the global object and thus not defined in global scope.

Get object reference, and function name

How can i retrieve the reference to object containing a function from an input in the form objectReference["functionName"].
Example:
function aaa(param) {
var objectReference = /*..???...*/;
var functionName = /*...???..*/;
// Now expected result is that objectReference contains
// a reference to myObject, and functionName contains a
// string with name of function (implemented in myObject),
// so I can invoke it with objectReference[functionName]()
// after some manipulation.
}
var myObject = new SomeFunction();
aaa(myObject["myFunction"]);
Thank you
You can't do either of the things you've listed. There are two separate things here:
Getting the myObject value
Getting the name of the property that that object uses to refer to the function
The value passed into aaa in your code is just a reference to the function. The reference to the object is not passed into aaa, nor is any information about what property the object used to refer to the function. Neither can be inferred or derived from the function reference itself. (The function may have a name, which could on modern JavaScript engines be access via its name property, but that may well be different from the name of the property that the object used to refer to it.)
In order to do this, you have to pass them separately, either as discrete arguments:
aaa(myObject, "myFunction");
or as an object
aaa({obj: myObject, prop: "myFunction"});
In the latter case, aaa might look like
function aaa(info) {
// Use info.obj and info.prop here
// The call would be
info.obj[info.prop]();
}
Another option, if you don't really need the object reference except for the purposes of making the call, is to use Function#bind:
aaa(myObject["myFunction"].bind(myObject));
aaa will receive a function reference that, when called, will call the original function with this referring to myObject. So aaa can't actually get the object reference, but it can still make the call.

Variable vs Parameter Scope and Assignment Values

I have been watching a video series by Douglas Crockford. I am a little confused on the relationship of assigning variables as a parameter of assigning variables as a global variable, let me demonstrate.
var bob = 22; //global scope
function funky(parameter){
parameter = null; //sets the var passed in to null
bob = 44; //sets the bob
}
var hello = [];
funky(hello); // hello still has the value of an empty array even after the function is invoked.
bob; // value is 44
So 'var bob' is assigned 44 when funky() is invoked. This bob holds the new value outside the scope of the function.
var hello is passed as a parameter, while inside funky, it has the value null, outside when hello is invoked in global space, it holds the value of an empty array.
Is this just something I have to memorize? If a defined variable in global scope is passed as a parameter, it will only hold it's new assigned value within the scope of the function? Am I missing something at a broader scope with either how a parameter is passed and assigned in a function?
Here is a repl.it of the code with console.log outputs while inside and outside the function/global scope.
http://repl.it/NgN
Because this line
parameter = null;
Only sets the value of the function's parameter, not the value of the variable that was passed in. However, bob inside the function is interpretted as a reference to the global variable, so it does modify the external value.
Note, however, that objects are references, so if you wrote it like this:
function funky(parameter){
parameter.hello = null;
}
Then calling funky does directly modify the object that the parameter references.
var x = { hello: [] };
funky(x); // x => { hello: null }
Is this just something I have to memorize?
Yes, understanding how parameters are passed is pretty important.
If a defined variable in global scope is passed as a parameter, it will only hold it's new assigned value within the scope of the function?
Parameters only hold their values within the scope of the function. Global variables are, well, global, so if they are modified inside the function, they keep that value outside the function.
Also, be aware of hiding—if a parameter has the same name as a global variable, the parameter hides the variable within the scope of that function.
ok, so the following example will confuse you even more.
var a = {'a': 'A'};
function foo(param){param.a = 'B';}
foo(a);
// now print a
{'a': 'B'}
Here's an important concept:
Primitives are passed by value, Objects are passed by "copy of a reference".
As for more information, you can check this answer:
Does Javascript pass by reference?
Regarding this:
var hello is passed as a parameter, while inside funky, it has the value null, outside when hello is invoked in global space, it holds the value of an empty array.
Do not think of parameter as an alias for hello. They are distinct variables. They are free to point to different things. Assigning a value -- null in this case -- to parameter has no effect on hello. After that line, the global variable hello still points to an empty array. Only parameter points to null.
Furthermore, funky(hello) passes the value of hello to the funky function. Consider the following:
var arr = [];
function addElements(arr) {
arr.push(5);
arr.push(77);
}
The global arr is still empty after addElements executes. The arr inside the function is distinct from the arr in the global scope. (I should note that the contents of each arr may point to the same objects, but that's a separate issue.)
(Note also that some languages do allow the sort of aliasing you seem to expect, but that's not how parameters are passed in JavaScript.)
JavaScript assumes that if you assign a value to a variable it is in the global scope—unless that variable is declared with a var. Like for example, this:
var bob = 22; //global scope
function funky(parameter){
parameter = null; //sets the var passed in to null
var bob = 44; //sets the bob
}
var hello = [];
funky(hello); // hello still has the value of an empty array even after the function is invoked.
bob; // value is 22
Since the function's bob variable is declared with a var, it is owned by the local scope of the function and has no impact on the bob declared outside the function's scope.
Regarding how objects differ from primitives when passed into functions, check out Jonathan Snook's article http://snook.ca/archives/javascript/javascript_pass and the helpful comment from #p.s.w.g.

What is the different between a parameter and a local variable?

Apologies for what must seem like a very stupid question.
I'm currently working through codecadamy, and this is throwing me off:
var greeting = function(name) {
name = "sausage";
console.log(name);
};
greeting(name);
I understand that I will get sausage
Why don't I just write var name = "sausage";? What is the difference?
The name in function(name) is a parameter. That is, it is used to pass data into the function. But, parameters are local variables. Assigning a value to name inside the function is a little strange though. I would assume you want to do something like this:
var greeting = function(name) {
console.log(name);
};
greeting("sausage");
In this version of the code you are passing the value "sausage" into the function via the parameter name. This is useful because you can call the function many times and each time the function may print a different value depending on what you pass.
In your function definition:
function(name) {
name is already being declared. It is a parameter for the function. If you want to change name, you can, but you don't need to use var to declare it as a new variable.
On the other hand, if you wanted to add, say, flavor, you should use var then since it is not already defined.
var flavor = 'savory';
In this case, flavor is a local variable and name is a parameter. A parameter is a type of local variable that is declared with the function declaration, but a local variable isn't necessarily a parameter because it may be declared elsewhere in the function.
Parameters are a general programming construct and are necessary to do anything sane in the world programming (dealing with masses of global variables is not sane.
var name would declare a new variable in the function scope that would override the value of the parameter name, so you would not be able to use the parameter anymore.
The CodeAcadamy example is a bit strange because it's rare that you want to override a parameter's value -- especially before you have used it.
Technically, there is no real difference.
Without giving you the huge background here, you have to understand that in the underlaying implementation, a special object (not a javascript object, on C/C++ level) is formed which is called Activation Object (ES3) or Lexical Environment Record (ES5).
However, this hash / object structure is used to store
variables declared by var
formal parameters
function declarations
As you can see, both var variables and parameters are stored in this structure.
This construct is most likely used to have somewhat default values for not passed in arguments. In a real world example, this would probably look more like
var greeting = function( name ) {
name = name || 'default';
console.log( name );
};
greeting('john'); // 'john'
greeting(); // 'default'

Javascript ~ Calling a function inside a Variable

I have a variable that is the functions name. I want to be able to call on that function from the variable.
var CircuitBox= document.getElementById("QLCS")
var CircuitNumber = CircuitBox.selectedIndex;
var circuit = CircuitBox.options[CircuitNumber].value;
// This Variable takes on the functions name that id like to call
circuit;
Cheers!
In JavaScript object properties can be accessed via there name as a string by using bracket notation, eg:
var propertyVal = myObj["propertyName"];
And since globally scoped members are actually properties of the Global object, you can get the properties from the window object (which is a reference to the Global object). So, if your drop down list contains values that map to function names in the global scope, you can call that function like this:
window[circuit]();
I can think of two ways.
You can try window[circuit]() if it is a global function. The other option is to use eval, but eval is evil. So to avoid the evilness of eval, a better way might be to maintain a map of handlers:
var handlers = {
someValue: function() {
...
},
otherValue: function() {
...
}
};
In this map, you're associating someValue and otherValue with anonymous functions. So assuming that your select box contains the options someValue and otherValue, the appropriate function will be called based on what they select.
Then all you have to do is handlers[circuit]().

Categories