javascript get function results outside of function - javascript

$(document)/ready(function(){
if (this == that) {
var myobject = {};
var variable = 55;
function dothisandthat(variable);
alert(JSON.stringify(myobject));
}
})
function dothisandthat(variable) {
//Do something
myobject["first"] = variable + 5;
myobject("second") = variable + 10;
}
How can i get myobject to be used in my function, and then call the object outside of the function again?

It can be globally available if you just do myobject = {} or window.myobject = {}, or even $.myobject = {}. Attach it to some global object like window, or since you are using JQuery, the JQuery $ object, and then you can use that throughout.
Or as #Pointy said, just add the parameter to the method:
function dothisandthat(variable, myObject) {

Well, with an object oriented approach, you would usually tell the object to modify it's internal state, which solves your scoping problems at the same time.
function MyObject() {
this.first = 0;
this.second = 0;
}
MyObject.prototype.doThisAndThat = function (variable) {
this.first = variable + 5;
this.second = variable + 10;
};
$(document).ready(function () {
//...
var myObject = new MyObject();
myObject.doThisAndThat(55);
alert(JSON.stringify(myObject));
//...
});
However, if you want to use a functional approach (data and behavior lives separately) you must make myObject available in the doThisAndThat's scope. There are a few ways to do this:
Pass the object as an argument to the function. That's usually the way I prefer since it makes dependencies explicit.
Please note that a pure functional approach would not mutate the object passed-in to the function, but would return a modified copy of the object since data structures are usually immutable.
Rely on a closure. In this case, you would simply have to move the doThisAndThat function declaration inside the document ready callback.
Rely on global variables or well-know objects. I would avoid this solution most of the time since it makes your dependencies hidden and your code harder to test.

Related

Function argument instead of direct ref

I feel weird about this question.
Somehow I feel the answer should be quite obvious. Yet it isn't.
In Java Script, considering that inside another object's scope I can directly access a variable in any surrounding scope and mutate the crap out of it. Why would I choose to pass those variable as arguments to a function instead of referencing directly? What's the best practice? When would one choose to pass something as arguments instead of using the direct reference method? Is it just a matter of if I want a reference to the actual var or just its value, analogous to the kind of system employed in the C-family of languages?
For example:
Why would I do this:
var foo= 1;
var bar = function(foo) {
return foo + 2;
}
Instead of:
var foo = 1;
var bar = function() {
return foo + 2;
}
This makes a bit sense:
var bar = function(foo) {
return foo + 2;
}
foo = bar(42); // foo = 44
The use depends on the type of problem you want to solve
The global range variables are dealt with when the value can be reused in other operations
let Person = (() => {
let Person = function() {
this.name = null;
}
/**
* You can also occupy private variables so that you
* can not access them externally to your logic
*/
let privateVariable = null;
Person.prototype = {
setName: (name) => {
this.name = name;
}, getName: () => {
return this.name;
}
}
return Person;
})();
// Use:
person = new Person();
person.setName('Alan');
console.log(person.getName()); // log: Alan
On the other hand there are when you occupy variables of local scope
The local range variables are dealt with when you will not occupy that value in subsequent operations. It is a very common use in libraries
let Library = (() => {
/*
* When dealing with this type of programming all the logic
* of your program falls into the functions but when
* you use an anonymous function like this
* you can define variables to support you
*
**/
let CONSTANT = 2;
return {
operation1: (param1) => {
return param1 * 2;
},
operation2: (param1) => {
return param1 * CONSTANT;
}
}
})();
// Use:
let result = Library.operation1(42);
console.log(result); // 84
I hope this works for you, regards
I can directly access a variable in any surrounding scope and mutate the crap out of it.
Yes, and that's one of the things one wants to protect against.
Why would I choose to pass those variable as arguments to a function instead of referencing directly?
Reusability, basically. By passing the value explicitly, one can a) also pass other values than that of the variable in scope b) easily refactor the code by putting the function declaration in a different scope, without having to rewrite it.
Also, dependency injection: even when you expect the variable to be a constant that you want to reference, making it a parameter allows injecting mocks etc.
What's the best practice?
To choose wisely :-) The above advantages of putting everything in parameters are met by the disadvantage of having everything in parameters - long parameter lists and having to pass everything around have quite some overhead. So when you don't absolutely need to reuse the function, and don't need to inject any other values (e.g. in case of a given constant), there's no reason to do it.

Javascript Class properties and methods work differently

I have been working with javascript for a while and always used this notation to create objects
var className = (function() {
var property = 1; //Example of a property
var method = function () {
//Example of a method
};
});
but now I have a project where I use AngularJs and the javascript don't recognize it. I can use this one
var className = (function() {
this.property = 1; //Example of a property
this.method = function() {
//Example of a method
};
});
Is there any reason for the first one not working? In my experience I prefer the first one better
[Edit]
var className = (function() {
var property = 1; //Example of a property
var method = function () {
//Example of a method
};
})();
var className = (function() {
var property = 1; //Example of a property
var method = function () {
//Example of a method
};
});
In this example you're not actually creating anything that surmounts to a property and/or method. You're simply assigning a function to the variable className, and within that function you're creating two more variables. Variables are function-scoped, and by definition, won't be visible outside the function.
If you use AngularJS, then there are different scopes and understanding of OOP. You should probably must know $scope which is the scope for Angular objects, methods etc. Please check the documentation, also read more about Angular scopes.
In your case, you should have this code in some controller or service (factory, directive) and have something like this:
angular.module('myapp', [])
.controller('MyCtrl', ['$scope', function($scope) {
$scope.myvar = 'hello';
$scope.mymethod = function() {
console.log($scope.myvar);
};
}])
Those 2 examples do 2 very different things.
In the first, you're not actually creating any properties on the newly created object when calling className(). Anything declared using var in a function is just a locally-scoped value to that function, meaning you can't access it once you leave that function.
The second will actually create the properties property and method on the newly created object. However, when defining constructor functions it's much more common to do it like this:
function ClassName() {
this.property = 'some property value'
}
Constructor functions are typically capitalized, but this is just a style guide thing.
And then define member functions on the constructor's prototype like this:
ClassName.prototype.method = function() {
// function body where "this" refers to an instance of ClassName
}
Then you can use the constructor like this:
var someObject = new ClassName()
To understand this behavior, you need to understand how JavaScript handles scope.
The only scope within JavaScript is function scope. To understand what this means, consider the other types of scope you see in other programming languages, such as loops, classes, and if-else statements. When you create a variable within a scope, it can not be accessed outside that scope.
Because the only JavaScript scope is function scope, these two methods are functionally identical:
function myFunc(){
var x = 5; // variable declared outside loops
for(var i = 0; i < x; i++){ // iterator variable declared in loop params
var y = i; // variable declared inside a loop
for(var i = 10; i > 6; i--){
var z = i; // variable declared inside another loop
}
}
}
function myFunc(){
var x, i, y, z; // all variables declared at beginning of function
x = 5;
for(i = 0; i < x; i++){
y = i;
for(i = 10; i > 6; i--){
z = i;
}
}
}
Notice that in JavaScript, it's a logic error to use the same iterator variable in for loops in the same scope, since they will refer to the same variable (there's no "loop scope" to distinguish them).
On the other hand, function scope can be used to prevent variable names from colliding, since variables can't be accessed outside their scope.
Notice in the example below we have two different variables named x. They are different because they exist in different function scopes.
var x = "Outer Scope";
(function(){
var x = "Inner Scope";
alert(x); // output: "Inner Scope"
})();
alert(x); // output: "Outer Scope"
There's no way for the outer scope to access the value of x in the inner scope.
That brings us to the JavaScript way of creating object-like syntax.
In your first example, the variables property and method cannot be accessed outside of the "constructor" or "class definition" (or whatever you want to call the function you'll use to create objects) because they're wrapped up in a function scope. You can practically think of them as private members.
In your second example, you're using the this keyword to attach the variables as attributes of the object returned by your "constructor". The object attributes can be accessed by code outside the function scope. Think of them as public members.
If it helps put things into an object-oriented frame of reference, you can even use that syntax to provide getters and setters (accessors and mutators), like so.
var className = function() {
var property = 1;
this.getProperty = function(){return property;};
this.setProperty = function(value){property = value;};
};
var obj = new className();
obj.getProperty(); // 1
obj.setProperty(200);
obj.getProperty(); // 200
typeof(obj.property); // "undefined"
The getProperty() and setProperty() functions are able to access the property because they were defined within the same function scope; to understand this more clearly, look up "closures."
From a performance perspective, you may not want to have many functions defined in your "class definition" as above, since that results in each instance of the object having its own copy of the function (which increases the amount of memory each object requires). Instead, you can attach methods to the prototype of the function, so the methods are defined once.
className.prototype.getDouble = function(){return this.getProperty()*2;};
obj.getDouble(); // 400
A big thing to note is that prototype functions are also bound by function scope, so they can't access variables that you defined in the "class definition."
className.prototype.getTriple = function(){return property*3;};
obj.getTriple(); // ERROR: "'property' is undefined"

How to use scope in JavaScript for Function constructor?

If I were to make a new function using the Function constructor, how could I give it a non-temporary scope to access besides window (meaning the scope only has to be evaluated once, not every time the function is called)? The purpose is to construct multiple variables that require some pretty costly calculations, and I don't want to reconstruct them every time the function is called, but I also don't want to store them in window. Any ideas?
You could bind your function to the specific context using bind keyword:
var context = {};
var f = new Function("args", "return this").bind(context);
f(); // context
Since bind is defined in ECMA 5th, it may not be present in all browsers, here's a workaround
For the above described purpose, you use static functions. You cannot prevent scope from being evaluated at every call, because this is the way JavaScript works, but you can speed it up by not having window in the scoping chain.
var namespace = {};
namespace.someMethod = function() {
// do something here.
};
Now anywhere in your code, you can call that method by using namespace.someMethod();. Just be careful. The above is a static method. You can call it without instantiating. But you MUST NOT use this.property inside a static function. It is a potentially very dangerous operation, as it may give an extension access to the global object and basically un-restricted permissions.
And the above is a static JavaScript method. It does not have window in the scoping chain.
Here's how to create a constructor using the same pattern. When you want to use a constructor, you always instantiate before using. For that you have the new keyword.
var namespace = {};
namespace.coordinate = function(x, y) {
this.x = x;
this.y = y;
};
namespace.coordinate.prototype.addCoordinates = function() {
return this.x + this.y;
};
Now anywhere in your code you can do:
var coordinateObject = new namespace.coordinate(5,10);
// you have created a new instance.
alert(coordinateObject.addCoordinates());// will alert 15;
// now you can make as many as you want. They will behave as instances.
// This means they do not interfere with each other in any way.
// They just have the same properties and methods, but the instance values
// Can be entirely different.
var secondCoordinateObject = new namespace.coordinate(10, 25);
alert(secondCoordinateObject.addCoordinates());// will output 35.
You have successufully created an instance of your namespace.coordinate class. Using the pattern I gave you, you can replicate almost the entire functionality of Java or C or any other Object Oriented language.
var yourNamespace = {
func1: function() {
},
func2: function() {
}
};
...
yourNamespace.func1();
you can call the function that you want by calling the function from name space like this yourNamespace.func1();
The ever-growing method of creating, storing, hiding, revealing, and grouping variables & functions is through the magic of "closures", Javascript's most powerful and yet unsung feature:
var groupObj = (function (setUp) {
// maintained by reference, hidden
var _priVar = setUp * 2;
// maintained by reference, revealed (through returned object)
var _pubVar = 8;
var _pubFunc = function (x) {
_priVar += x;
_pubVar += x;
}
var lostVar = setUp * 99; // not referenced, hidden, so evaporates!
return {
'pubVar' : _pubVar,
'pubFunc' : _pubFunc
}
}(4)); // runs immediately with 4 as setUp, revealing pubVar & pubFunc
Then...
groupObj.pubFunc(7); // runs public function, adds 7 to both variables
alert('public variable: ' + groupObj.pubVar); // alerts public variable
A closure occurs whenever there is a function inside of another function. A variable inside of the outter function will be maintained so long as it is referenced by the inner function, kind of a "no-mans land" where a variable is forced to exist by a reference to it from a lower scope, but is hidden from the higher scope due to the innate principles of Javascript.
There are a few other ways to use closures, replacing the object constructor, one-off conflict-free private functions, and more. There are many posts here about them.

Namespaces in JavaScript: do I need to rewrite all my variable and function references?

I am namespacing some JavaScript code, and I want to know if I have rewritten all my function calls and references to global variables correctly. The current code is this:
var x = 10;
function foo() {
console.log('foo');
bar();
},
function bar() {
console.log('bar', x);
}
foo();
I have rewritten it as follows:
var namespace = {
x : 10,
foo: function() {
console.log('foo');
// Is this the correct way to call bar?
this.bar();
},
bar: function() {
// Is this the correct way to refer to x?
console.log('bar', this.x);
}
};
namespace.foo();
Is this correct, i.e. do I need to rewrite all function calls (EDIT: by which I mean all inside the namespace variable) to this.functionname() and all global variables to this.variablename?
If you like, you can make yourself some "real" private variables and methods by incorporating a closure. I favour the module pattern.
var ns = (function () {
var x = 10;
return {
foo: function () {
console.log('foo');
this.bar();
},
bar: function () {
console.log('bar', x);
},
increment: function () {
x++;
}
}
}());
ns.foo();
ns.increment();
ns.foo();
http://jsfiddle.net/DjYue/
No, in some places (code that calls those functions from outside of your namespace object) you would have to call namespace.foo(), namespace.bar(), namespace.varName
Actually, if you use namespace.bar() from the function in the object itself, you get the added benefit that your functions don't depend on context. That is, the following code doesn't work with what you have
var fun = namespace.foo;
fun(); // This would break, since the this value is going to be the global object
I usually don't like to use this from literal objects because of the problem mentioned above. It's definitely a preference, I just prefer to avoid problems with this
No, you shouldn't rewrite to this.funcname() but rather namespace.funcname(). The this keyword is reserved to refer to the current context object (or whatever it's called), meaning that you'd use it within your "namespaced" code to refer to the namespace object.
And generally, it's good to know that you aren't actually working with namespaces as you'd know it from more classical OOP. JavaScript is a prototype-based language, which means that you don't have namespaces - rather, what you're creating is an object containing several properties and methods. As previously mentioned, when you're working with methods of the object, the this keyword refers to the object itself. You'd need a reference to the object when outside of it's context.
Currently, the approach of using objects to contain all of your code as a sort of namespaces and classes in disguise is diminishing in favor of closures which attaches the methods and properties that should be publicly available to a function (which, in JavaScript, is a first class object), and either returns that function or attaches it to the global object. You may also, alternatively, use a function to contain the properties and methods instead of an object.
I disagree with the people who say No to your question. It really depends on what you want to accomplish here. Based the rewritten code, I don't see anything wrong with it. As long as you call namespace.foo(), the execution context of each function should be namespace. Thus, it is not wrong to use this.
There is a situation that invoking the function foo() will not work:
var foo1 = namespace.foo;
foo1();
Although foo1 is same as the function namespace.foo, foo1's execution context has changed. this will refer to window, not namespace.
Their is no need to rewrite that much because you can have more than one reference to a function - a private and a public one.
var namespace = (function() {
var ns = {}; // the 'namespace'
var x = 10;
var foo = // 'private' reference: bar();
ns.foo = // 'public' reference: ns.bar() -> namespace.bar();
function foo() { // the name is optional because it's a function expression
console.log('foo');
bar();
}; // don't forget the semicolon
var bar =
ns.bar =
function() {
console.log('bar', x);
};
return ns; // return the 'namespace'
})();
namespace.foo();
var foo = namespace.foo;
foo();
delete namespace.bar;
// namespace.bar(); // Error
foo(); // bar is called

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