Understanding passing JS objects and return values - javascript

I'm studying some JS code and compared to other languages it's not making any sense to me.
First, there's a date object that's declared and that I understand,
$ns.constant = {
date: {}, /* Input date */
};
Then there's functions like this one below where a date is passed to a function. Here's what I don't understand. In other languages, when you pass a variable to a function, that function creates a new variable that's local to the function and the function acts upon that local variable.
This function returns date.julian. But it also adds other dates like date.j2000 and date.1950. In my understanding of other languages, those aren't being returned because they're the date object local to the function. It would seem to me that in order to put those values into the date constant you'd have to return the entire date object the function created and not just date.julian. Or, is js just seeing that date being passed and somehow knows that it's the date constant?
Is this function modifying the date constant, an object that's local to the function or what?
Thanks
$ns.julian.calc = function (date) {
var centuries;
var year;
var month;
var b = 0;
var c;
var e;
year = date.year + 4800;
if (date.year < 0) {
year += 1;
}
month = date.month;
if (month <= 2) {
month += 12;
year -= 1;
}
e = Math.floor ((306 * (month + 1)) / 10);
centuries = Math.floor (year / 100);
if (date.year <= 1582) {
if (date.year == 1582) {
if (date.month < 10) {
b = -38;
}
if (date.month > 10 || date.day >= 15) {
b = Math.floor ((centuries / 4) - centuries);
}
}
else { b = -38; }
} else {
b = Math.floor ((centuries / 4) - centuries);
}
c = Math.floor ((36525 * year) / 100);
date.julianDate = b + c + e + date.day - 32167.5;
date.julianTime = (3600.0 * date.hours + 60.0 * date.minutes + date.seconds) / 86400.0;
date.julian = date.julianDate + date.julianTime;
date.j2000 = 2000.0 + (date.julian - $const.j2000) / 365.25;
date.b1950 = 1950.0 + (date.julian - $const.b1950) / 365.25;
date.j1900 = 1900.0 + (date.julian - $const.j1900) / 365.25;
return date.julian;
};

It appears that you're passing a date "object" to your function and then adding things to it, which will make the original date passed to that function update as well, not just local to the function.
In all languages, not just javascript, objects and heap references are passed by reference, while stack variables are passed by value (a copy local to the function). An object, in any language, will be passed by reference and whatever you change on that object will also make the original object change.
That's because the "date" that you're passing is a pointer or reference to a heap location in memory where you're updating things, so when you later, outside of that function, use "date" again it's still pointing to the same heap address where you updated things. Changing the values on a heap reference will reflect in anything that's pointing to the same reference.
You might also be confused with how immutability works since you declared "date" as a constant, but you assigned that date an object. What that means is that the reference to that heap location (date) can't change, so you couldn't i.e. do date = {} since you can't reassign a new address to that pointer, however the values on that object can still change, they are not immutable, so you can do something like date.example = 'example'. I'm not aware of a data structure in JS that's recursively immutable unless you use something like https://immutable-js.com/.

Related

Snowflake UDF behaves differently while using "LIMIT"

I have created a UDF that evaluates rows. It works fine in most cases, but sometimes it acts weird. See example below. These are exactly the same query. One with "Limit" and the other without. The total record count here is 32 but I add Limit 1000 just for the example. Would you know why the these two queries behave differently?
Without Limit - Wrong Output
With Limit - Correct Output - Again total records is 32.
The function code:
create or replace function new_row_evaluator
(b varchar, m datetime, f DATETIME, t datetime )
returns string
language javascript
as '
if (typeof tmp_barcode === "undefined") {
tmp_barcode = B;
tmp_fromdate = F;
tmp_todate = T;
return "1";
}
if (tmp_barcode == B) {
if (M >= tmp_fromdate && M <= tmp_todate) {
return "0";
} else {
tmp_fromdate = F;
tmp_todate = T;
return "1";
}
} else {
tmp_barcode = B;
tmp_fromdate = F;
tmp_todate = T;
return "1";
} ';
I assume that the UDF is using some sort of global state tmp_barcode.
Global state
Snowflake usually preserves the JavaScript global state between iterations of a UDF. However, you should not rely on previous modifications to the global state being available between function calls. Additionally, you should not assume that all rows will execute within the same JavaScript environment.
a recommended pattern is to guarantee that relevant code is evaluated only once, using JavaScript’s global variable semantics. For example:
var setup = function() {
/* SETUP LOGIC */
};
if (typeof(setup_done) === "undefined") {
setup();
setup_done = true; // setting global variable to true
}
Note that this mechanism is only safe for caching the effects of code evaluation. It is not guaranteed that after an initialization the global context will be preserved for all rows, and no business logic should depend on it.

API response is returning undefined

I am making a API call that returns a JSON response of an Array with a bunch of objects. Each object has a key "dt" that is the timestamp of a specific time of day and another key of "height" which is the Ocean's predicted or past tide height at that moment in time.
I only want the current tide's height at whatever moment in time the AJAX call happens. This is the function I created in order to achieve that:
let tideApi = 'https://www.worldtides.info/api?heights&lat=45.202&lon=-123.963&key=24e4ff14-6edf-4f79-9591-e47f9e0e21e1';
$.getJSON(tideApi, function(response) {
// Create Global variable
let tideHeight = 0;
// get current time
let nowMil = new Date().getTime();
// round that time to the nearest halfhour and convert back to timestamp (JSON timestamps are set in intervals of 30 minutes)
let timeNow = Math.round(nowMil/1000/60/30) * 30 * 60 * 1000;
// set entire array to variable
let heightArray = response.heights;
// get length
len = heightArray.length
// loop through each object in height array
for (var i=0; i < len; i++) {
// if one of the objects timestamp equals current time
if (i.dt = timeNow) {
// set tide height to variable
tideHeight = i.height;
// return tide height (curretly returning undefined)
console.log("Tide Height: " + tideHeight);
return tideHeight;
} else {
console.log("Error, no time found");
}
}
// put tide height into div
$("#tideStat").append("<p>" + tideHeight + "</p>");
});
It's currently returning undefined for a reason I am struggling to figure out. Any help would be great!
API Call (Don't worry going to change after this)
Codepen
There are a few problems in your code
let timeNow = Math.round(nowMil/1000/60/30) * 30 * 60 * 1000;. Your API doesn't seem to be returning milliseconds. Remove the * 1000.
You're not accessing items from your heightArray. Rather, just checking dt and height property on i, which is an integer. So change i.dt and i.height to heightArray[i].dt and heightArray[i].height respectively.
When you use if (lhs = rhs), you're attempting to assign, not compare. So, change = to === in the if condition.
Remove return tideHeight;. I think you want break? Not sure though. Because of this line, your last jQuery related code doesn't execute.
Forked pen. Some logs commented out for better output.
Use bracket notation to reference i object of heightArray array, === operator, instead of =, which is assignment operator
if (heightArray[i].dt === timeNow) {
// do stuff
tideHeight = heightArray[i].height;
}

can be calculate some objects like [object] operator [object] in JavaScript? [duplicate]

This is the best way I can think of phrasing this question, given this JavaScript "class" definition:
var Quota = function(hours, minutes, seconds){
if (arguments.length === 3) {
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.totalMilliseconds = Math.floor((hours * 3600000)) + Math.floor((minutes * 60000)) + Math.floor((seconds * 1000));
}
else if (arguments.length === 1) {
this.totalMilliseconds = hours;
this.hours = Math.floor(this.totalMilliseconds / 3600000);
this.minutes = Math.floor((this.totalMilliseconds % 3600000) / 60000);
this.seconds = Math.floor(((this.totalMilliseconds % 3600000) % 60000) / 1000);
}
this.padL = function(val){
return (val.toString().length === 1) ? "0" + val : val;
};
this.toString = function(){
return this.padL(this.hours) + ":" + this.padL(this.minutes) + ":" + this.padL(this.seconds);
};
this.valueOf = function(){
return this.totalMilliseconds;
};
};
and the following test setup code:
var q1 = new Quota(23, 58, 50);
var q2 = new Quota(0, 1, 0);
var q3 = new Quota(0, 0, 10);
console.log("Quota 01 is " + q1.toString()); // Prints "Quota 01 is 23:58:50"
console.log("Quota 02 is " + q2.toString()); // Prints "Quota 02 is 00:01:00"
console.log("Quota 03 is " + q3.toString()); // Prints "Quota 03 is 00:00:10"
Is there any way of implicitly creating q4 as a Quota object using the addition operator as follows...
var q4 = q1 + q2 + q3;
console.log("Quota 04 is " + q4.toString()); // Prints "Quota 04 is 86400000"
rather than resorting to...
var q4 = new Quota(q1 + q2 + q3);
console.log("Quota 04 is " + q4.toString()); // Prints "Quota 04 is 24:00:00"
If not what are the best practice recommendations in this area for making custom numeric JavaScript objects composable via the arithmetic operators?
As far as I'm aware, Javascript (at least as it exists now) doesn't support operator overloading.
The best I can suggest is a class method for making new quota objects from several others. Here's a quick example of what I mean:
// define an example "class"
var NumClass = function(value){
this.value = value;
}
NumClass.prototype.toInteger = function(){
return this.value;
}
// Add a static method that creates a new object from several others
NumClass.createFromObjects = function(){
var newValue = 0;
for (var i=0; i<arguments.length; i++){
newValue += arguments[i].toInteger();
}
return new this(newValue)
}
and use it like:
var n1 = new NumClass(1);
var n2 = new NumClass(2);
var n3 = new NumClass(3);
var combined = NumClass.createFromObjects(n1, n2, n3);
Unfortunately no.
For fallbacks, if you arranged the return values, you could use method chaining
var q4 = q1.plus(p2).plus(q3);
Since everyone down voted my other answer I wanted to post proof of concept code which does in fact work as intended.
This has been tested in chrome and IE.
//Operator Overloading
var myClass = function () {
//Privates
var intValue = Number(0),
stringValue = String('');
//Publics
this.valueOf = function () {
if (this instanceof myClass) return intValue;
return stringValue;
}
this.cast = function (type, call) {
if (!type) return;
if (!call) return type.bind(this);
return call.bind(new type(this)).call(this);
}
}
//Derived class
var anotherClass = function () {
//Store the base reference
this.constructor = myClass.apply(this);
var myString = 'Test',
myInt = 1;
this.valueOf = function () {
if (this instanceof myClass) return myInt;
return myString;
}
}
//Tests
var test = new myClass(),
anotherTest = new anotherClass(),
composed = test + anotherTest,
yaComposed = test.cast(Number, function () {
return this + anotherTest
}),
yaCComposed = anotherTest.cast(Number, function () {
return this + test;
}),
t = test.cast(anotherClass, function () {
return this + anotherTest
}),
tt = anotherTest.cast(myClass, function () {
return this + test;
});
debugger;
If someone would be so kind as to give a technical explanation WHY this is not good enough I would be happy to hear it out!
Paper.js does it, for example with point addition (docs):
var point = new Point(5, 10);
var result = point + 20;
console.log(result); // {x: 25, y: 30}
But it does it using its own custom script parser.
You can implicitly convert to integer or string, your objects.
Objects are only implicitly converted if JavaScript expects a number or a string. In the former case, the conversion takes three steps:
1.- Call valueOf(). If the result is primitive (not an object) then use it and convert it to a number.
2.- Otherwise, call toString(). If the result is primitive, use it and convert it to a number.
3.- Otherwise, throw a TypeError.
Example for step 1:
3 * { valueOf: function () { return 5 } }
If JavaScript converts to string, steps 1 and 2 are swapped: toString() is tried first, valueOf() second.
http://www.2ality.com/2013/04/quirk-implicit-conversion.html
Second suggestion:
var q4 = Quota.add(q1, q2, q3);
I recently came upon this article: http://www.2ality.com/2011/12/fake-operator-overloading.html .
It describes how you can redefine the valueOf method on objects to do something like operator overloading in javascript. It seems like you can only really perform mutator operations on the objects being operated on, so it wouldn't do what you want. Its interesting nonetheless tho.
I made a script that does operator overloading in JavaScript. It wasn't straight forward to make work, so there are a few quirks though. I will cross post the caveats here from the project page, otherwise you can find the link at the bottom:
Calculation results must be passed to a new object, so instead of (p1 + p2 + p3) you have to do new point(p1 + p2 + p3), (given your user defined object is named "point").
Only +, -, * and / are supported, the fifth arithmetic opperator % is not.
Coercion to strings (""+p1) and comparisons (p1 == p2) will not work as expected. New functions should be built for these purposes if needed, like (p1.val == p2.val).
Finally the computational resources needed to calculate the answer increases quadratically with the number of terms. Therefore only 6 terms is allowed in one calculation chain per default (although this can be increased). For longer calculation chains than that, split the calculations up, like: new point(new point(p1 + p2 + p3 + p4 + p5 + p6) + new point(p7 + p8 + p9 + p10 + p11 + p12))
The Github page.
In addition to what already have been said: overriding .valueOf() may help to produce quite powerful operator overloading. In proof-of-concept Fingers.js lib you can add event listeners in .NET style:
function hi() { console.log("hi") }
function stackoverflow() { console.log("stackoverflow") }
function bye() { console.log("bye") }
on(yourButton).click += hi + stackoverflow;
on(yourButton).click -= hi - bye;
Core idea is to replace temporarily valueOf when on() is called:
const extendedValueOf = function () {
if (handlers.length >= 16) {
throw new Error("Max 16 functions can be added/removed at once using on(..) syntax");
}
handlers.push(this); // save current function
return 1 << ((handlers.length - 1) * 2); // serialize it as a number.
};
Number returned can be then de-serialized back into function using handlers array. What's more it's possible extract bit values from final value (func1 + func2 - func3) so effectively you can understand what functions where added, and what functions were removed.
You can check out source on github and play with demo here.
Complete explanation exists in this article (it's for AS3, tough since it's ecmascript it will work for JS either).
I am not sure why people continue to answer this question with no!
There is absolutely a way which I will outline with a very very small script which your don't have to be John Resig to understand...
Before I do so I will also state that in JavaScript the way your constructor would have worked is by checking for arrays or iterating the 'arguments' literal.
e.g. In my constructor of my 'class' I would iterate the arugments, determine the type of the underlying arugments and process it intelligently.
This means that if you passed an array I would iterate the arugments to find an array and then iterate the array to do further processing depending on the type the element in the array.
E.g. -> new someClass([ instanceA, instanceB, instanceC])
However you guys are seeking a more "C" style approach to operator overloading which can actually be achived contrary to populare belief.
Here is a class which I have created using MooTools which does honor operator overloading. In plain old JavaScript you would just utilize the same toString method only attach it to the prototype of instance directly.
My main reason for displaying this approach is because of the text I continually read which states this functionality is "impossible" to emulate. Nothing is impossible only sufficently difficult and I will display this below...
//////
debugger;
//Make a counter to prove I am overloading operators
var counter = 0;
//A test class with a overriden operator
var TestClass = new Class({
Implements: [Options, Events],
stringValue: 'test',
intValue: 0,
initialize: function (options) {
if (options && options instanceof TestClass) {
//Copy or compose
this.intValue += options.intValue;
this.stringValue += options.stringValue;
} else {
this.intValue = counter++;
}
},
toString: function () {
debugger;
//Make a reference to myself
var self = this;
//Determine the logic which will handle overloads for like instances
if (self instanceof TestClass) return self.intValue;
//If this is not a like instance or we do not want to overload return the string value or a default.
return self.stringValue;
}
});
//Export the class
window.TestClass = TestClass;
//make an instance
var myTest = new TestClass();
//make another instance
var other = new TestClass();
//Make a value which is composed of the two utilizing the operator overload
var composed = myTest + other;
//Make a value which is composed of a string and a single value
var stringTest = '' + myTest;
//////
The most recent display of this nomenclature was observed at XDate's documentation page:
http://arshaw.com/xdate/
In this case I believe it was actually even easer, he could have used the prototype of the Date object to achive the same.
None the less the method I have given as an example which should portray this style of utilization for others.
Edit:
I have a complete implementation here:
http://netjs.codeplex.com/
Along with other goodies.
For some limited use cases you can have operator "overloading" effects:
function MyIntyClass() {
this.valueOf = function() { return Math.random(); }
}
var a = new MyIntyClass();
var b = new MyIntyClass();
a < b
false
a + b
0.6169137847609818
[a, b].sort() // O(n^2) ?
[myClass, myClass]
function MyStringyClass() {
this.valueOf = function() { return 'abcdefg'[Math.floor(Math.random()*7)]; }
}
c = new MyStringyClass();
'Hello, ' + c + '!'
Hello, f!
The above code is free to use under the MIT license. YMMV.

How to expand javascript arithmetic operators [duplicate]

This is the best way I can think of phrasing this question, given this JavaScript "class" definition:
var Quota = function(hours, minutes, seconds){
if (arguments.length === 3) {
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.totalMilliseconds = Math.floor((hours * 3600000)) + Math.floor((minutes * 60000)) + Math.floor((seconds * 1000));
}
else if (arguments.length === 1) {
this.totalMilliseconds = hours;
this.hours = Math.floor(this.totalMilliseconds / 3600000);
this.minutes = Math.floor((this.totalMilliseconds % 3600000) / 60000);
this.seconds = Math.floor(((this.totalMilliseconds % 3600000) % 60000) / 1000);
}
this.padL = function(val){
return (val.toString().length === 1) ? "0" + val : val;
};
this.toString = function(){
return this.padL(this.hours) + ":" + this.padL(this.minutes) + ":" + this.padL(this.seconds);
};
this.valueOf = function(){
return this.totalMilliseconds;
};
};
and the following test setup code:
var q1 = new Quota(23, 58, 50);
var q2 = new Quota(0, 1, 0);
var q3 = new Quota(0, 0, 10);
console.log("Quota 01 is " + q1.toString()); // Prints "Quota 01 is 23:58:50"
console.log("Quota 02 is " + q2.toString()); // Prints "Quota 02 is 00:01:00"
console.log("Quota 03 is " + q3.toString()); // Prints "Quota 03 is 00:00:10"
Is there any way of implicitly creating q4 as a Quota object using the addition operator as follows...
var q4 = q1 + q2 + q3;
console.log("Quota 04 is " + q4.toString()); // Prints "Quota 04 is 86400000"
rather than resorting to...
var q4 = new Quota(q1 + q2 + q3);
console.log("Quota 04 is " + q4.toString()); // Prints "Quota 04 is 24:00:00"
If not what are the best practice recommendations in this area for making custom numeric JavaScript objects composable via the arithmetic operators?
As far as I'm aware, Javascript (at least as it exists now) doesn't support operator overloading.
The best I can suggest is a class method for making new quota objects from several others. Here's a quick example of what I mean:
// define an example "class"
var NumClass = function(value){
this.value = value;
}
NumClass.prototype.toInteger = function(){
return this.value;
}
// Add a static method that creates a new object from several others
NumClass.createFromObjects = function(){
var newValue = 0;
for (var i=0; i<arguments.length; i++){
newValue += arguments[i].toInteger();
}
return new this(newValue)
}
and use it like:
var n1 = new NumClass(1);
var n2 = new NumClass(2);
var n3 = new NumClass(3);
var combined = NumClass.createFromObjects(n1, n2, n3);
Unfortunately no.
For fallbacks, if you arranged the return values, you could use method chaining
var q4 = q1.plus(p2).plus(q3);
Since everyone down voted my other answer I wanted to post proof of concept code which does in fact work as intended.
This has been tested in chrome and IE.
//Operator Overloading
var myClass = function () {
//Privates
var intValue = Number(0),
stringValue = String('');
//Publics
this.valueOf = function () {
if (this instanceof myClass) return intValue;
return stringValue;
}
this.cast = function (type, call) {
if (!type) return;
if (!call) return type.bind(this);
return call.bind(new type(this)).call(this);
}
}
//Derived class
var anotherClass = function () {
//Store the base reference
this.constructor = myClass.apply(this);
var myString = 'Test',
myInt = 1;
this.valueOf = function () {
if (this instanceof myClass) return myInt;
return myString;
}
}
//Tests
var test = new myClass(),
anotherTest = new anotherClass(),
composed = test + anotherTest,
yaComposed = test.cast(Number, function () {
return this + anotherTest
}),
yaCComposed = anotherTest.cast(Number, function () {
return this + test;
}),
t = test.cast(anotherClass, function () {
return this + anotherTest
}),
tt = anotherTest.cast(myClass, function () {
return this + test;
});
debugger;
If someone would be so kind as to give a technical explanation WHY this is not good enough I would be happy to hear it out!
Paper.js does it, for example with point addition (docs):
var point = new Point(5, 10);
var result = point + 20;
console.log(result); // {x: 25, y: 30}
But it does it using its own custom script parser.
You can implicitly convert to integer or string, your objects.
Objects are only implicitly converted if JavaScript expects a number or a string. In the former case, the conversion takes three steps:
1.- Call valueOf(). If the result is primitive (not an object) then use it and convert it to a number.
2.- Otherwise, call toString(). If the result is primitive, use it and convert it to a number.
3.- Otherwise, throw a TypeError.
Example for step 1:
3 * { valueOf: function () { return 5 } }
If JavaScript converts to string, steps 1 and 2 are swapped: toString() is tried first, valueOf() second.
http://www.2ality.com/2013/04/quirk-implicit-conversion.html
Second suggestion:
var q4 = Quota.add(q1, q2, q3);
I recently came upon this article: http://www.2ality.com/2011/12/fake-operator-overloading.html .
It describes how you can redefine the valueOf method on objects to do something like operator overloading in javascript. It seems like you can only really perform mutator operations on the objects being operated on, so it wouldn't do what you want. Its interesting nonetheless tho.
I made a script that does operator overloading in JavaScript. It wasn't straight forward to make work, so there are a few quirks though. I will cross post the caveats here from the project page, otherwise you can find the link at the bottom:
Calculation results must be passed to a new object, so instead of (p1 + p2 + p3) you have to do new point(p1 + p2 + p3), (given your user defined object is named "point").
Only +, -, * and / are supported, the fifth arithmetic opperator % is not.
Coercion to strings (""+p1) and comparisons (p1 == p2) will not work as expected. New functions should be built for these purposes if needed, like (p1.val == p2.val).
Finally the computational resources needed to calculate the answer increases quadratically with the number of terms. Therefore only 6 terms is allowed in one calculation chain per default (although this can be increased). For longer calculation chains than that, split the calculations up, like: new point(new point(p1 + p2 + p3 + p4 + p5 + p6) + new point(p7 + p8 + p9 + p10 + p11 + p12))
The Github page.
In addition to what already have been said: overriding .valueOf() may help to produce quite powerful operator overloading. In proof-of-concept Fingers.js lib you can add event listeners in .NET style:
function hi() { console.log("hi") }
function stackoverflow() { console.log("stackoverflow") }
function bye() { console.log("bye") }
on(yourButton).click += hi + stackoverflow;
on(yourButton).click -= hi - bye;
Core idea is to replace temporarily valueOf when on() is called:
const extendedValueOf = function () {
if (handlers.length >= 16) {
throw new Error("Max 16 functions can be added/removed at once using on(..) syntax");
}
handlers.push(this); // save current function
return 1 << ((handlers.length - 1) * 2); // serialize it as a number.
};
Number returned can be then de-serialized back into function using handlers array. What's more it's possible extract bit values from final value (func1 + func2 - func3) so effectively you can understand what functions where added, and what functions were removed.
You can check out source on github and play with demo here.
Complete explanation exists in this article (it's for AS3, tough since it's ecmascript it will work for JS either).
I am not sure why people continue to answer this question with no!
There is absolutely a way which I will outline with a very very small script which your don't have to be John Resig to understand...
Before I do so I will also state that in JavaScript the way your constructor would have worked is by checking for arrays or iterating the 'arguments' literal.
e.g. In my constructor of my 'class' I would iterate the arugments, determine the type of the underlying arugments and process it intelligently.
This means that if you passed an array I would iterate the arugments to find an array and then iterate the array to do further processing depending on the type the element in the array.
E.g. -> new someClass([ instanceA, instanceB, instanceC])
However you guys are seeking a more "C" style approach to operator overloading which can actually be achived contrary to populare belief.
Here is a class which I have created using MooTools which does honor operator overloading. In plain old JavaScript you would just utilize the same toString method only attach it to the prototype of instance directly.
My main reason for displaying this approach is because of the text I continually read which states this functionality is "impossible" to emulate. Nothing is impossible only sufficently difficult and I will display this below...
//////
debugger;
//Make a counter to prove I am overloading operators
var counter = 0;
//A test class with a overriden operator
var TestClass = new Class({
Implements: [Options, Events],
stringValue: 'test',
intValue: 0,
initialize: function (options) {
if (options && options instanceof TestClass) {
//Copy or compose
this.intValue += options.intValue;
this.stringValue += options.stringValue;
} else {
this.intValue = counter++;
}
},
toString: function () {
debugger;
//Make a reference to myself
var self = this;
//Determine the logic which will handle overloads for like instances
if (self instanceof TestClass) return self.intValue;
//If this is not a like instance or we do not want to overload return the string value or a default.
return self.stringValue;
}
});
//Export the class
window.TestClass = TestClass;
//make an instance
var myTest = new TestClass();
//make another instance
var other = new TestClass();
//Make a value which is composed of the two utilizing the operator overload
var composed = myTest + other;
//Make a value which is composed of a string and a single value
var stringTest = '' + myTest;
//////
The most recent display of this nomenclature was observed at XDate's documentation page:
http://arshaw.com/xdate/
In this case I believe it was actually even easer, he could have used the prototype of the Date object to achive the same.
None the less the method I have given as an example which should portray this style of utilization for others.
Edit:
I have a complete implementation here:
http://netjs.codeplex.com/
Along with other goodies.
For some limited use cases you can have operator "overloading" effects:
function MyIntyClass() {
this.valueOf = function() { return Math.random(); }
}
var a = new MyIntyClass();
var b = new MyIntyClass();
a < b
false
a + b
0.6169137847609818
[a, b].sort() // O(n^2) ?
[myClass, myClass]
function MyStringyClass() {
this.valueOf = function() { return 'abcdefg'[Math.floor(Math.random()*7)]; }
}
c = new MyStringyClass();
'Hello, ' + c + '!'
Hello, f!
The above code is free to use under the MIT license. YMMV.

JavaScript function will only work once

I have a JavaScript function that is triggered onchange. What it does is take the value from a input field and then add it to the value entered in another field and then display the answer in a different field.
It works fine the first time, but when I enter a new value and leave the field there is an error: TotalPurchasePrice is not a function
function TotalPurchasePrice(BuyinPrice, TopupAmount) {
var BuyinPrice
var TopupAmount
BuyinPrice = BuyinPrice.toString().replace(/\£|\,/g, '');
TopupAmount = TopupAmount.toString().replace(/\£|\,/g, '');
TotalPurchasePrice = (BuyinPrice * 1) + (TopupAmount * 1);
document.getElementById('tTotalPurchasePrice').value = TotalPurchasePrice;
}
Can anyone tell me why this would only work once?
This line :
TotalPurchasePrice = (BuyinPrice * 1) + (TopupAmount * 1);
replaces the TotalPurchasePrice function by a number. Then it's not a function, hence the error you have.
Use a different variable name :
var totalPrice = (BuyinPrice * 1) + (TopupAmount * 1);
document.getElementById('tTotalPurchasePrice').value = totalPrice;
You could also simply have added the var keyword but it would have made the code confusing.
A way to reduce the probability of such errors is to follow best practices when naming functions and variables. Here you should have named your function as a verb to denote an action instead of a value.
You're are confusing JavaScript with VBScript here.
To return value use return keyword:
return (BuyinPrice * 1) + (TopupAmount * 1);
Then outside the function have such line:
document.getElementById('tTotalPurchasePrice').value = TotalPurchasePrice(BuyinPrice, TopupAmount);
Assigning the value of a variable inside a function without stating it with var (TotalPurchasePrice in your case) means that the variable is global.
Since you could have the function declaration written as: var TotalPurchasePrice = function(BuyinPrice, TopupAmount) {}, you are just overriding it.
You could either rename the variable inside the function or add a var statement in front of it like:
var TotalPurchasePrice = (BuyinPrice * 1) + (TopupAmount * 1);

Categories

Resources