function returning function as property - javascript

I know that it's sometimes handy to make functions return other functions so that you don't have to repeat yourself, increase modularity, etc.
But what's the point in this snippet(one of many) here from the three.js library?
Object.assign( Matrix4.prototype, {
...
applyToBufferAttribute: function () {
var v1 = new Vector3();
return function applyToBufferAttribute( attribute ) {
for ( var i = 0, l = attribute.count; i < l; i ++ ) {
v1.x = attribute.getX( i );
v1.y = attribute.getY( i );
v1.z = attribute.getZ( i );
v1.applyMatrix4( this );
attribute.setXYZ( i, v1.x, v1.y, v1.z );
}
return attribute;
};
}(),
...
} );
The 'inlined' applyToBufferAttribute doesn't get reused anywhere else.

The returned function becomes the method, yes. The purpose of wrapping it into an IIFE is to hide the v1 variable, making it what C would call "static variable": no matter how many Matrix4 objects you make, no matter how many times you invoke applyToBufferAttribute, there will be only one instance of v1, and it will not be accessible except inside the applyToBufferAttribute function.
The purpose of that, we can only guess at, but probably avoiding allocation and deallocation costs for that Vector3 object, assuming applyToBufferAttribute gets called with some frequency. Given that three.js is a WebGL library, every little bit of optimisation helps.

This is how you "hide" a variable to the outer scope.
v1 is no longer visible outside of your module and you make sure that nobody will tamper it.
Typically the return function is a closure that close over the v1 variable.
An alternative would be to make a full fledge object and make v1 readonly but you often wont bother to make such object. So it a quick handy way to encapsulate some variable.
A second alternative would be the add v1 to the return object.
function applyToBufferAttribute() {
if (!this.v1) {
this.v1 = new Vector3();
}
...
}
But this also have the issue of making v1 visible outside and make code more fragile.

Related

In which way can i pass through a method call in JavaScript class

Assume we have some classes A and B:
Class A {
constructor(a) {
this.a = a;
};
showInfo() {
console.log(this.a)
};
};
Class B {
constructor(b) {
this.b = b;
};
printText() {
console.log('its B!');
};
};
Then we create an instance of B like this:
const objB = new B(
new A(3)
);
So now we have objB with its own method inside - printText, and we surely can call it.
But what if i want somehow when calling not existing method in objB to make it pass through to encapsulated A class in there and look for invoking this method on him, like this: objB.showInfo() - to give me 3 here ?
Same story, but at this time i want when calling not existing method on A to make it pass through to B outside (like that printText)?
P.S. Don't wanna use super() and inheritance, just composition and wrapping objects, hope you've got the point.
Just a little warning at the start: this might make your program harder to debug, and it also might be a little complicated for something like this. As others have suggested, you should probably investigate other options which may be simpler and also less in the way of everything else your code does.
Here's the code which provides the functionality:
function makeGetProxy(t){
return new Proxy(t, {
get(obj,prop){
if(prop in t){
return t[prop];
}else{
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var val = t[keys[i]];
if(prop in val){
return val[prop];
// what about a recursive function?
}
}
return undefined;
}
}
});
}
And one itty bitty change to your constructor in B:
class B {
constructor(b) {
this.b = b;
return makeGetProxy(this);
};
printText() {
console.log('its B!');
};
};
If you want, you can also do the same to A.
Let's slow down. What just happened? I'll explain.
Since the properties we might request don't already exist, we're going to have to use a getter (see resources) to properly send back the value required. But, since we don't know the property names, we need a Proxy (see resources) to have a "catch-all" kind of get method.
The proxy will check if the property requested prop already exists, and if so, returns it. If it doesn't exist, it checks all of your properties' properties (all of the sub-properties).
The first result it gets, it returns it. This might cause unexpected bugs in your program. If it doesn't find it, it simply returns undefined.
Then, the proxy is generalized into a function for reuse in multiple classes (as you requested).
So, this can get the properties of a class and the properties of a class' properties, but if you need to go further (with your C class that doesn't exist yet), you can use a recursive function. I currently don't have the implementation for that recursive function, but in my head it would comprise mostly of a modified version of the else block in the makeGetProxy function.
Again, be careful with this code. It might get in the way of other things and cause unnecessary difficulty in debugging.
Resources:
Getters (MDN)
Proxy (MDN)
I borrowed some code from this answer and got the Proxy idea from this answer.

getting the name of a variable through an anonymous function

Is it possible to find the name of an anonymous function?
e.g. trying to find a way to alert either anonyFu or findMe in this code http://jsfiddle.net/L5F5N/1/
function namedFu(){
alert(arguments.callee);
alert(arguments.callee.name);
alert(arguments.callee.caller);
alert(arguments.caller);
alert(arguments.name);
}
var anonyFu = function() {
alert(arguments.callee);
alert(arguments.callee.name);
alert(arguments.callee.caller);
alert(arguments.caller);
alert(arguments.name);
}
var findMe= function(){
namedFu();
anonyFu();
}
findMe();
This is for some internal testing, so it doesn't need to be cross-browser. In fact, I'd be happy even if I had to install a plugin.
You can identify any property of a function from inside it, programmatically, even an unnamed anonymous function, by using arguments.callee. So you can identify the function with this simple trick:
Whenever you're making a function, assign it some property that you can use to identify it later.
For example, always make a property called id:
var fubar = function() {
this.id = "fubar";
//the stuff the function normally does, here
console.log(arguments.callee.id);
}
arguments.callee is the function, itself, so any property of that function can be accessed like id above, even one you assign yourself.
Callee is officially deprecated, but still works in almost all browsers, and there are certain circumstances in which there is still no substitute. You just can't use it in "strict mode".
You can alternatively, of course, name the anonymous function, like:
var fubar = function foobar() {
//the stuff the function normally does, here
console.log(arguments.callee.name);
}
But that's less elegant, obviously, since you can't (in this case) name it fubar in both spots; I had to make the actual name foobar.
If all of your functions have comments describing them, you can even grab that, like this:
var fubar = function() {
/*
fubar is effed up beyond all recognition
this returns some value or other that is described here
*/
//the stuff the function normally does, here
console.log(arguments.callee.toString().substr(0, 128);
}
Note that you can also use argument.callee.caller to access the function that called the current function. This lets you access the name (or properties, like id or the comment in the text) of the function from outside of it.
The reason you would do this is that you want to find out what called the function in question. This is a likely reason for you to be wanting to find this info programmatically, in the first place.
So if one of the fubar() examples above called this following function:
var kludge = function() {
console.log(arguments.callee.caller.id); // return "fubar" with the first version above
console.log(arguments.callee.caller.name); // return "foobar" in the second version above
console.log(arguments.callee.caller.toString().substr(0, 128);
/* that last one would return the first 128 characters in the third example,
which would happen to include the name in the comment.
Obviously, this is to be used only in a desperate case,
as it doesn't give you a concise value you can count on using)
*/
}
Doubt it's possible the way you've got it. For starters, if you added a line
var referenceFu = anonyFu;
which of those names would you expect to be able to log? They're both just references.
However – assuming you have the ability to change the code – this is valid javascript:
var anonyFu = function notActuallyAnonymous() {
console.log(arguments.callee.name);
}
which would log "notActuallyAnonymous". So you could just add names to all the anonymous functions you're interested in checking, without breaking your code.
Not sure that's helpful, but it's all I got.
I will add that if you know in which object that function is then you can add code - to that object or generally to objects prototype - that will get a key name basing on value.
Object.prototype.getKeyByValue = function( value ) {
for( var prop in this ) {
if( this.hasOwnProperty( prop ) ) {
if( this[ prop ] === value )
return prop;
}
}
}
And then you can use
THAT.getKeyByValue(arguments.callee.caller);
Used this approach once for debugging with performance testing involved in project where most of functions are in one object.
Didn't want to name all functions nor double names in code by any other mean, needed to calculate time of each function running - so did this plus pushing times on stack on function start and popping on end.
Why? To add very little code to each function and same for each of them to make measurements and calls list on console. It's temporary ofc.
THAT._TT = [];
THAT._TS = function () {
THAT._TT.push(performance.now());
}
THAT._TE = function () {
var tt = performance.now() - THAT._TT.pop();
var txt = THAT.getKeyByValue(arguments.callee.caller);
console.log('['+tt+'] -> '+txt);
};
THAT.some_function = function (x,y,z) {
THAT._TS();
// ... normal function job
THAT._TE();
}
THAT.some_other_function = function (a,b,c) {
THAT._TS();
// ... normal function job
THAT._TE();
}
Not very useful but maybe it will help someone with similar problem in similar circumstances.
arguments.callee it's deprecated, as MDN states:
You should avoid using arguments.callee() and just give every function
(expression) a name.
In other words:
[1,2,3].forEach(function foo() {
// you can call `foo` here for recursion
})
If what you want is to have a name for an anonymous function assigned to a variable, let's say you're debugging your code and you want to track the name of this function, then you can just name it twice, this is a common pattern:
var foo = function foo() { ... }
Except the evaling case specified in the MDN docs, I can't think of any other case where you'd want to use arguments.callee.
No. By definition, an anonymous function has no name. Yet, if you wanted to ask for function expressions: Yes, you can name them.
And no, it is not possible to get the name of a variable (which references the function) during runtime.

Confused about JavaScript prototypal inheritance with constructors

I've read pages and pages about JavaScript prototypal inheritance, but I haven't found anything that addresses using constructors that involve validation. I've managed to get this constructor to work but I know it's not ideal, i.e. it's not taking advantage of prototypal inheritance:
function Card(value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
}
var card1 = new Card();
var card2 = new Card();
var card3 = new Card();
This results in three Card objects with random values. However, the way I understand it is that each time I create a new Card object this way, it is copying the constructor code. I should instead use prototypal inheritance, but this doesn't work:
function Card(value) {
this.value = value;
}
Object.defineProperty( Card, "value", {
set: function (value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
}
});
This doesn't work either:
Card.prototype.setValue = function (value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
};
For one thing, I can no longer call new Card(). Instead, I have to call var card1 = new Card(); card1.setValue(); This seems very inefficient and ugly to me. But the real problem is it sets the value property of each Card object to the same value. Help!
Edit
Per Bergi's suggestion, I've modified the code as follows:
function Card(value) {
this.setValue(value);
}
Card.prototype.setValue = function (value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
};
var card1 = new Card();
var card2 = new Card();
var card3 = new Card();
This results in three Card objects with random values, which is great, and I can call the setValue method later on. It doesn't seem to transfer when I try to extend the class though:
function SpecialCard(suit, value) {
Card.call(this, value);
this.suit = suit;
}
var specialCard1 = new SpecialCard("Club");
var specialCard2 = new SpecialCard("Diamond");
var specialCard3 = new SpecialCard("Spade");
I get the error this.setValue is not a function now.
Edit 2
This seems to work:
function SpecialCard(suit, value) {
Card.call(this, value);
this.suit = suit;
}
SpecialCard.prototype = Object.create(Card.prototype);
SpecialCard.prototype.constructor = SpecialCard;
Is this a good way to do it?
Final Edit!
Thanks to Bergi and Norguard, I finally landed on this implementation:
function Card(value) {
this.setValue = function (val) {
if (!isNumber(val)) {
val = Math.floor(Math.random() * 14) + 2;
}
this.value = val;
};
this.setValue(value);
}
function SpecialCard(suit, value) {
Card.call(this, value);
this.suit = suit;
}
Bergi helped me identify why I wasn't able to inherit the prototype chain, and Norguard explained why it's better not to muck with the prototype chain at all. I like this approach because the code is cleaner and easier to understand.
the way I understand it is that each time I create a new Card object this way, it is copying the constructor code
No, it is executing it. No problems, and your constructor works perfect - this is how it should look like.
Problems will only arise when you create values. Each invocation of a function creates its own set of values, e.g. private variables (you don't have any). They usually get garbage collected, unless you create another special value, a privileged method, which is an exposed function that holds a reference to the scope it lives in. And yes, every object has its own "copy" of such functions, which is why you should push everything that does not access private variables to the prototype.
Object.defineProperty( Card, "value", ...
Wait, no. Here you define a property on the constructor, the function Card. This is not what you want. You could call this code on instances, yes, but note that when evaluating this.value = value; it would recursively call itself.
Card.prototype.setValue = function(){ ... }
This looks good. You could need this method on Card objects when you are going to use the validation code later on, for example when changing the value of a Card instance (I don't think so, but I don't know?).
but then I can no longer call new Card()
Oh, surely you can. The method is inherited by all Card instances, and that includes the one on which the constructor is applied (this). You can easily call it from there, so declare your constructor like this:
function Card(val) {
this.setValue(val);
}
Card.prototype...
It doesn't seem to transfer when I try to extend the class though.
Yes, it does not. Calling the constructor function does not set up the prototype chain. With the new keyword the object with its inheritance is instantiated, then the constructor is applied. With your code, SpecialCards inherit from the SpecialCard.prototype object (which itself inherits from the default Object prototype). Now, we could either just set it to the same object as normal cards, or let it inherit from that one.
SpecialCard.prototype = Card.prototype;
So now every instance inherits from the same object. That means, SpecialCards will have no special methods (from the prototype) that normal Cards don't have... Also, the instanceof operator won't work correctly any more.
So, there is a better solution. Let the SpecialCards prototype object inherit from Card.prototype! This can be done by using Object.create (not supported by all browsers, you might need a workaround), which is designed to do exactly this job:
SpecialCard.prototype = Object.create(Card.prototype, {
constructor: {value:SpecialCard}
});
SpecialCard.prototype.specialMethod = ... // now possible
In terms of the constructor, each card IS getting its own, unique copy of any methods defined inside of the constructor:
this.doStuffToMyPrivateVars = function () { };
or
var doStuffAsAPrivateFunction = function () {};
The reason they get their own unique copies is because only unique copies of functions, instantiated at the same time as the object itself, are going to have access to the enclosed values.
By putting them in the prototype chain, you:
Limit them to one copy (unless manually-overridden per-instance, after creation)
Remove the method's ability to access ANY private variables
Make it really easy to frustrate friends and family by changing prototype methods/properties on EVERY instance, mid-program.
The reality of the matter is that unless you're planning on making a game that runs on old Blackberries or an ancient iPod Touch, you don't have to worry too much about the extra overhead of the enclosed functions.
Also, in day-to-day JS programming, the extra security from properly-encapsulated objects, plus the extra benefit of the module/revealing-module patterns and sandboxing with closures VASTLY OUTWEIGHS the cost of having redundant copies of methods attached to functions.
Also, if you're really, truly that concerned, you might do to look at Entity/System patterns, where entities are pretty much just data-objects (with their own unique get/set methods, if privacy is needed)... ...and each of those entities of a particular kind is registered to a system which is custom made for that entity/component-type.
IE: You'd have a Card-Entity to define each card in a deck.
Each card has a CardValueComponent, a CardWorldPositionComponent, a CardRenderableComponent, a CardClickableComponent, et cetera.
CardWorldPositionComponent = { x : 238, y : 600 };
Each of those components is then registered to a system:
CardWorldPositionSystem.register(this.c_worldPos);
Each system holds ALL of the methods which would normally be run on the values stored in the component.
The systems (and not the components) will chat back and forth, as needed to send data back and forth, between components shared by the same entity (ie: the Ace of Spade's position/value/image might be queried from different systems so that everybody's kept up to date).
Then instead of updating each object -- traditionally it would be something like:
Game.Update = function (timestamp) { forEach(cards, function (card) { card.update(timestamp); }); };
Game.Draw = function (timestamp, renderer) { forEach(cards, function (card) { card.draw(renderer); }); };
Now it's more like:
CardValuesUpdate();
CardImagesUpdate();
CardPositionsUpdate();
RenderCardsToScreen();
Where inside of the traditional Update, each item takes care of its own Input-handling/Movement/Model-Updating/Spritesheet-Animation/AI/et cetera, you're updating each subsystem one after another, and each subsystem is going through each entity which has a registered component in that subsystem, one after another.
So there's a smaller memory-footprint on the number of unique functions.
But it's a very different universe in terms of thinking about how to do it.

JavaScript function offsetLeft - slow to return value (mainly IE9)

I've had a hard time debugging a news ticker - which I wrote from scratch using JavaScript.
It works fine on most browsers apart from IE9 (and some mobile browsers - Opera Mobile) where it is moving very slowly.
Using Developer Tools > Profiler enabled me to find the root cause of the problem.
It's a call to offsetLeft to determine whether to rotate the ticker i.e. 1st element becomes the last element.
function NeedsRotating() {
var ul = GetList();
if (!ul) {
return false;
}
var li = GetListItem(ul, 1);
if (!li) {
return false;
}
if (li.offsetLeft > ul.offsetLeft) {
return false;
}
return true;
}
function MoveLeft(px) {
var ul = GetList();
if (!ul) {
return false;
}
var li = GetListItem(ul, 0);
if (!li) {
return false;
}
var m = li.style.marginLeft;
var n = 0;
if (m.length != 0) {
n = parseInt(m);
}
n -= px;
li.style.marginLeft = n + "px";
li.style.zoom = "1";
return true;
}
It seems to be taking over 300ms to return the value, whereas the ticker is suppose to be moving left 1 pixel every 10ms.
Is there a known fix for this?
Thanks
DOM operations
I agree with #samccone that if GetList() and GetListItem() are performing DOM operations each time, you should try to save references to the elements retrieved by those calls as much as possible and reduce the DOM operations.
then I can just manipulate that variable and hopefully it won't go out of sync with the "real" value by calling offsetLeft.
You'll just be storing a reference to the DOM element in a variable. Since it's a reference, it is the real value. It is the same exact object. E.g.:
var li = ul.getElementsByTagName( "li" )[ index ];
That stores a reference to the DOM object. You can read offsetLeft from that object anytime, without performing another DOM operation (like getElementsByTagName) to retrieve the object.
On the other hand, the following would just store the value and would not stay in sync:
var offsetLeft = ul.getElementsByTagName( "li" )[ index ].offsetLeft;
offsetLeft
If offsetLeft really is a bottleneck, is it possible you could rework this to just read it a lot less? In this case, each time you rotate out the first item could you read offsetLeft once for the new first item, then just decrement that value in each call to MoveLeft() until it reaches 0 (or whatever)? E.g.
function MoveLeft( px ) {
current_offset -= px;
If you want to get even more aggressive about avoiding offsetLeft, maybe you could do something where you read the width of each list item once, and the offsetLeft of the first item once, then just use those values to determine when to rotate, without ever calling offsetLeft again.
Global Variables
I think I get it... so elms["foo"] would have to be a global variable?
I think really I just need to use global variables instead of calling offsetLeft every 10 ms.
You don't need to use global variables, and in fact you should avoid it -- it's bad design. There are at least a couple of good approaches you could take without using global variables:
You can wrap your whole program in a closure:
( function () {
var elements = {};
function NeedsRotating() {
...
}
function example() {
// The follow var declaration will block access
// to the outer `elements`
var elements;
}
// Rest of your code here
} )();
There elements is scoped to the anonymous function that contains it. It's not a global variable and won't be visible outside the anonymous function. It will be visible to any code, including functions (such as NeedsRotating() in this case), within the anonymous function, as long as you don't declare a variable of the same name in your inner functions.
You can encapsulate everything in an object:
( function () {
var ticker = {};
ticker.elements = {};
// Assign a method to a property of `ticker`
ticker.NeedsRotating = function () {
// All methods called on `ticker` can access its
// props (e.g. `elements`) via `this`
var ul = this.elements.list;
var li = this.elements.list_item;
// Example of calling another method on `ticker`
this.do_something();
} ;
// Rest of your code here
// Something like this maybe
ticker.start();
} )();
Here I've wrapped everything in an anonymous function again so that even ticker is not a global variable.
Response to Comments
First of all, regarding setTimeout, you're better off doing this:
t = setTimeout( TickerLoop, i );
rather than:
t = setTimeout("TickerLoop();", i);
In JS, functions are first-class objects, so you can pass the actual function object as an argument to setTimeout, instead of passing a string, which is like using eval.
You may want to consider setInterval instead of setTimeout.
Because surely any code executed in setTimeout would be out of scope of the closure?
That's actually not the case. The closure is formed when the function is defined. So calling the function via setTimeout does not interfere with the function's access to the closed variables. Here is a simple demo snippet:
( function () {
var offset = 100;
var whatever = function () {
console.log( offset );
};
setTimeout( whatever, 10 );
} )();
setTimeout will, however, interfere with the binding of this in your methods, which will be an issue if you encapsulate everything in an object. The following will not work:
( function () {
var ticker = {};
ticker.offset = 100;
ticker.whatever = function () {
console.log( this.offset );
};
setTimeout( ticker.whatever, 10 );
} )();
Inside ticker.whatever, this would not refer to ticker. However, here you can use an anonymous function to form a closure to solve the problem:
setTimeout( function () { ticker.whatever(); }, 10 );
Should I store it in a class variable i.e. var ticker.SecondLiOffsetLeft = GetListItem(ul, 1).offsetLeft then I would only have to call offsetLeft again when I rotate the list.
I think that's the best alternative to a global variable?
The key things are:
Access offsetLeft once each time you rotate the list.
If you store the list items in a variable, you can access their offsetLeft property without having to repeatedly perform DOM operations like getElementsByTagName() to get the list objects.
The variable in #2 can either be an object property, if you wrap everything up in an object, or just a variable that is accessible to your functions via their closure scope. I'd probably wrap this up in an object.
I updated the "DOM operations" section to clarify that if you store the reference to the DOM object, it will be the exact same object. You don't want to store offsetLeft directly, as that would just be storing the value and it wouldn't stay in sync.
However you decide to store them (e.g. object property or variable), you should probably retrieve all of the li objects once and store them in an array-like structure. E.g.
this.li = ul.getElementsByTagName( "li" );
Each time you rotate, indicate the current item somehow, e.g.:
this.current_item = ###;
// or
this.li.current = this.li[ ### ];
// Then
this.li[ this.current_item ].offsetLeft
// or
this.li.current.offsetLeft
Or if you want you could store the li objects in an array and do this for each rotation:
this.li.push( this.li.shift() );
// then
this.li[0].offsetLeft
if you dont cache your selectors in var li = GetListItem(ul, 1);
then performance will suffer greatly.. and that is what you are seeing because you are firing up a new selector every 10ms
you should cache the selector in a hash like
elms["foo"] = elms["foo"] || selectElm(foo);
elms["foo"].actionHere(...)
your code is slow because reading offsetLeft will force the browser to do a reflow. the reflow is the part that is slowing you down. the browser is typically smart enough to queue changes to reduce the number of reflows. however, given that you want the most up to date value when access offsetLeft, you're forcing the browser to flush that queue and do a reflow in order to calculate the correct value for you.
without knowing all the details of what you're trying to do, it's hard to know what to recommend to improve performance. http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/ explains this problem in more detail and offers some advice about minimizing reflows.

Check whether function result value is used

I was wondering whether it is possible to check whether a function is called in such a way that its return value is stored in a variable, or that it is called 'standalone'.
In the first case, the function should indeed return something, but otherwise it should save the value(s) to the current instance of my object.
To be specific, I have a Vector3D as follows:
function Vector3D(x, y, z) {
this.x = parseNumber(x);
this.y = parseNumber(y);
this.z = parseNumber(z);
}
Vector3D.prototype.add = function(that) {
return new Vector3D(
this.x + that.x,
this.y + that.y,
this.z + that.z
);
};
As can be seen, the add function returns something based on the object instance itself and on another instance. As it is now, the function must be called in a way like this:
var addedVector = vect1.add(vect2);
However, if I were to call it like this:
vect1.add(vect2);
it should not return anything (that's quite useless), but instead store the return coordinates (x, y and z) in the variables of vect1. So vect1 should become what is called addedVector in the other line of code.
To accomplish this, I guess I'm going to need to know whether the function is called alone or that its return value is stored.
Is there any way to accomplish this?
You could pretty easily break this apart into two functions, add(vector) and add_m(vector).
The second function (add_m) would mutate vector 1 and add the values of vector 2 to it and return nothing, whereas the first would make a new vector that is the result and return it.
I'm reasonably sure what you're describing is impossible. Even if it were, though, You'd probably not want to do it that way. Compare your code with a small variation:
var addedVector = vect1.add(vect2);
vect1.add(vect2);
var addedVector = eval("vect1.add(vect2)");
eval("vect1.add(vect2)");
I'm pretty sure that you'd like the lines with the evals to work the same as the ones without, right? Yet eval() trivially has to "use" the return value so it can propagate it outside.
Now, what I'd do is write any of the following functions that I happened to need:
v1.add(v2); // returns (v1+v2), v1 and v2 are unchanged
v1.addFrom(v2) // v1 = v1 + v2, v2 is unchanged, returns undefined
v1.addTo(v2) // v2 = v1 + v2, v1 is unchanged, returns undefined
depending on the usage, I might or might not have addTo/addFrom return the result.
There's no way to know how your caller has called your method, i.e. whether your caller has assigned the return value to a variable or not.
Nope. No way to do that, the function body is completely independent from the code context it's called in. Sounds like you want two separate functions, one to add in place and one to add and return a new value.
You cannot find that out. How about letting the function accept two parameters?
If only one is passed, you add it to the vector the function is called on.
If two are passed, you create a new one and sum them.
Something like:
Vector3D.prototype.add = function(vec1, vec2) {
var target = vec2 ? new Vector3D(0,0,0) : this;
vec1 = vec2 ? vec1 : this;
vec2 = vec2 || vec1;
target.x = vec1.x + vec2.x;
target.y = vec1.y + vec2.y;
target.z = vec1.z + vec2.z;
return target;
}
Then you can call it with:
v1.add(v2); // adds v2 to v1
or
var addedVector = v1.add(v1, v2); // creates a new vector v1 + v2
But I agree that it is probably better to create two separate functions. A function should only do one thing.

Categories