in the beginning i declare a variable like this:
var content = "likes";
var main_likes_data = true;
And later i want to change the variable to false, but i need to add a new variable like this:
main_" + content + "_data = false;
But this does not work!
Can someone please tell me the right sytax to change the variable?
Thank You!!!
You need an associative array.
var content = "likes";
var main_data = {
likes: true,
somethingelse: false,
xyz: false
};
main_data[content] = false;
window["main_" + content + "_data"] = true;
This works as
a) variables created without a defined scope are, by default, scoped against the window object
b) You can use the square bracket notation in javascript interchangably with the dot notation. The square bracket notation takes a string. The string can be concatenated using variables.
Live example: http://jsfiddle.net/bX5Zy/
It's really bad programming practice, but you could use eval:
eval("main_" + content + "_data = false");
I personally would not use eval myself, but other people would. To quote John Resig:
“Overwhelmingly [eval is] trivailized, misused, and outright condemned
by most JavaScript programmers but by looking at the work of some of
the best coders you can see that , when used appropriately [it] allows
for the creation of some fantastic pieces of code that wouldn’t be
possible otherwise”
John Resig, in Secrets of the JavaScript Ninja
Related
My problem is simple:
I want to concatenate a dynamic variable name in a function, so with the name insert in parameter, when I call the function, she concat automatically the string in the new variable name.
Exemple (wrong, I think):
function blockDL(insertName){
return var 'block' + insertName + 'DT'= document.createElement('dt');
};
blockDL('First');
I expect the code return:
blockFirstDT = document.createElement('dt');
Thanks for your help ! =)
What you want is not possible. See "Variable" variables in Javascript? for alternatives of what you can do.
However, "variable variables" is usually a indicator of bad code design. Especially in your case, there is absolutely no reason or benefit to do any of these. Just name the variables blockDT and paraphDT or whatever you want.
The only way you will be able to use a string for a variable name is by placing it as the property of another object. if you want the variable global you could use the window object.
window['block' + insertName + 'DT'] = document.createElement('dt');
that said, you really shouldn't need to and should probably look for other ways of structuring your code.
To create an IDE that would autocomplete all variables the user declares but would be oblivious to other variables such as Math.PI or even the module Math, the IDE would need to be able to identify all identifiers relating to variables declared by the user. What mechanism could be used to capture all such variables, assuming you already have access to the AST (Abstract Symbol Table) for the program?
I am using reflect.js (https://github.com/zaach/reflect.js) to generate the AST.
I think it's pretty much impossible
Here is why I think it's pretty much impossible without executing it:
Let us go through the unexplored parts, from easy to hard.
Easy to catch:
Function scope is missed here:
(function(x){
//x is now an object with an a property equal to 3
// for the scope of that IIFE.
x;
})({a:3});
Here is some fun dirty tricks for you all.:
Introducing... drum roll... Block Scoping!!
with({x:3}){
x;//x is now declared in the scope of that with and is equal to 3.
}
try{ throw 5}catch(x){
x // x is now declared in the scope of the try block and is equal to 5;
}
(people reading: I beg you to please not use these last two for actual scoping in code :))
Not easy:
Bracket notation:
var n = "lo";
a["h"+"e"+"l"+n] = "world"; // need to understand that a.hello is a property.
// not a part of the ast!
The really hard parts:
Let us not forget invoking the compiler These would not show up in the AST:
eval("var x=5"); // declares x as 5, just a string literal and a function call
new Function("window.x = 5")();// or global in node
In node.js this can also be done with the vm module. In the browser using document.write or script tag injection.
What else? Of course they can obfuscate all they want:
new Function(["w","i","n","dow.x"," = ","5"].join(""))(); // Good luck finding this!
new Function('new Function(["w","i","n","dow.x"," = ","5"].join(""))()')();// Getting dizzy already?
So what can be done?
Execute the code, once, in a closed, timed environment when you update the symbol table (just the relevant parts)
See what's the generated symbol table is from the execution
Boom, you got yourself a symbol table.
This is not reliable but it's probably as close as you get.
The only other alternative I can think of, which is what most IDEs are doing is to simply ignore anything that is not:
object.property = ... //property definition
var a = ... //scoped
b = ... //global, or error in strict mode
function fn(){ //function declaration
object["property"] //property with a _fixed_ literal in bracket notation.
And also, function parameters.
I have seen no IDE that has been able to deal with anything but these. Since they're the most common by far, I think it's perfectly reasonable to count those.
By adding them onto am object that already exists....ie
window.mynewvar = 5;
function mynewfunc() {
}
My code -
<script type="application/javascript">
var firstObject = {
sayHello : function(){
document.write("My name is "+ this.myName +"<br>");
},
myName : "Swapnesh Sinha"
};
var secondObject = {myName : "Sanjay Sinha"};
document.write("First one " + firstObject.sayHello() );
document.write("<br>");
document.write("Second one "+ secondObject.myName);
</script>
Source - http://learn.jquery.com/javascript-101/this-keyword/
Expecting output -
First one Swapnesh Sinha
Second one Sanjay Sinha
Unexpected Output (from my sense)-
My name is Swapnesh Sinha
First one undefined
Second one Sanjay Sinha
Let me know the case why it returns undefined however source is mentioning to return name ? or something I am getting wrong from my side
In your first document.write, you call a function, and ask the return value of the function to be concatenated to the string "First one ".
The function is evaluated, at which point "My name is Swapnesh Sinha" gets outputed via document.write call inside the object. That function call however does not return a value, hence it is undefined, and that gets concatenated to "First one", which is then printed.
Here is the working fiddle: JsFIDDLE
Here is what you fail to understand, as most jQuery developers: JavaScript scoping.
Basically, in order for a property to be accessed via this, it has to be nested in the Object.prototype.
Correction
When you define the object properties inline, calling this will still point to the right object. However, the pattern I gave you, even though less popular, is a much neater and better approach.
The prototype is the JavaScript way of OOP. If you are looking for solid OOP style JS and for proper definition of models, improved code maintainability and better coding style, it is preferred to define classes using the pattern I gave you, as it will allow you to make a strong distinction between static functions and classes. It is also the natural flow of JavaScript, where everything is an object.
In high level JavaScript programming(powerful Ajax applications or applications where for one reason or the other the browser has to perform more advanced computation), the below style is always preferred. Static functions placed under a namespace are still defined separately:
var namespace = {};
namespace.firstStaticFunc = function() {/*do stuff etc;*/};
namespace.secondStaticFunc = function() { return !1; };
The only reason why you use your definition pattern is enums and hash maps. For instance:
var typesOfChicken = {
RED: 'red',
BLUE: 'blue'
};
The above is always used for things like internationalization and avoidance of hard coded values. Also, it helps JS minifiers to a better job. Given the above, you can say:
console.log(typesOfChicken.RED);// will print red.
console.log("red");// wil still print red
But, when I want to change red to something else, using enums I only have to do a single change. Also, the minifier can replace typesOfChicken.RED with a.b, whereas "RED" will always be "RED". It's unminifiable.
var firstObject = function() { };
firstObject.prototype.myName = "Swapnesh Sinha";//this will not be nested as an instance property.
firstObject.prototype.sayHello = function() {
alert(this.myName);// will now correctly display Swapnesh Sinha
};
// to use your first object.
var instance = new firstObject();
instance.sayHello();
To properly make use of scope, use the pattern I gave you, which is an Object Oriented pattern and the right approach to defining classes in JS.
And now you have a great way to organize your JavaScript code, it's fair easier to maintain, scope is a lot more obvious and most important of all you can immediately make a distinction between static functions and classes.
replace document.write() with return in your sayHello function
In JavaScript, is there a naming convention for objects instantiated from constructor functions?
For example, if I had a constructor function set up like so:
function Dance(style, timing) {
this.style = style; // for reflection
this.timing = timing;
}
var waltz = new Dance('waltz' , '3/4');
var rumba = new Dance('rumba' , '4/4');
So a console command would look like this:
console> waltz.timing 3/4
console> rumba.timing 4/4
What I'm looking for is a convention saying that waltz and rumba are instantiated objects; like prefixing with an "o"?
var oWaltz = new Dance('waltz' , '3/4');
var oRumba = new Dance('rumba' , '4/4');
I actually (gasp!) Googled and did a little homework before asking this question, and came up with the following:
a. Crockford's "JavaScript: The Good Parts." Most notably, he recommends using a capital letter on the actual constructor function:
There is a convention that all constructor functions are named with an initial capital (Pg. 49).
Fine, but I don't see any convention regarding instances of these constructor functions. All his examples are prefixed with "my," like so..
var myTango = new Dance('tango' , '4/4');
console> myTango.timing 4/4
...which is great for an example, but is not a reasonable convention.
b. I also dug up this thread, which calls the "o" prefix "Hungarian dialect," and also calls it obsolete:
What does "o" mean as a variable prefix?
c. We also have the convention of prefixing variables that contain jQuery wrapped set with a "$" like the following, which would select all <button> tags on the page, create a jQuery wrapped set, and assign it to the $buttons variable:
$buttons = $('button');
d. Finally, a simple Google search for "JavaScript object instance prefix" yields the underscore "_" convention for private functions; in this example if we were to add a private prototype function, it might look like this:
Dance.prototype._lessonCost = function(minutes) { return ($1.50 * minutes); }
Which, again, is not really of any help, which brings me here.
If you made it this far, thank for answering :^) I feel like I'm missing something; like there's a fundamental flaw with my technique.
I'm not sure if its a standard but usually instances of objects start with a lowercase letter and then camel case the rest. I'm not aware of any prefixes and think this would just cause a bunch of extra code to pass to the client.
var myObject = new MyObject();
I'm pretty new to Javascript, as my SO profile will attest.
I've just been reading up on a few tutorials and come across something I don't totally understand in regards to Object Orientation and Encapsulation when applied with Javascript.
The tutorial stated that Javascript objects can be declared like this:
var myCustomObject = new Object();
And that you can give it instance variables like this:
myCustomObject.myVariable = "some value";
myCustomObject.myOtherVariable = "deadbeef";
Finally, it states that you can create a template function to create new objects like this:
function CustomObject(myVariable, myOtherVariable)
{
this.myVariable = myVariable;
this.myOtherVariable = myOtherVariable;
}
I also know that you can create and assign values to variables that do not yet exist and as a result are declared implicitly, as is seen in the example, where myCustomObject didn't have a myVariable, but now it does.
So, my question is: What is there to prevent new variables from being added at some other point in the code. If I'm trying to learn how an object works and what I can/should do with it, I may never see the variable additions that could well be in some other .js file, and thus not have a full understanding of the object...
Also, how do I know that some object that has just been created won't suddently turn out to have 60 more variables added later on in code that weren't mentioned at all at creation time?
How are you meant to be able to understand what an object can contain at a glance if more can just be added to it "willy nilly"?
I can't quite believe that I'm about to quote Spiderman but …
With great power comes great responsibility
JavaScript is powerful and flexible and gives programmers lots of freedom. It doesn't come with features designed to stop programmers writing bad code. When you write JavaScript, you are responsible for making sure the code is good, not the language.
You can't, there's nothing that stops me from doing whatever I want with your objects ;) However, you don't have to use those variables..
One thing you can do is to play with scopes, example:
function myConstructor()
{
var myState = {}; //Create new, empty object
myState.text = "Hello World!";
this.say = function() {
alert(myState.text);
};
}
In this simple example you can store you internal variables in myState (or "var text = '';" etc) and they aren't accessible from outside since they are not members of an object, they are just private variables in your function. And, as you can see, the function say still has access to it.
Short answer: Absolutely nothing.
Long answer:
Javascript is a dynamic language in more ways than just the type system. Every object like thing in the language is basically an associative array which can be added to as you please. Variables (which can obviously contain these object like things) exist only within their function scope.
You can use this point to simulate private members which can tame the situation somewhat. I've posted examples of this several times before so I'll just refer you to the definitive guide on the subject: http://javascript.crockford.com/private.html.
As far as adding new members to objects in a way you did not intend goes, there's really nothing to be done that's just the way the language is.
Afterthought:
When approaching javascript try to remember it's really not an OOP language it's a weird and wonderful mix of functional / prototypical with a few OOP ideas. Don't be fooled by the java like syntax, you'll have a much better time if you play to the languages strengths rather than ape java.
Javascript objects are transformers (TM), they can turn from one form to another.
In practise this only happens to enrich objects, never to cause harm. It allows one to for example upgrade an existing 'class' rather then subclassing or to decorate instances again removing the need to create even more 'classes'. Take the following example:
var Vehicle = function(){}
var factory = {
create: function(name, props){
var v = new Vehicle();
v.type = name;
for(var prop in props) {
v[prop] = props[prop];
}
}
}
var bike = factory.create('Bike', {
wheels: 2
});
var car = factory.create('Car', {
wheels: 4,
doors: 5,
gear: 'automatic'
});
var plane = factory.create('Airplane', {
wings: 2,
engines: 4
});
Imagine what the code above would take without dynamic objects and you couldn't do this:
// lets paint our car
car.color = 'candy red';
// bling!
car.racingStripes = true;
car.mirrorDice = true;
car.furryChairs = true;
You get to enrich/personalize objects in a much easier way.