how to reference object as string name - javascript

I need to reference my object as a string but I am having issues.
ideally I would like this to work ['mystring'].myproperty; but obviously this wont work.
Is there another way besides the options below?
// auto generated ecample/////////////
var mystring = {
myproperty :'test'
}
/////////////////////////////////////
var optionA =mystring.myproperty; // works
var optionB = window['mystring'].myproperty; //gives issues
var optionC = eval('mystring').myproperty; //gives issues
var optionD = ['mystring'].myproperty; // wont work

If your variables are defined on a global scope, the following works
window[ mystring.myproperty ].data
If you are in a function's scope, things get a lot harder. Easiest way then is to define your objects in a specific namespace on window and retrieve the objects similar to the above code.

Related

How to create dynamic variables using jquery?

I want some jquery variables to be created dynamically. In my code I am having a loop, and with the loop values I want to create some variables. Here is my sample code.
array=["student","parent","employee"]
$.each(user_types, function( index, value ){
var value+"_type" // this is the type of variable i want to build.
})
I have found about eval function. That code goes like this.
var type = "type"
eval("var pre_"+type+"= 'The value of dynamic variable, val';");
alert(pre_type) // this gives 'The value of dynamic variable, val' in alert box.
Is there any alternate ways as I have read the eval function is not prefered while coding .js files.
Any time you find yourself using a variable in the name of a variable, you probably want to use an object literal. Create the object with curly braces {}, and then set the object property key using square bracket notation:
var user_types = ["student","parent","employee"];
var types = {};
$.each(user_types, function( index, value ){
types[value] = 'The value of dynamic variable, val';
});
JSFiddle
Note: You haven't tagged it, but I assume because you've used each() that you are using jQuery, please correct me if I'm wrong.
First of all i must say that i can't think of any reason why you want to do this.
If you really need to have those variables, in global scope, you can do the following:
var array=["student","parent","employee"]
array.forEach(function(value){
window[value+"_type"] = 'My value ' + value;
});
console.log(student_type);
console.log(parent_type);
console.log(employee_type);
If you don't want the variables in global scope, i'm afraid i don't know an elegant solution.
I used array.forEach instead of your jQuery loop because the problem is not related to jQuery at all and because i don't think you said enough of your logic to make a coherent example.
EDIT: I should make it clear that while the 'variables' created behave mostly like other variables in global scope, they are NOT variables. Here is how they differ:
// Difference 1: hoisting
console.log(x); // undefined
console.log(y); // ReferenceError: y is not defined
var x = 5;
window[y] = 5;
console.log(x); // 5
console.log(y); // 5
// Difference 2: [[Configurable]]
delete x;
delete y;
console.log(x); // 5
console.log(y); // ReferenceError: y is not defined
If you want to add an intermediate variable inside the string, you can do it as follows:
var itemSelect: number = 1;
$(`#tab${this.itemSelect}-tab`).tab('show');
/* Result -> $(`#tab1-tab`).tab('show'); */
/* HTML */
<a id="tb1-tab"> </a>

Problems with basic prototyping in Javascript

i am kinda new to javascript and i started off on something where i am stuck with some basics, the thing is i am trying to create an prototype for an object and then the references of created objects in an array and then accesing their methods but i am wrong somewhere can anyone help me with this, what i am doing is shown here :-
function Obj(n){
var name=n;
}
Obj.prototype.disp = function(){
alert(this.name);
};
var l1=new Obj("one");
var l2=new Obj("two");
var lessons=[l1,l2];
//lessons[0].disp();
//alert(lessons[0].name);
but none of these methods seem to work out.... :(
You not assigning a property of the Obj object, but just have a local variable inside the constructor. Change like this:
function Obj(n){
this.name = n;
}
Example Fiddle
Your problem is with the constructor, you are assigning the parameter to a local variable not to a field variable, change it like:
function Obj(n){
this.name=n;
}
Hope this helps
Use this:
function Obj(n){
this.name=n;
}
REASON:
Difference between var name=n; and this.name=n;
var name=n;
The variable declared with var is local to the constructor function. It will only survive beyond the constructor call if it's used in some method inside the object
this.name=n;
this is property of the object, and it will survive as long as the object does, irrespective of whether it's used or not.
Example:this in javascript

javascript function arguments as private variables

I remember reading somewhere that function arguments get turned into private variables within the function so I tried this:
var node = function(nParent,nName,nContent){
this.init = function(){
alert(nName+" "+nParent+" "+nContent);
}
};
var a = new node("A - parent","A - name","A - content");
var b = new node("B - parent","B - name","B - content");
a.init();
b.init();
which alerts the correct passed in arguments so is this ok to use instead of something like this:
var node = function(nParent,nName,nContent){
var parent = nParent;
var name = nName;
var content = nContent;
this.init = function(){
alert(name+" "+parent+" "+content);
}
};
I know I would have to use the second version if I wanted to do any form of extra validation checking on the arguments before assigning them to the private variables, I just didn't want to waste space if the arguments are already private variables that will never go anywhere, is this a reasonable thing to do?
Thanks,
Of course it's okay. These arguments are instantiated variables, with no appreciable difference from the other variables you set them to.
Now, if you didn't use any named parameters, and used arguments instead, then there would be a difference: in code readability, in even performance (there's a penalty for using arguments).
Only downside to all of this is that your variable definitions won't all be in the same place. (Assuming that there would be any more variable definitions and assignments in this function, beyond the params passed.)
Yes; that's perfectly fine.

Javascript local variable declare

Basically this is a question how to access local scope handler. I trying to achieve something similar for global variable definition like:
window['newObject'] = "some string";
alert(newObject);
but for local scope. Right now only solution I have is using evals:
eval("var newObject='some string'");
But this is really ugly solution... The best one would be like using some reference to local scope like in a window[] solution, but I never heard of any reference to local scope... Any ideas ?
Example goes here:
function x(arg)
{
localScope[arg.name]=arg.value;
alert(sex);
}
x({name:"sex", value:"Male"});
What you're looking for is called the call object. But according to this, you can't access it directly, so you're out of luck.
Why not create an object in local scope and then use it as a container for any variables you wish to create dynamically?
function x(arg)
{
var localSpace = {};
localSpace[arg.name] = arg.value;
}
Okey I found related question that is talking about what I need...
How can I access local scope dynamically in javascript?
I just remember that in ECMA 262 is only one way to add dynamically local variables to scope using "with" statement (and eval of course), here are solution:
var x=function(obj)
{
with(obj)
{
alert(someObj);
}
}
alert(typeof someObj);
x ( {someObj:"yea"}) ;
alert(typeof someObj);
I must be missing something. How is what you want different from just doing:
var newObject = 'some string';
? (OP has clarified question)
I don't think there is a way to do what you are asking. Use members of a local object, e.g.
function doSomething(name, value)
{
var X = {};
X[name] = value;
if (X.foo == 26)
alert("you apparently just called doSomething('foo',26)");
}
If you choose a 1-character variable like $ or X, it "costs" you 2 characters (variable name plus a dot), and avoids trying to use eval or doing something weird.
You could try the named arguments trick
EDIT: This isn't cross browser
function x( {sex:sex, height:height} ) {
alert( sex );
alert( height );
}
x( { sex: 'male', height: 'short' } );
x( { height: 'medium', sex: 'female' } );
// male
// short
// female
// medium
Not sure what you need exactly, but here's my 2 cents.
The only way to dynamically create vars in an existing function is the eval method you've already mentioned.
Another option (mentioned by others) is that your function take a context map, and the template access it with dot notation (context.var1)
My final suggestion is the Function constructor. But I have a feeling this may be what you're looking for. (Note that the function constructor suffers from the same problems as an eval call)
var arg1 = "first";
var arg2 = "last";
// This is the body of the function that you want to execute with first
// and last as local variables. It would come from your template
var functionBody = "alert(first + ' ' + last)";
var myCustomFun = new Function(arg1, arg2, functionBody);
myCustomFun("Mark", "Brown"); // brings up and alert saying "Mark Brown";
Hope it helps
Interesting question, never thought of something like this. But what is the usecase?
The reason you'd want to do something like this, is if you don't know the name of the variable. But then in that case, the only way to access the variable again would be using the same reference object. I.e. you could just use any old object to store data in.
Reading from such a reference object would be interesting for debugging purposes, but I don't see why you'd want to write to it.
Edit:
The example you posted doesn't convince me of the need for access to the local scope, since you still have the name sex hard coded in the alert. This could be implemented as:
function x(arg)
{
container = {};
container[arg.name] = arg.value;
alert(container.sex);
}
Could you elaborate more on the example?
I'm not entirely sure I understand your question. When creating a class x, I generally do this:
function x(args) {
var _self = this;
_self.PriviledgedMethod(a) {
// some code
}
function privateMethod(a) {
// some code
}
}
var newObject = new x(args);
You can continue to access _self and args since it is closed on by the contained functions.

How to get class object's name as a string in Javascript?

Let's say I instantiate an object in Javascript like this:
var myObj = new someObject();
Now, is it possible to obtain the var object's name as string 'myObj' from within one of the class methods?
Additional details (edited):
The reason why I would like to get the name of the variable holding reference to the object is that my new myObj would create a new clickable DIV on the page that would need to call a function myObj.someFunction(). As I insert the new DIV I need to know the name of the variable holding reference to the object. Is there maybe a better way of doing this?
You are right, sorry for the mixup in terminology.
The reason why I would like to get the name of the variable holding reference to the object is that my new myObj would create a new clickable DIV on the page that would need to call a function myObj.someFunction(). As I insert the new DIV I need to know the name of the variable holding reference to the object. Is there maybe a better way of doing this?
Shog9 is right that this doesn't make all that much sense to ask, since an object could be referred to by multiple variables. If you don't really care about that, and all you want is to find the name of one of the global variables that refers to that object, you could do the following hack:
function myClass() {
this.myName = function () {
// search through the global object for a name that resolves to this object
for (var name in this.global)
if (this.global[name] == this)
return name
}
}
// store the global object, which can be referred to as this at the top level, in a
// property on our prototype, so we can refer to it in our object's methods
myClass.prototype.global = this
// create a global variable referring to an object
var myVar = new myClass()
myVar.myName() // returns "myVar"
Note that this is an ugly hack, and should not be used in production code. If there is more than one variable referring to an object, you can't tell which one you'll get. It will only search the global variables, so it won't work if a variable is local to a function. In general, if you need to name something, you should pass the name in to the constructor when you create it.
edit: To respond to your clarification, if you need to be able to refer to something from an event handler, you shouldn't be referring to it by name, but instead add a function that refers to the object directly. Here's a quick example that I whipped up that shows something similar, I think, to what you're trying to do:
function myConstructor () {
this.count = 0
this.clickme = function () {
this.count += 1
alert(this.count)
}
var newDiv = document.createElement("div")
var contents = document.createTextNode("Click me!")
// This is the crucial part. We don't construct an onclick handler by creating a
// string, but instead we pass in a function that does what we want. In order to
// refer to the object, we can't use this directly (since that will refer to the
// div when running event handler), but we create an anonymous function with an
// argument and pass this in as that argument.
newDiv.onclick = (function (obj) {
return function () {
obj.clickme()
}
})(this)
newDiv.appendChild(contents)
document.getElementById("frobnozzle").appendChild(newDiv)
}
window.onload = function () {
var myVar = new myConstructor()
}
Short answer: No. myObj isn't the name of the object, it's the name of a variable holding a reference to the object - you could have any number of other variables holding a reference to the same object.
Now, if it's your program, then you make the rules: if you want to say that any given object will only be referenced by one variable, ever, and diligently enforce that in your code, then just set a property on the object with the name of the variable.
That said, i doubt what you're asking for is actually what you really want. Maybe describe your problem in a bit more detail...?
Pedantry: JavaScript doesn't have classes. someObject is a constructor function. Given a reference to an object, you can obtain a reference to the function that created it using the constructor property.
In response to the additional details you've provided:
The answer you're looking for can be found here: JavaScript Callback Scope (and in response to numerous other questions on SO - it's a common point of confusion for those new to JS). You just need to wrap the call to the object member in a closure that preserves access to the context object.
You can do it converting by the constructor to a string using .toString() :
function getObjectClass(obj){
if (typeof obj != "object" || obj === null) return false;
else return /(\w+)\(/.exec(obj.constructor.toString())[1];}
You might be able to achieve your goal by using it in a function, and then examining the function's source with toString():
var whatsMyName;
// Just do something with the whatsMyName variable, no matter what
function func() {var v = whatsMyName;}
// Now that we're using whatsMyName in a function, we could get the source code of the function as a string:
var source = func.toString();
// Then extract the variable name from the function source:
var result = /var v = (.[^;]*)/.exec(source);
alert(result[1]); // Should alert 'whatsMyName';
If you don't want to use a function constructor like in Brian's answer you can use Object.create() instead:-
var myVar = {
count: 0
}
myVar.init = function(n) {
this.count = n
this.newDiv()
}
myVar.newDiv = function() {
var newDiv = document.createElement("div")
var contents = document.createTextNode("Click me!")
var func = myVar.func(this)
newDiv.addEventListener ?
newDiv.addEventListener('click', func, false) :
newDiv.attachEvent('onclick', func)
newDiv.appendChild(contents)
document.getElementsByTagName("body")[0].appendChild(newDiv)
}
myVar.func = function (thys) {
return function() {
thys.clickme()
}
}
myVar.clickme = function () {
this.count += 1
alert(this.count)
}
myVar.init(2)
var myVar1 = Object.create(myVar)
myVar1.init(55)
var myVar2 = Object.create(myVar)
myVar2.init(150)
// etc
Strangely, I couldn't get the above to work using newDiv.onClick, but it works with newDiv.addEventListener / newDiv.attachEvent.
Since Object.create is newish, include the following code from Douglas Crockford for older browsers, including IE8.
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o
return new F()
}
}
As a more elementary situation it would be nice IF this had a property that could reference it's referring variable (heads or tails) but unfortunately it only references the instantiation of the new coinSide object.
javascript: /* it would be nice but ... a solution NOT! */
function coinSide(){this.ref=this};
/* can .ref be set so as to identify it's referring variable? (heads or tails) */
heads = new coinSide();
tails = new coinSide();
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);
alert(["FF's Gecko engine shows:\n\ntoss.toSource() is ", toss.toSource()])
which always displays
[object Object]
and Firefox's Gecko engine shows:
toss.toSource() is ,#1={ref:#1#}
Of course, in this example, to resolve #1, and hence toss, it's simple enough to test toss==heads and toss==tails. This question, which is really asking if javascript has a call-by-name mechanism, motivates consideration of the counterpart, is there a call-by-value mechanism to determine the ACTUAL value of a variable? The example demonstrates that the "values" of both heads and tails are identical, yet alert(heads==tails) is false.
The self-reference can be coerced as follows:
(avoiding the object space hunt and possible ambiguities as noted in the How to get class object's name as a string in Javascript? solution)
javascript:
function assign(n,v){ eval( n +"="+ v ); eval( n +".ref='"+ n +"'" ) }
function coinSide(){};
assign("heads", "new coinSide()");
assign("tails", "new coinSide()");
toss = Math.random()<0.5 ? heads : tails;
alert(toss.ref);
to display heads or tails.
It is perhaps an anathema to the essence of Javascript's language design, as an interpreted prototyping functional language, to have such capabilities as primitives.
A final consideration:
javascript:
item=new Object(); refName="item"; deferAgain="refName";
alert([deferAgain,eval(deferAgain),eval(eval(deferAgain))].join('\n'));
so, as stipulated ...
javascript:
function bindDIV(objName){
return eval( objName +'=new someObject("'+objName+'")' )
};
function someObject(objName){
this.div="\n<DIV onclick='window.opener."+ /* window.opener - hiccup!! */
objName+
".someFunction()'>clickable DIV</DIV>\n";
this.someFunction=function(){alert(['my variable object name is ',objName])}
};
with(window.open('','test').document){ /* see above hiccup */
write('<html>'+
bindDIV('DIVobj1').div+
bindDIV('DIV2').div+
(alias=bindDIV('multiply')).div+
'an aliased DIV clone'+multiply.div+
'</html>');
close();
};
void (0);
Is there a better way ... ?
"better" as in easier? Easier to program? Easier to understand? Easier as in faster execution? Or is it as in "... and now for something completely different"?
Immediately after the object is instantiatd, you can attach a property, say name, to the object and assign the string value you expect to it:
var myObj = new someClass();
myObj.name="myObj";
document.write(myObj.name);
Alternatively, the assignment can be made inside the codes of the class, i.e.
var someClass = function(P)
{ this.name=P;
// rest of the class definition...
};
var myObj = new someClass("myObj");
document.write(myObj.name);
Some time ago, I used this.
Perhaps you could try:
+function(){
var my_var = function get_this_name(){
alert("I " + this.init());
};
my_var.prototype.init = function(){
return my_var.name;
}
new my_var();
}();
Pop an Alert: "I get_this_name".
This is pretty old, but I ran across this question via Google, so perhaps this solution might be useful to others.
function GetObjectName(myObject){
var objectName=JSON.stringify(myObject).match(/"(.*?)"/)[1];
return objectName;
}
It just uses the browser's JSON parser and regex without cluttering up the DOM or your object too much.

Categories

Resources