Javascript: Assign Function To A Variable Fills Variable With Undefined
It's kinda basic, but its giving me some headaches:
I'm assigning a function to a variable, then I call a function inside the first function from the variable.
When I assign the function to the variable its filled with undefined, so when I call the inner function I get the error:
Uncaught TypeError: Cannot read property 'add' of undefined
This is the code I'm working on:
(function () {
function Sum() {
this.result = 0;
this.getCurrentSum = function getCurrentSum() {
return this.result;
}
this.add = function add(add_number) {
this.result += add_number;
}
}
var s1 = Sum(); // here s1 is undefined
var s2 = Sum(); // here s2 is undefined
s1.add(10); // here cannot execute add of undefined crash
s1.add(20);
s2.add(30);
s2.add(5);
// must print 30
console.log(s1.getCurrentSum());
// must print 35
console.log(s2.getCurrentSum());
}());
I can change the code in the Sum function, but I can't change the rest of the code
Answer
It looks like you want Sum
to be a constructor function. You call constructor functions via new
, not directly. So:
var s1 = new Sum();
var s2 = new Sum();
The reason you were getting undefined
in s1
and s2
without new
is that Sum
doesn't do return x
anywhere, so the result of calling it is the value undefined
. But when you use new
, the result of the new
expression is the object that was created.
FWIW, there's another problem with Sum
: You're missing out this.
in a couple of places (also a couple of semicolons, though Automatic Semicolon Insertion will add them for you):
function Sum() {
this.result = 0;
this.getCurrentSum = function getCurrentSum() {
return this.result;
// −−−−−−−−^^^^^
};
this.add = function add(add_number) {
this.result += add_number;
// −^^^^^
};
}
JavaScript isn't like Java or C#, this.
isn't optional.
In a comment you've asked:
wat if I can change the Sum function or anything inside the function but I can't change the var s1 = Sum();calling?
In that case, you'd make Sum
a builder function and have it return an object, like this:
function Sum() {
return {
result: 0,
getCurrentSum: function getCurrentSum() {
return this.result;
},
add: function add(add_number) {
this.result += add_number;
}
};
}
Live Example:
(function () {
function Sum() {
return {
result: 0,
getCurrentSum: function getCurrentSum() {
return this.result;
},
add: function add(add_number) {
this.result += add_number;
}
};
}
var s1 = Sum(); // here s1 is undefined
var s2 = Sum(); // here s2 is undefined
s1.add(10); // here cannot execute add of undefined crash
s1.add(20);
s2.add(30);
s2.add(5);
// must print 30
console.log(s1.getCurrentSum());
// must print 35
console.log(s2.getCurrentSum());
})();
Normally a builder function wouldn't start with a capital letter (that's essentially reserved for constructor functions), so it would have a name like createSum
or buildSum
or similar.
That version of Sum
is written with ES5-level syntax (actually it's even ES3-level). In ES2015+ it could be a bit more concise:
// ES2015+ using method syntax
function Sum() {
return {
result: 0,
getCurrentSum() {
return this.result;
},
add(add_number) {
this.result += add_number;
}
};
}
Live Example:
(function () {
// ES2015+ using method syntax
function Sum() {
return {
result: 0,
getCurrentSum() {
return this.result;
},
add(add_number) {
this.result += add_number;
}
};
}
var s1 = Sum(); // here s1 is undefined
var s2 = Sum(); // here s2 is undefined
s1.add(10); // here cannot execute add of undefined crash
s1.add(20);
s2.add(30);
s2.add(5);
// must print 30
console.log(s1.getCurrentSum());
// must print 35
console.log(s2.getCurrentSum());
})();
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM