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.
Related
I have a Javascript function declartions as a string (gotten from Function.toString), and I want to wrap all variable declarations with a function (also in Javascript), E.g.
const value = 42 to const value = wrapper(42).
First I thought of using RegEx to get the original values and location and then replace them with the wrapped value, but the RegEx got too complex very fast because of needing to think about things like multiline strings and objects. Using RegEx would also impact the ease of other people contributing to the project.
After that I looked into using a module for this, I found Acorn (used by Babel, Svelte. Parses the Javascript into an ESTree, the spec for Javascript Abstract Syntax Trees): https://github.com/acornjs/acorn, but I couldn't find a way of parsing the ESTree back to a Javascript function declaration after making the modifications.
Is there a way of parsing the ESTree back to a function, or another better solution?
You don't really need a function to stringify the tree back into code. Instead, take note of the offsets where the change should occur, and then don't apply the change in the tree, but to the original string.
Here is a demo with the acorn API:
function test () { // The function we want to tamper with
const value = 42, prefix = "prefix";
let x = 3;
for (let i = 0; i < 10; i++) {
x = (x * 997 + value) % 1000;
}
return prefix + " " + x;
}
function addInitWrappers(str) { // Returns an updated string
let ast = acorn.parse(str, {ecmaVersion: 2020});
function* iter(node) {
if (Object(node) !== node) return; // Primitive
if (node.type == "VariableDeclaration" && node.kind == "const") {
for (let {init} of node.declarations) {
yield init; // yield the offset where this initialisation occurs
}
}
for (let value of Object.values(node)) {
yield* iter(value);
}
}
// Inject the wrapper -- starting at the back
for (let {start, end} of [...iter(ast)].reverse()) {
str = str.slice(0, start) + "wrapper(" + str.slice(start, end) + ")" + str.slice(end);
}
return str;
}
function wrapper(value) { // A wrapper function to demo with
return value + 1;
}
console.log("before wrapping test() returns:", test());
let str = test.toString();
str = addInitWrappers(str);
eval(str); // Override the test function with its new definition
console.log("after wrapping test() returns:", test());
<script src="https://cdnjs.cloudflare.com/ajax/libs/acorn/8.7.1/acorn.min.js"></script>
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/.
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.
I have a function to generate guids for testing:
helpers.guid = function(){
var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
return guid;
};
I call it with:
var thisTest.guid1 = helpers.guid();
var thisTest.guid2 = helpers.guid();
The problem is each time I refer to thisTest.guid1 it's a different guid. I need to set the object property to a permanent value and I'm not sure how to do that. I've tried adding a closure but couldn't get it to work.
Edit: to clarify, i need to be able to generate multiple guids and assign each one to a different variable. Right now each time I refer to a variable i get a new guid as it presumably calls the function again and returns a new value. I need "guid1" and "guid2" to be the same values each time then are used.
Question title is much simpler than unnecessarily complicated code example and text with it ... Let's use much simpler code.
var seed = 1 ;
function generate () {
return seed++ ;
}
var a = generate() ;
alert(a + "\n" + a + "\n" + a ) ;
This of course shows "1" three times ... And it will, regardless of is it an object property or a variable. Return value of the function is kept in the memory because it is referenced by the variable a. Object property of course will behave the same:
var a = { b : generate() };
alert( a.b + "\n" + a.b + "\n" + a.b ) ;
This will show "1" three times again. Likewise each call to generate() will yield new value.
var a = {b:generate(), c:generate(), d:generate() };
alert( a.b + "\n" + a.c + "\n" + a.d ) ;
This will output "1", "2" and "3". Each call to function returns a value which is referenced by different object property, thus we have three different values.
If I am understanding correctly you could use 2 functions:
1 - a function to generate the GUID and then store it somewhere, like
in a hidden control somewhere on your form, so you can get it later
2- a function that retrieves the value of your hidden control.
Of these similar function definitions, what is optimal way to access arguments and why?
function DoStuff()
{
return arguments[0] + arguments[1] + arguments[2];
}
function DoStuff(first, second, third)
{
return first + second + third;
}
Does one allocate less memory than the other? Is one faster to access the parameter values than the other?
Here is my test:
function Test1()
{
var start = new Date();
for (var i = 0; i < 1000000; i++)
{
DoStuff1(i, i + 1, i + 2);
}
var done = new Date();
alert(done - start);
}
function Test2()
{
var start = new Date();
for (var i = 0; i < 1000000; i++)
{
DoStuff2(i, i + 1, i + 2);
}
var done = new Date();
alert(done - start);
}
function DoStuff1()
{
var result = arguments[0] + arguments[1] + arguments[2];
}
function DoStuff2(first, second, third)
{
var result = first + second + third;
}
Here are the results:
IE FF
Test1()
2355 402
2381 395
2368 392
Test2()
504 6
507 7
505 7
I figured that test 2 would be faster but it's drastically faster. So, not only is it more readable but it's more efficient.
Forget about performance in this case and go for readability. From that perspective, option (2) is much to be preferred -- though, I'd go for more descriptive names. ;-)
The second.
Using the second, you know based on the signature exactly what is expected when you call the method. It's also far easier for maintainability in the future.
Referencing arguments[] anywhere in a function will significantly decrease performance on many browsers.
The performance difference should be fairly negligible between the two, however the readability of named parameters is a better practice. There are times when you cannot use named parameters and in those cases I typically use a big block of script to unpack arguments into named locals.