how do I return a variable from a function and assign it to an object as a property? I wrote this code but it says that the object property is undefined
var ahoy = (function yes() {
var mp = {};
function oh() {
var greeting = "hello";
var advoir = "goodbye";
}
return {
greeting: greeting,
advoir: advoir
};
oh();
mp.greeting = greeting;
mp.advoir = advoir;
console.log(mp.greeting);
console.log(mp.advoir);
});
ahoy();
The error here arises from the fact that the ahoy function does not have access to the variables in the scope of oh.
function oh() {
var greeting = "hello";
var advoir = "goodbye";
console.log(greeting); // "hello"
}
oh();
console.log(greeting); // undefined
greeting is local to the scope of oh since it is declared inside of oh, and is thus not accessible outside of that function. Instead, this would work:
var greeting;
console.log(greeting); // undefined
function oh() {
greeting = "hello";
console.log(greeting); // "hello"
}
console.log(greeting); // undefined
oh();
console.log(greeting); // "hello"
move return statement to the bottom. define greeting outside of the oh function(define with var mp)
Instead of executing a function, you can just define the variables and return the object all at once
var ahoy = (function yes() {
return {
greeting: "hello",
advoir: "goodbye"
};
});
ahoy();
console.log(ahoy());
I can see few issues in your code:-
You are assigning "hello" to greeting and "goodbye" to advoir in function oh() and return in outside that function.
Now say even if you put return inside the function oh(), your greeting and advoir would be returned, but you are not capturing the output and thus greeting shows undefined.
You can try following:-
var ahoy = (function yes() {
function oh() {
var mp={
greeting:'greeting',
advoir:'advoir'
}
return mp;
}
mp=oh();
var greeting = mp.greeting;
var advoir = mp.advoir;
console.log(mp.greeting);
console.log(mp.advoir);
});
ahoy();
Jsfiddle link
Try this
var ahoy = (function yes() {
var mp = {};
// declare the variable outside of function oh
var greeting, advoir;
function oh() {
greeting = "hello";
advoir = "goodbye";
}
oh();
mp.greeting = greeting;
mp.advoir = advoir;
console.log(mp.greeting);
console.log(mp.advoir);
// move return statement to end of function
return {
greeting: greeting,
advoir: advoir
};
});
ahoy();
Related
My English = Google Translate. Sorry :(
function XXX(){
abc = function(){return 'Message';}
return abc;
}
function Alerttt(){
var AlertText= XXX();
alert(AlertText);
}
Result:
AlertText = function(){return 'Message';}
I want to:
AlertText = Message
How can I do?
You'll have to call the function.
function XXX() {
abc = function() {
return 'Message';
}
return abc;
}
function Alerttt() {
var AlertText = XXX();
alert(AlertText()); // call it
}
Alerttt();
You can also do var AlertText = XXX()(); so that AlertText gets the return value from the called function so you can just do alert(AlertText);
Are you looking for this?
function XXX()
{
abc = function(){return 'Message';}
return abc;
}
function Alerttt()
{
var AlertText = XXX()();
alert(AlertText);
}
Alerttt();
Calling XXX returns a function object, so XXX() is a function object, and you need to call that function object as XXX()() to return 'Message'.
Calling a function from a Object Literal
var runApp = {
init: function(){
this.validate();
},
run: function() {
var myStr = "My Name";
var abc = function()
{
return myStr;
}
},
validate: function() {
var val = this.run().abc(); // It Gives "Uncaught TypeError: Cannot call method 'abc' of undefined "
alert(val);
}
};
runApp.init();
How to Call the function abc() inside the function validate?
Function abc is defined within the scope of "run" on thus will not be accessible from another function. If you really want this, you could make "abc" available on the "this" scope.
var runApp = {
init: function(){
this.validate();
},
run: function() {
var myStr = "My Name";
this.abc = function() {
return myStr;
}
},
validate: function() {
this.run(); // run this one first so function abc exists
var val = this.abc();
alert(val);
}
}
runApp.init();
So in short: you cannot do this without modifying the code itself.
You can return abc function from run function inside an object:
run: function() {
var myStr = "My Name";
var abc = function() {
return myStr;
}
return { abc : abc };
}
and then this.run().abc() will work.
Since your run method does not return an object which contains the abc function you are not able to call it. It returns undefined instead.
One solution to this is if you return an object which has a method named abc.
I think I understand why variables exist outside of the function they were declared in, because you're returning another function:
myFunction = function() {
var closure = 'closure scope'
return function() {
return closure;
}
}
A = myFunction(); // myFunction returns a function, not a value
B = A(); // A is a function, which when run, returns:
console.log(B); // 'closure scope'
The way that it's written now, calling A() is like a getter.
Q: How can I write myFunction so that calling A(123) is a setter?
Try the following:
myFunction = function() {
var closure = 'closure scope'
// value is optional
return function(value) {
// if it will be omitted
if(arguments.length == 0) {
// the method is a getter
return closure;
} else {
// otherwise a setter
closure = value;
// with fluid interface ;)
return this;
}
}
}
A = myFunction(); // myFunction returns a function, not a value
A(123); // set value
B = A(); // A is a function, which when run, returns:
console.log(B); // '123'
You could do something like this if you want both getter and setter for example:
var func = function() {
var closure = 'foo';
return {
get: function() { return closure; },
set: function(value) { closure = value; }
}
};
var A = func();
A.set('foobar');
console.log(A.get()); //=> "foobar"
Should be as simple as:
myFunction = function() {
var closure = 'closure scope'
return function(setTo) {
if (typeof setTo !== "undefined") {
closure = setTo;
return this; //support call chaining, good idea hek2mgl
} else {
return closure;
}
}
}
Since the closure variable is within the closure of the function's scope, you should be able to assign to it the same way you can read from it.
See jsFiddle: http://jsfiddle.net/WF4VT/1/
Another alternative would be to use a class and define getters and setters:
function MyClass(p){
this._prop = p;
}
MyClass.prototype = {
constructor: MyClass,
get prop(){
return this._prop;
},
set prop(p){
this._prop = p;
}
}
var myObject = new MyClass("TEST");
console.log(myObject.prop);
myObject.prop = "test";
console.log(myObject.prop);
Demo: http://jsfiddle.net/louisbros/bMkbE/
jsFiddle Demo
Have your returned function accept an argument. Use it as a setter:
myFunction = function() {
var closure = 'closure scope';
return function(val) {
closure = val;
return closure;
}
}
A = myFunction(); // myFunction returns a function, not a value
B = A(123); // A is a function, which when run, returns:
console.log(B); // 'closure scope'
Revisiting this question, I see that I could do it this way:
function outside() {
var result = 'initialized'
return inside
function inside(argVariable) {
if(arguments.length) {
result = argVariable
return this
} else {
return result
}
}
}
myFunction = outside() // outside returns a function
X = myFunction() // returns: 'initialized'
$('body').append(X + '<br>')
myFunction(123) // setter
X = myFunction() // returns: 123
$('body').append(X)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I do this
function myFunction() {
var myVar = "I think I am encapsulated";
function getMyVar() {
return myVar;
}
}
var myProperty = myFunction;
myProperty.getMyVar(); // tells me myProperty.getMyVar is not a function.
and
function myFunction() {
var myVar = "I think I am encapsulated";
function getMyVar() {
return myVar;
}
}
var myProperty = myFunction();
myProperty.getMyVar(); // tells me myProperty is undefined
and even
function MyFunction() {
var myVar = "I think I am encapsulated";
function getMyVar() {
return myVar;
}
}
var myProperty = new MyFunction();
myProperty.getMyVar(); // tells me myProperty.getMyVar is not a function.
and in all three cases I get problems. I have included the problem as in line comment in all three sections. Now, before someone tells me to just use a closure, I am not trying to understand closures, I am trying to understand exactly what happens with inner functions.
If you can explain above, I would grateful. Because it is counter intuitive to me.
Thanks
What you did is just define a function inside myFunction, creating a closure ...
To remedy the implementation, make getMyVar an instance member:
function myFunction() {
var myVar = "I think I am encapsulated";
this.getMyVar = function () {
return myVar;
}
}
You aren't exposing the getMyVar function.
You want:
function myFunction() {
var myVar = "I think I am encapsulated";
this.getMyVar = function() {
return myVar;
}
}
However, myVar is also locally scoped to the function execution... and the funciton hasn't been executed.
The last lines need to be
(new myFunction()).getMyVar();
EDIT: Though perhaps all you're looking for is pseudo-namespacing? In which case you can do:
var myObject = {
myProperty: "value",
myFunction: function() { }
}
Or, more likely you're trying to make myVar act like a private member, in which case you can do:
var myObject = function() {
var myVar = "I think I am encapsulated";
return {
getMyVar: function() {
return myVar;
}
}
}(); //self-executing function
I've got a big Javascript project that I'm trying to refactor into pseudo-classes:
jsFiddle: http://jsfiddle.net/waitinforatrain/7T42w/
var MyNameSpace = {}
MyNameSpace.MyClass = function() {
this.doSomething = function () {
return "hello";
}
this.doSomething2 = function() {
var x = this.doSomething() + " world";
alert(x);
}
this.doSomething2(); //Works fine
$("#mydiv").click ( this.doSomething2 ); //Doesn't work
}
var class = new MyNameSpace.MyClass();
The reason the click event causes an error is that this refers to the #mydiv element.
How am I supposed to design the above so that I can access the element that was clicked but can also call doSomething()?
You need to cache the context reference and wrap the call in a closure:
var MyNameSpace = {}
MyNameSpace.MyClass = function() {
var context = this;
context.doSomething = function () {
return "hello";
}
context.doSomething2 = function() {
var x = context.doSomething() + " world";
alert(x);
}
// You can do this:
context.doSomething2();
// Or this:
$("#mydiv").click(function(e) {
context.doSomething2();
});
}
this.doSomething2 = $.proxy(function() {
var x = this.doSomething() + " world";
alert(x);
}, this);
$.proxy binds the this scope to the context variable inside said function.
Save a reference to this in the outer scope:
MyNameSpace.MyClass = function() {
var that = this;
this.doSomething = function () {
return "hello";
}
this.doSomething2 = function() {
var x = that.doSomething() + " world";
alert(x);
}
this.doSomething2(); //Works fine
$("#mydiv").click ( this.doSomething2 ); //Doesn't work
}
The function assigned to doSomething2 is said to "close over" the variables in its lexical scope and so has access to their values even once MyClass has returned. This allows us to access the doSomething method through the reference to the instance we assigned to that.