I have some simple code here that I'm running in Visual Studio Code with Quokka and NodeJS.
var str = "hello"
function printStr(){
console.log(this.str);
}
printStr();
Output:
undefined at this.str quokka.js:6:4
I can run this code in my web browser just fine, and it works just fine, printing out "hello".
"use strict"; is not enabled
Screenshot: https://i.imgur.com/IEQwv5D.png
In a browser this will be interpreted as the window object in this case and the variable str will be defined on the window. There is no window object in Node. It's not clear why you are using this at all here rather than using regular scoping rules. This will work in both the browser and Node:
var str = "hello"
function printStr(){
console.log(str); // will see outside scope
}
printStr();
Better yet, pass the value into the function so it doesn't depend on values defined outside its scope:
var str = "hello"
function printStr(s){
console.log(s);
}
printStr(str);
In Node there is a global object, which has some similarity to the browser's window object so code like this can work in Node, but it would be a fairly non-standard way to do this:
global.str = "hello"
function printStr(){
console.log(this.str)
}
printStr();
Inside a function this normally refers to the window object and the variable str is not defined on window.
You may simple call it like
var str = "hello"
function printStr(){
console.log(str);
}
printStr();
I hope mi answer will be to help. The object 'this' is undefined in node JS for the element window not exist and you aren't working with any object or constructor or class.
For example:
var Animal = function(kind) {
this.name = "NN"
this.kind = kind
};
Animal.prototype.printName = function() {console.log(this.name)};
Animal.prototype.setName = function(name){this.name = name}
var a1 = new Animal("Lion");
var a2 = new Animal("Cat");
a1.setName("Robert");
a2.setName("Alex");
a1.printName();
a2.printName();
Please look at the code when I use the sentence this. if you have a questions, please write me! (Y)
Related
Ever since let came out it allowed me to follow stricter naming conventions.However, lets consider the below scenario, would it be valid or is it hacky to do something like this? I am very well aware that the first has function scope and the other block scope.
var sample = 'sample';
function fooBar() {
let sample = 'This is a sample';
console.log(sample);
}
fooBar();
console.log(sample)
What you are trying to do here is perfectly valid and is called shadowing. As the name suggests - You have shadowed the global scoped variable sample with the function scoped variable sample. And by doing that you have restricted yourself to access the global variable without using some special tricks.
You can still access global variable of the same name inside the function as given below
var sample = 'sample';
function fooBar() {
var sample = 'This is a sample';
console.log(sample); // 'This is a sample'
console.log(window.sample); //Sample
//console.log(this.sample);//Sample. Works only in non strict mode
}
fooBar();
console.log(sample); // 'sample'
Moreover, if someone says never use var then that little too hard a statement to make. var still has its use. You can have a look at this article by Kyle Simpson here
https://davidwalsh.name/for-and-against-let
Hope this be of some help.
Happy Learning :)
Vatsal
It's valid.
And since one declaration is outside the function and the other is inside, you could even declare both with var:
var sample = 'sample';
function fooBar() {
var sample = 'This is a sample';
console.log(sample); // 'This is a sample'
}
fooBar();
console.log(sample); // 'sample'
I know using eval is not at all recommended and I have read this link too. Set Variable inside Eval (JavaScript)
However, this is what I want to do. Lets say we have some code in a textbox. So I have to take that text, and then find out all the global variables, functions and objects in that code.
My idea was to wrap the code in a namespace, eval it and then iterate through the properties of the namespace to get the results. However, even though the eval runs successfully, I can't access the variable defined there. Is there a better solution or some other way to get this working.
http://jsfiddle.net/DbrEF/2/ - This is the Fiddle here.
The "var code" could actually be arbitrary code. I know its unsafe to do it but I need it for a different context.
Thanks
In 2015, creating a Function object is your best bet here, rather than using eval:
new Function('arg1', 'arg2', 'return arg1 + arg2')(3,4) // returns 7
You might have better luck using a Javascript parser, like the one used by JSHint/JSLint
here's a demo on safely using eval using "use strict"
window.onload = function(){
'use strict';
//use strict forces to run code in "strict mode"
//use strict prevents eval from
//contaminating the immediate scope
//let's test with "foo"
var foo = 'lol';
//now code has "foo" but using "use strict"
//makes code in eval stay in eval
//note that at the last of the code, foo is "returned"
var code = 'var foo = {name: "Spock",greeting: function() {return "Hello " + foo.name;}}; foo';
//store eval'ed code in evalO
var evalstore = eval(code);
console.log(evalstore); //code in eval stays in here, which is "inner foo"
console.log(foo); //"outer foo" is unharmed and daisy fresh
};
so whatever code you have, contain it in a function which will serve as your namespace. then have that function returned to the outside world stored as a variable. this demo shows how it can be constructed, however, works only if code is in object literal notation.
window.onload = function() {
'use strict';
var ns = 'lol';
//code must be an object literal
var code = '{name: "Spock",greeting: function(){return "Hello " + foo.name;}}';
//store in a constructor to be returned
var constructorString = 'var ns = function(){return ' + code + '}; ns';
var evalNs = eval(constructorString); //type function/constructor
var evalObj = new evalNs() //object instance
console.log(evalNs); //constructor
console.log(evalObj); //the namespaced object
console.log(ns); //outer "ns" preserved
};
Probably not what exactly OP was looking for but another option is to use outside variables to store values generated inside eval, as in:
var value;
var code = 'var foo = 42';
code = code.replace('var foo', 'value');
eval(code);
value // returns 42;
While I'm at work, I'll write little snippets of JS to explore the language proper, not using any frameworks. However, since I'm lazy, I'll keep a reference to document.getElementById by storing it in a variable:
var grab = document.getElementById;
var foo = grab('some_id');
var bar = grab('some_other_id');
This has always worked in IE7/8, but I tried it back home on Firefox and it didn't like the shortcut. Now, it works when I wrap it up in a function and close over the argument:
var grab = function (some_id) {
return document.getElementById(some_id);
};
but I don't understand why I need to do that; in Firefox I can throw around references to user-defined functions and it doesn't complain:
var foo = function(x) {
alert(x);
};
var bar = foo;
foo('foo'); // alerts 'foo'
bar('bar'); // alerts 'bar'
Why can't I call a reference to document.getElementById I've stored in a variable?
It's about this value. I've created a test case on jsFiddle http://jsfiddle.net/pomeh/mPRZR/ to show you the problem.
When you do var foo = document.getElementById("...");, this value of this inside the function is the document object.
When you do var grab = document.getElementById; var foo = grab("..."); you're executing the getElementById in a global context. In this case, the value of this inside the function is the global object, and not the document object.
I hope that's clear for you :) Look at the example and logged values.
This works:
var grab = document.getElementById.bind( document );
So, you use the bind function method to explicitly set the context for your grab function.
Live demo: http://jsfiddle.net/E2tvB/
(Note: you'll need to polyfill bind to achieve cross-browser compatibility.)
I usually use this to short my codes. And as this far, I have never found any problem with my method.
var grab=function (x){return document.getElementById(x);};
grab("par").textContent="This is textContent of paragraph AFTER changed by javascript";
<html>
<body>
<p id="par">This is textContent of paragraph BEFORE changed by javascript</p>
</body>
</html>
I am now in the process of removing most globals from my code by enclosing everything in a function, turning the globals into "pseudo globals," that are all accessible from anywhere inside that function block.
(function(){
var g = 1;
var func f1 = function () { alert (g); }
var func f2= function () { f1(); }
})();
(technically this is only for my "release version", where I append all my files together into a single file and surround them with the above....my dev version still has typically one global per js file)
This all works great except for one thing...there is one important place where I need to access some of these "globals" by string name. Previously, I could have done this:
var name = "g";
alert (window[name]);
and it did the same as
alert(g);
Now -- from inside the block -- I would like to do the same, on my pseudo-globals. But I can't, since they are no longer members of any parent object ("window"), even though are in scope.
Any way to access them by string?
Thanks...
Basically no, as answered indirectly by this question: Javascript equivalent of Python's locals()?
Your only real option would be to use eval, which is usually not a good or even safe idea, as described in this question: Why is using the JavaScript eval function a bad idea?
If the string name of those variables really and truly is defined in a safe way (e.g. not through user-input or anything), then I would recommend just using eval. Just be sure to think really long and hard about this and whether there is not perhaps a better way to do this.
You can name the function you are using to wrap the entire code.
Then set the "global" variable as a member of that function (remember functions are objects in JavaScript).
Then, you can access the variable exactly as you did before....just use the name of the function instead of "window".
It would look something like this:
var myApp = new (function myApp(){
this.g = "world";
//in the same scope
alert ( "Hello " + this["g"]);
})();
//outside
alert ( "Hello " + myApp["g"]);
if you want to access something in a global scope, you have to put something out there. in your case it's probably an object which references your closed off function.
var obj1 = new (function(){
var g = 1;
var func f1 = function () { alert (g); }
var func f2= function () { f1(); }
})();
you can add a method or property as a getter for g. if the value of g isn't constant you might do like
this.getG = function() { return g; };
you can work from there to access items by name, like
alert( obj1["getG"]() );
alert( window["obj1"]["getG"]() );
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.