This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript Variable Variables
Please take a look at code below
var selected_id=1;
resetVar("selected");
function resetVar(foo){
foo+"_id"=0; // I want to set selected_id into 0
}
Is that possible? Any suggestion?
If your variables are global variables, then they are implicitly properties of the window object and you can reference them as properties of the window object like this:
function resetVar(foo){
window[foo + "_id"] = 0;
}
var selected_id = 1;
resetVar("selected");
If your variables are not global variables, then you will need to make them properties of some known object so that you can use this same technique.
In general, this is usually a bad programming idea and we often see this question where there are better ways to handle the situation. You don't disclose what the overall situation is so we can't advise very specifically, but you should usually be using properties on a known object directly or you should be using an array to hold several related values in the array or you should just be referencing the variable directly.
if selected is a global variable:
function resetVar(foo){
window[foo+"_id"] = 0;
}
You can invoke functions using square bracket notation on the object which owns the method (in your case, the global, window object).
window['selected_id'] = value
This is a "solution" often proposed by beginners (which is not a bad thing, everyone starts somewhere). The answer is; don't do that, use an array (or some other collection).
Using variable names to determine program logic is a terrible idea that will inevitably lead to messy, unmaintainable code. Changing the name of a varibale should not change your program's logic. Instead, group obbjects into a collection, using a key into the collection if needed, or simply the index.
Related
The concept of functions being objects in JavaScript would be ok with me if I could understand the following question. I have searched around and looked into the javascript engine to try and find the answer, but no explanation I've found so far sits well in my mind...
An object like the one below is understandably layed out in a hash map type of construct.
var person = {
firstName:"John",
lastName:"Doe",
age:50,
eyeColor:"blue"
};
However, to say this is also an object is where I get stuck:
var name = function () {
alert ('name');
}
In terms of memory, how is this function stored?
Are the statements inside the "hash map" of a function layed out in an execute order? So each property is called upon after the other?
I'm probably missing something or visualising something wrong.
Thanks.
P.S
To clear up question 2,
Say I have an if statement inside my function... will that be stored in a property accessible through one of its properties?
Every object in javascript has properties (key-value pairs identified by strings or symbols) and it has internal slots.
The function object name is stored in the same format as the person object, but their internal slots differ.
person's properties are firstName, lastName, age and eyeColor, each holding the respective primitive value
person's internal slots are (amongst others):
[[prototype]], pointing to Object.prototype
name's properties are name, prototype and length (as typical for Function instances)
name's internal slots are (amongst others):
[[prototype]], pointing to Function.prototype
[[ECMAScriptCode]], pointing to the code of the function
[[Environment]], pointing to the scope the closure was created in
Disclaimer: That's only how it behaves, engines may implement this however they want. Still, it serves well as a mental model, and it's important to understand that objects have a layer below the publicly visible properties.
Functions are objects, in that they can have properties and methods. Unlike objects, they can also be called and will always return a result.
Note that the ECMAScript (i.e. JavaScript) language specification describes how Function objects should behave rather than underlying implementation, so the in-memory representation of the object will depend on implementation.
Regarding 2: Note that the full text of a Function might be stored in the functionBody property, however the body of a Function does not have to be JavaScript. It could be native code, for example, that is not meaningful to return in a string.
If you just want to do regular JavaScript coding, I don't think you really need to worry about how the function is stored by the browser or server or whatever. I do think you are misunderstanding the object-nature of a function. The lines of code inside the function are not individual parts of a hash map. Rather (and this only begins to touch on the concept), a function can have properties with names and values just like a regular object can have such properties. The following code demonstrates this.
var myFunc = function() {
var x = "hello".toUpperCase();
document.write('<p>' + x + '</p>');
};
myFunc.favoriteColor = "red";
myFunc(); // runs the function and shows the text "hello"
document.write("<p>" + myFunc.favoriteColor + "</p>"); // shows the text "red"
The answer to 1. is: It depends on the implementation.
The 2nd question doesn't make any sense.
I think you are looking at the syntax, and assuming that because the way data is declared, and the way functions are declared, that a function can be treated as data in the language.
This is not the case.
There are languages where this IS the case. Lisps and Prolog being the most common examples. see:
https://en.wikipedia.org/wiki/Homoiconicity
I tried googling but couldn't find a precise answer, so allow me to try and ask here. If the question does not seem proper, please let me know and I'll delete it.
In JS you've got three different way of writing certain build in functionalities:
str.length
str.toString()
parseInt(str)
I wonder if there is a reason behind these different ways of writing. As a new user I don't grasp why it couldn't be streamlined as: length(str) / toString(str) / parseInt(str) or with dot formulation.
I however think if I do know the reason behind these differences, it would give me a better understanding of JavaScript.
Length is one of the attributes of string in JavaScript. Hence you use string.length to get the length of the string.
toString is a function for string objects, hence we use stringobj.toString().
parsInt(str) is a global function which takes string as a parameter.
JavaScript is object-oriented, so there are functions or procedures which require first an object to use as this in their bodies. str.length is a property, both syntactically and semantically. It doesn't require any parameters and represents some quality of the object. obj.toString() is a method (a function attached to an object), which doesn't represent any characteristics of the object, but rather operates on its state, computes some new values, or changes the state of the object a lot. parseInt(str) is a "global" function, which represents an operation not attached to any type or object.
Under the hood, these three ways may be well implemented with just calling a function, passing this as the first parameter (like C# does, for example). The semantic difference is the important one.
So why not use just the third syntax, like for example PHP does? First, it doesn't bloat the global environment with lots of functions which only work for one specific case and type, allowing you to specify any new function you want without breaking the old functionality. Second, it ecourages you to use object-oriented concepts, because you can already see working objects and methods in the language, and can try to make something similar.
And why isn't parseInt a method? It can as well be str.toInt() without any issues, it's just the way JavaScript designers wanted it to be, although it seems also a bit logical to me to make it a static method Number.parseInt(str), because the behaviour of the function is relevant more to the Number type than the String type.
JavaScript is based around objects. Objects have properties (e.g. a User object may have name and age properties). These are what define the user and are related to the user. Properties are accessed via dot-notation or brackets notation (to access Eliott’s age, we’ll use either eliott.age or eliott['age'] — these are equivalent).
These properties can be of any type — String, Number, Object, you name it — even functions. Now the proper syntax to call a function in JS is to put round brackets: eliott.sayHello(). This snippet actually fetches Eliott’s sayHello property, and calls it right away.
You can see Eliott as a box of properties, some of which can be functions. They only exist within the box and have no meaning out of the box: what would age be? Whose age? Who’s saying hello?
Now some functions are defined at the global level: parseInt or isNaN for instance. These functions actually belong to the global box, named window (because legacy). You can also call them like that: window.parseInt(a, 10) or window.isNaN(a). Omitting window is allowed for brevity.
var eliott = {
name: 'Eliott',
age: 32,
sayHello: function () { console.log('Hello, I’m Eliott'); }
};
eliott.name; // access the `name` property
eliott.age; // access the `age` property
eliott.sayHello; // access the `sayHello` property
eliott.sayHello(); // access the `sayHello` property and calls the function
sayHello(eliott); // Reference error: `window.sayHello` is undefined!
Note: Some types (String, Number, Boolean, etc.) are not real objects but do have properties. That’s how you can fetch the length of a string ("hello".length) and reword stuff ("hello, Eliott".replace("Eliott", "Henry")).
Behaviour of these expressions is defined in ECMAScript grammar. You could read the specification to understand it thoroughly: ECMAScript2015 specification. However, as pointed out by Bergi, it's probably not the best resource for beginners because it doesn't explain anything, it just states how things are. Moreover I think it might be too difficult for you to be able to grasp concepts described in this specification because of the very formal language used.
Therefore I recommend to start with something way simpler, such as a very basic introduction to JavaScript: JavaScript Basics on MDN. MDN is a great resource.
But to answer your question just briefly:
str.length is accessing a property of the str object.
parseInt(str) is a function call
str.toString() is a call of a function which is a property of the str object. Such functions are usually named methods.
Functions and methods are in fact very similar but one of the differences (except for the obvious syntax difference) is that methods by default have context (this) set to refer to the object which they're part of. In this case inside of toString function this equals to str.
Note: Accessing a property (as in str.length) could in effect call a getter function but it depends on how the object is defined, and is in fact transparent for the user.
This question already has answers here:
Getting All Variables In Scope
(11 answers)
Closed 8 years ago.
I wanted to be able to get a list of all variables in the current scope. I know it may not be possible (ex. 1, 2, 3 but it would really be helpful in simplifying a parsing algorithm for a Node/browser library I'm currently working on.
One thing: it doesn't need to be printed or safe from 'minification'.
I was wanting to be able to figure out what variables were introduced by reading a JS library and dynamically evaling it, finding the difference in state between the two. I know this approach sounds terrible on paper (I'm well acquainted with the hatred of eval), but if there is a better way to find this than just simply parsing the whole library (which is slow for any language other than C/etc.), I'm all ears.
For you all right off crying over the blatant use of eval, I know to use closures to protect the parent scope from modification. I also will be able to prevent changes to the browser display in the eval as well if it is in a browser environment (temporarily change some DOM constructors).
Yes and no. "No" in almost every situation. "Yes," but only in a limited manner, if you want to check the global scope. Take the following example:
var a = 1, b = 2, c = 3;
for ( var i in window ) {
console.log(i, typeof window[i], window[i]);
}
Which outputs, amongst 150+ other things, the following:
getInterface function getInterface()
i string i // <- there it is!
c number 3
b number 2
a number 1 // <- and another
_firebug object Object firebug=1.4.5 element=div#_firebugConsole
"Firebug command line does not support '$0'"
"Firebug command line does not support '$1'"
_FirebugCommandLine object Object
hasDuplicate boolean false
So it is possible to list some variables in the current scope, but it is not reliable, succinct, efficient, or easily accessible.
So, here's what I need:
var a = 5;
var b = a;
a = 6;
alert(b) // I want this to alert 6 not 5
I've seen questions like How does variable assignment work in JavaScript?, answers like https://stackoverflow.com/a/509614/1117796 and posts like http://hpyblg.wordpress.com/2010/05/30/simulating-pointers-in-javascript/. I do NOT want to use objects/hashes/dictionaries or whatever else you want to call them. I want this done with plain variables containing plain primitive values. Something like the PHP assignment by reference: $b = &$a;. Is it at all possible? Anything that comes near to it?
No that isin't possible to pass simple values as reference in JavaScript.
However JavaScript is a flexible language and you could possibly implement something similar using Object.defineProperty by providing setters and getters that will all work with the same variable. That could work for global variables however, there's no way to completely mimic this behaviour. For instance, since you can't get a reference to the execution scope of functions, you would not be able to emulate this concept for variables declared inside functions.
No, this is not possible as of ECMA Script 5.
No its not possible. And its a boon that this is not allowed in JavaScript.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I came across this by mistake one day while programming a game:
var foo = function() { alert("Hello, World!"); }
foo[0] = "Zero";
foo[1] = "One";
foo[2] = "Two";
foo[3] = "Three";
foo(); // Alerts "Hello, World!"
alert(foo[2]); // Alerts "Two"
Why does JavaScript let you do this? Is this a glitch?
There are no arrays here. For example, Array.isArray(foo) is false.
Instead, you are giving foo four properties, named "0", "1", "2", and "3" [1], with different values. This is completely valid, because functions are objects; you can always attach properties, with whatever name you like, to objects.
You could also do:
foo.otherProp = "hi!";
alert(foo.otherProp);
[1]: Note that property names are always converted to strings before setting them; doing foo[{ toString: function () { return "baz"; }] = 5 will be the same as foo["baz"] = 5 or foo.baz = 5. Similarly, doing foo[0] = "whatever" is the same as doing foo["0"] = "whatever".
Why does JavaScript let you store an array and a function in one variable?
It doesn't. It lets you store a reference to a function in a variable. Functions are first-class objects in JavaScript, and so they can have properties, including ones with names like "0", "1", etc.
You're seeing a couple of things at play here:
What I said above, functions are objects, and so you can add properties to them.
You can add properties ad-hoc, there's no need to predefine them as in some other languages.
In JavaScript, you can refer to a property using dot notation and a literal (foo.bar), or using bracketed notation and a string (foo["bar"]).
When you use bracketed notation, the thing within the brackets is cast to a string if it isn't already one, so [0] is actually ["0"].
And yes, that last is true even when you're dealing with arrays, because standard arrays in JavaScript aren't really arrays. (There are recent additions, Int32Array and such, which are true arrays, but Array is not.)
The answer is quite simple, and can be expressed as a syllogism (for my amusement).
All objects can have developer-defined properties1.All functions are objects.Therefore, all functions can have developer-defined properties.
1 Technically not all objects. "Hardened" objects cannot be mutated by untrusted code, and objects provided by the application embedding the JavaScript runtime can customize their behavior to prevent this. These are edge cases, though. Un-hardened objects created from within the JavaScript runtime should all exhibit this functionality, and most of the time these are the objects one is trying to mutate.
foo[0] in this case assigns the value to a property named "0". A function is an object and can have properties added to it.
In the same way, these two are equivilant:
foo["abc"]
foo.abc
What no one's mentioned so far is that this feature allows you to associate information with a function that might be useful to the function, but without polluting the global space with a lot of public data that might create collisions and so on.
This is of course a feature of OOP/prototyping in general, but it has the added benefit of letting you call a function directly, and not as a property of a more general object.
Almost everything (including functions) in Javascript is an object, so you can give it extra properties like 0 and 1.
First of all, your question has nothing to do with your title.
The answer to the question asked in your title, "Why does JavaScript let you store an array and a function in one variable?", JavaScript is a dynamically typed language, and that means you can put whatever you like in a variable, and the interpreter won't complain.
In the body of your question, you wonder why you are allowed to set attributes of a function, as if it were an object or an array.
Well, you just can. That's the definition of the language. It's enormously useful to be able to add metainformation about a function.
But yes, JavaScript is covered with sharp edges and pointy bits, so you have to be careful.
In JavaScript, functions are first class objects.
function foo() {}
var isObject = foo instanceof Object;
// isObject is true
That's the deal with assigning functions to a variable, passing them as arguments, returning them from functions etc.
Reference on MDN