Functions With Global Inputs Return NaN - javascript

Edit:
I wanted to be more specific about why I'm doing it this way. The code below is something I've been attempting to get working.
function newClass(self) {
this.invest;
this.interest;
function method1() {
return this.invest + this.interest;
}
}
var newC = new newClass();
newC.invest = prompt("Enter investment");
newC.interest = prompt("Enter interest");
alert(newC.method1());
End Of Edit:
I'm fairly new to the javascript language and can not figure out why my functions are always returning NaN. I have attempted many different fixes but nothing I have tried works. Below is an example.
function investment() {
var iniInvest;
var interest;
return iniInvest + interest;
}
investment.iniInvest = 10;
investment.interest = 20;
console.log(investment())
This returns a NaN. I have attempted creating classes and methods and attempted to parse the variables but they still all return NaN.
Unless the variables values are assigned to the var in the function
var iniInvest = 10;
or args are given
function investment(args1, args2) {
return args1 + args2;
}
console.log(investment(10, 20));
it will return NaN.
I appreciate the help.

You cannot access the variable inside functions like
investment.iniInvest = 10;
investment.interest = 20;
Since, you need that variables globally accessed so you can keep that variables outside the function and initialize them from anywhere in the code:
var iniInvest;
var interest;
function investment() {
return iniInvest + interest;
}
iniInvest = 10;
interest = 20;
console.log(investment())

The code investment.iniInvest = 10; is creating an iniInvest property on investment, not a local variable. This code does not modify the variable var iniInvest created within the function's scope.
function investment() {
return investment.iniInvest + investment.interest;
}
investment.iniInvest = 10;
investment.interest = 20;
console.log(investment())
This code achieves what you are asking, but this is not a good way to solve the problem.
The following is more likely what you are looking for:
function investment( iniInvest, interest) {
this.iniInvest = iniInvest;
this.interest = interest;
this.investment = function() {
return this.iniInvest + this.interest;
};
}
var inv = new investment( 10, 30 );
console.log( inv.investment() );
inv.iniInvest = 5;
inv.interest = 10;
console.log( inv.investment() );

As you are declaring iniInvest interest in function so you can not use that variable out of that function as they are out of scope. Make that variable global.
You can go through https://www.w3schools.com/js/js_scope.asp for scope of variables.

The problem is that when you declare a variable inside of a function, it exists only within that function, and is only local. Therefore, it can not be referenced from outside of the function.
In the example that you gave, you attempt to reference the variable investment.iniInvest and investment.interest, but those variables only exist within the local reference of the investment function, and are destroyed after the function ends, so you can not reference them. You're probably better off using args anyways.

You can try something like
var investment = function () {
this.iniInvest;
this.interest;
this.sum = function() {
return this.iniInvest + this.interest;
}
}
var i = new investment()
i.iniInvest = 10;
i.interest = 20;
console.log(i.sum());

Thanks everyone for all your answers! After reading everyones answer I was able to fix my syntax and resolve the problem.
This is my finished code.
function newClass() {
this.invest;
this.interest;
this.investment = function() {
return parseFloat(this.invest) + parseFloat(this.interest);
}
}
var newC = new newClass();
newC.invest = prompt("Enter investment");
newC.interest = prompt("Enter interest");
alert(newC.investment());
It returns the proper answer. Please do let me know if this code requires fixing.
Thanks Again!

Related

Equivalent of interfaces in javascript

I have a function object in javascript called BlinkyTextBox Inside of that I have 2 Shape objects that act as scroll buttons. I need a something very simple to happen which is just increment or decrement a variable called scrollY.
I tried it with an anonymous inner function, but the function couldn't recognize the member variables. Now I tried it with a member function, but it doesn't work with that either...
Here are both samples of what I am talking about.
function BlinkyTextBox(textdata, font, w, h)
{
this.scrollY = -50;
this.scrollBarYTop = new Button();
this.scrollBarYTop.callFunction = this.scrollUp;
this.scrollBarYBottom = new Button();
this.scrollBarYBottom.callFunction = function()
{
this.scrollY -= 10;
}
}
BlinkyTextBox.prototype.scrollUp = function()
{
this.scrollY += 10;
}
The problem here is that once you assign a function to another object the this inside that function will refer to the new object instead of the object the function came from.
For example:
var a = {
message : 'Hello!',
say : function () { return this.message }
}
var b = {
message : 'Goodbye'
}
b.say = a.say;
console.log(a.say()); // Hello!
console.log(b.say()); // Goodbye
Notice that we didn't do anything to the function say(). We just assigned it to b and it now print's the message from b instead of a.
Now, let's look at your code:
this.scrollBarYBottom.callFunction = function()
{
this.scrollY -= 10; // refers to scrollBarYBottom.scrollY
// not BlinkyTextBox.scrollY
}
Same thing happens to the other method:
this.scrollBarYTop.callFunction = this.scrollUp;
// the this inside scrollUp will now refer to scrollBarYTop
Traditionally, to fix this you'd use an alias for this:
var myself = this;
this.scrollBarYBottom.callFunction = function()
{
myself.scrollY -= 10;
}
But with ES5 you can use the .bind() method:
this.scrollBarYBottom.callFunction = (function()
{
this.scrollY -= 10;
}).bind(this);
and:
this.scrollBarYTop.callFunction = this.scrollUp.bind(this);
Refer to this answer for a more detailed explanation of this: How does the "this" keyword in Javascript act within an object literal?

How do I wrap a javascript function with dynamic arguments?

I'd like to wrap some dynamically created javascript functions, similar to Daniel's accepted answer here:
How do I store javascript functions in a queue for them to be executed eventually
// Function wrapping code.
// fn - reference to function.
// context - what you want "this" to be.
// params - array of parameters to pass to function.
var wrapFunction = function(fn, context, params) {
return function() {
fn.apply(context, params);
};
}
The difference is I'd like the argument values to be dynamic at time of execution - is it possible to pass a reference to a variable in the arguments, which could be updated after it is wrapped?
Here's what I'd like to do:
// I have a function to be wrapped
var sayStuff = function(a,b) {
console.log(a);
console.log(b);
}
// Variables I'd like to pass
var randomNumberA = 0;
var randomNumberB = 0;
// Wrap the function
var fun = wrapFunction(sayStuff, this, [*reference randomNumberA*,*reference randomNumberB*]);
// variables get changed
randomNumberA = Math.random()*100;
randomNumberB = Math.random()*100;
// Execute the function using current values of randomNumberA & randomNumberB
fun();
If possible I'd like to do this without changing sayStuff, I have a lot of existing functions like this I'm hoping to wrap, which also get used outside of the wrapping, so ideally I'd like to not replace the arguments with an object.
Hope that makes sense, Thanks!
If the function and the variable will be created in the same scope you can just use that:
var randomNumber = 0;
var fun = function(){ alert(randomNumber); }
randomNumber = 10;
// Now this will alert 10, because when fun is executed
// JS looks in his scope to find what randomNumber is.
fun();
This happens because functions in javascript works as Closures, they carry their environment with them. See: https://en.wikipedia.org/wiki/Closure_(computer_programming)
So if randomNumber will be changed out of the scope where you bind that function, you need to use an object, this is because in javascript we don't have "pointers" or references to pass by. One way is using a object.
function giveMeAFunction(){
var params = { randomNumber: 0 }
var fun = function(){ alert(scope.randomNumber); }
return {fun: fun, scope: scope};
}
var paramsAndFun = giveMeAFunction()
// Now you can change the variables in the scope and call the function
paramsAndFun.params.randomNumber = 10;
paramsAndFun.fun(); // Will alert 10
// Now if you replace the entire params object it will not work
// This is because you will replacing it with a new object while
// The one that is referenced in the scope where fun was created is
// the old one.
paramsAndFun.params = { randomNumber: 15 };
paramsAndFun.fun(); // will still alert 10
Now let's get to binding part of the problem.
There is already Function.prototype.bind function to help you with that.
For example:
var sayStuff = function(opts) {
alert(otions.randomNumber);
}
var options = { randomNumber: 0 };
var fun = sayStuff.bind(this, options);
options.randomNumber = 10;
fun(); // Will print 10
There is a lot going on here. Sorry if I made everything confuse.
If the dynamic arguments are defined in the context argument, a solution can be based passing the name of the variables and then, at execution time, calculate its current value:
var wrapFunction = function(fn, context) {
var xArg = arguments;
return function() {
var argsArray = [];
for (var i = 2; i < xArg.length; i++) {
argsArray.push(context[xArg[i]]);
}
fn.apply(context, argsArray);
};
}
var sayStuff = function() {
for (var i = 0; i < arguments.length; i++) {
console.log('sayStuff func: ' + arguments[i]);
}
}
var randomNumber1 = 0;
var randomNumber2 = 0;
var fun = wrapFunction(sayStuff, this, 'randomNumber1', 'randomNumber2');
randomNumber1 = Math.random()*100;
randomNumber2 = Math.random()*100;
console.log('randomNumber1: ' + randomNumber1);
console.log('randomNumber2: ' + randomNumber2);
fun();

`this` is undefined when calling method from another context

This is my first time creating OOP for JS. I followed some tutorials but I can't wrap my head around this issue. I know the problem, but i dont know the solution
function NewApp(name){
this.name = name;
this.currentPage = 1;
this.customObjectWithMethods = //init with options and so on
}
NewApp.prototype.logic = function(){
// Note 1.
var app = this
//Note 3.
this.customObjectWithMethods.method{
if(app.currentpage < 3)
// Note 2.
app.navigate(app.logic)
}
}
NewApp.prototype.navigate = function(sender){
var app = this;
this.customObjectWithMethods.method{
app.currentpage++;
this.method(function() {
return app.currentPage === 2;
}, sender(), this.terminate);
}
}
Note 1: I need to create a reference because after that, this doesn't
work anymore to refer to the current object.
Note 2: After the check I want to do some logic in another method and repeat the current function, but when the function runs again it breaks on the method (this.customObjectWithMethods) because this doesn't exists.
Note 3: This is where it breaks because "this" works the first time not the second time.
It gets very complicated like this with the this-keyword, which makes me think that my design may be flawed.
Is there any solution for this problem, or should I refactor it ?
Surely it will become complicated, thiskeyword doesn't always refer to the main object but to the scope where it is used, take a look at Scope and this in JavaScript for further information.
This is your way to go, make a variable that contains your constructor and add these two methods to this variable, after that you can call your functions:
var newApp = function newApp(name){
this.name = name;
this.currentPage = 1;
//Make a reference to your object here
var THIS = this;
this.logic = function(){
var sender = this;
THIS.customObjectWithMethods.method = function(){
if(THIS.currentpage < 3)
THIS.navigate(sender);
}
}
this.navigate = function(sender){
this.customObjectWithMethods.method = function(){
THIS.currentpage++;
this.method(function() {
return THIS.currentPage === 2;
}, sender(), this.terminate);
}
}
}
And this is how to use your constructor and its methods:
var app = newApp("Test");
//Call the first method
app.customObjectWithMethods();
//Thenn call the second one
app.logic();
Some syntax errors & style issues - here is a short correction
var myFunction = function(){
//code here
};
var mySecondFunction = function(){
//code here
};
function NewApp(name){
this.name = name;
this.currentPage = 1;
this.customObjectWithMethods = function(){}; //empty function so calling doesnt resolve in error
}
NewApp.prototype.logic = function(){
this.customObjectWithMethods.method = mySecondFunction.bind(this);
}
NewApp.prototype.navigate = function(sender){
this.customObjectWithMethods.method = myFunction.bind(this);
}
I have moved the 2 functions outside of the constructor Function so they dont get recreated every time you call the constructor functions.
with _.bind(this) the "this"-reference gets passed into the scope of your functions (i think this is more pretty than creating another var).
with
var reff = new NewApp('namename');
you can get started calling your functions now:
ref.logic();
maybe this approach works for you?

How to access a variable within a function

How do I access a variable that is defined within a function like this:
var functionVar = function(){
this.var = 1;
}
console.log(functionVar().var); //MH - obviously this doesn't work, but I'm looking for the command that will log that variable
You can access like this,
var functionVar = function(){
this.var = 1;
}
var o = new functionVar();
alert(o.var)​
a new will do the trick.
var functionVar = function(){
this.var = 1;
}
console.log(new functionVar().var);
Though not sure what you are trying to achieve by using this code.

Calling a function by a string in JavaScript and staying in scope

I've been playing around and searching a bit, but I can't figure this out. I have a pseudo private function within a JavaScript object that needs to get called via eval (because the name of the function is built dynamically). However, the function is hidden from the global scope by a closure and I cannot figure out how to reference it using eval().
Ex:
var myObject = function(){
var privateFunctionNeedsToBeCalled = function() {
alert('gets here');
};
return {
publicFunction: function(firstPart, SecondPart) {
var functionCallString = firstPart + secondPart + '()';
eval(functionCallString);
}
}
}();
myObject.publicFunction('privateFunctionNeeds', 'ToBeCalled');
I know the example looks silly but I wanted to keep it simple. Any ideas?
The string passed to eval() is evaluated in that eval()'s scope, so you could do
return {
publicFunction: function(firstPart, SecondPart) {
var captured_privateFunctionNeedsToBeCalled = privateFunctionNeedsToBeCalled;
var functionCallString = 'captured_' + firstPart + secondPart + '()';
eval(functionCallString);
}
}
However, a better solution would be to avoid the use of eval() entirely:
var myObject = function(){
var functions = {};
functions['privateFunctionNeedsToBeCalled'] = function() {
alert('gets here');
};
return {
publicFunction: function(firstPart, secondPart) {
functions[firstPart+secondPart]();
}
}
}();
myObject.publicFunction('privateFunctionNeeds', 'ToBeCalled');

Categories

Resources