Check whether function result value is used - javascript

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.

Related

Is it good practice to override function parameter value?

In JavaScript consider I am trying to append a new value and return it.
I have below example regarding overriding parameter value
The below function receives a string value as param and overriding the param with new value and returning it.
function test(value) {
value = value + "hi";
return value;
}
console.log(test("Hello"));
The below function receives a string value as param. I would like to append a new value and return it. So I assigned value to a local variable and then appended strong to a new variable and returning it.
function test(value) {
let temp = value;
temp = value + "hi";
return temp;
}
console.log(test("Hello"));
I am calling it and passing value
test(“Hello”);
Which one is recommended from above?
It's purely a matter of style. Some people think you should leave parameter values alone, others think it's fine to change them.¹
From a practical perspective, it doesn't cause any harm. That is, there is no hidden side-effect to doing so. In particular, since JavaScript is purely pass-by-value, reassigning the parameter can't have any effect on whatever argument was used to fill in that parameter:
function test(value) {
value = value + "hi";
return value;
}
let a = "let's say ";
let b = test(a);
console.log(b); // "let's say hi"
console.log(a === b); // false, `a` was not modified
Your version with temp can be simpler, though:
function test(value) {
let temp = value + "hi";
return temp;
}
(or even
function test(value) {
return value + "hi";
}
but I figure it's highly simplified for the question.)
¹ (I happen to be in the latter camp, but that's neither here nor there.)
Yes, this is not at all wrong and is often done by many programmers across many languages. It is a common practice.
You can use it in cases where you want to use the parameter value inside the function but after making certain modifications to it.
For example, I might want to add two numbers using a function add(a, b) where a and b can be strings or integers or floats.
But just to be sure about it, I can define the add function in the following way:
function add(a,b) {
a = parseFloat(a);
b = parseFloat(b);
return a + b;
}
and this is perfectly fine. This way I can be always sure that there will be no exceptions thrown or in case parameters were passed as strings, it doesn't returns 12 (if I said add(1,2)) when really it should have been 3.
By making parameter overriding a common practice and incorporating it into your coding style, you spare the browser from creating or defining new variables just to modify those variable values. This might not mean much in small applications, but in large scale heavy applications, it might make a noticeable difference especially on low end devices.
The short answer is: it's only a matter of style.
However, this isn't always right. When passing objects, they will be passed by reference, meaning that every change you'll make to the parameter will affect the original object:
const obj = {originalValue: true};
function modifyObject(input) {
input.originalValue = false; // The change happens here
return input; // So it will take place regardless of this line
}
console.log('before:', obj);
modifyObject(obj); // See? we don't even retrieve the return value
console.log('after:', obj);
If we were talking about Java, then creating a new variable would be good practice. As there is something called the Garbage Collector that collects unused variables, etc. and discards them. So keeping a link to the original variable wouldn't allow the collector to discard the variable. (I read this somewhere, but some people said to me it doesn't really work this way, so read more about this online if you want)
In JavaScript, however, it doesn't really matter. It depends on you. Your style. It also depends on the situation as it can be useful sometimes. But really it doesn't really matter. Do as you like.
If you want to simplify it you can do as #T.JCrowder said:
function test(value){
return value+ “hi”;
}
That's about it.
Using ES6 Template literals
function test(value){
return `${value} hi`;
}

how to create a swapping function in jquery

i basically want to swap the content of 2 variables using a function either in jquery or javascript. and i cont have a bias against any method.(it won't make difference using a temporary variable or not using it)
I tried this in javascript
function swap(x,y){
x = x + y;
y = x - y;
x = x - y;
return x,y
}
var two = 1;
var one= 2;
swap (one,two);
document.write(one);
There are a few errors in your code. It seems like you are not familiar with how datastructures and variable/functions work in Javascript. I strongly recommend you learn about them first.
Your swap function takes 2 arguments x and y and does some mathematical operations on it which would swap the values. Here, you are making the assumption that the variables will always be a number or a type of variable where addition and subtraction would make sense. Unless you can assure that variables will always be numbers, this is the wrong approach.
Similarly, your return statement is return x, y. You cannot return 2 variables from a function. Output from a function is a single value. In this case, since you need 2 variables to be returned, you should use a composite structure like an array / object.
The value returned from this function needs to be stored in appropriate variables so that you can use them. Line number 10 in your code calls the method, but does not store its return value anywhere.
Generic solution for your use case will be as follows
// Create two variables
let x = 1, y = 2;
function swap(x, y) {
// Return the 2 variables in swapped order
return [y, x]
};
// Call the swap function and assign the return values back to the variables
[x, y] = swap(x, y);
// Print to console to verify
console.log(x, y);
You don't need to do any addition or subtraction in the function; you can simply return y and then x. However, note that you can't return two values at once from a function -- you'll need to return then as an array (that optionally gets converted to a string), if you want to return them both at the same time.
function swap(x, y) {
return [y, x].toString();
}
console.log(swap(1, 2));

function returning function as property

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.

Trying to understand this function as value

I got this code from the Headfirst Javascript book. I changed the function names to be clearer. I'm trying to wrap my head around this.
I assigned add to the function outer with a number. That number remains for some reason - returns a reference to inner with n = num (which returns the added values?
Anytime I change outers n value, the inner will use that new value?
I believe I'm right on that. Is there anywhere I can read more about it? See better examples? Or can anyone explain this better?
function outer(n) {
var inner = function(x) { //or x = 0
return n + (x || 0); //added default 0 for testing to prevent NaN
}
return inner;
}
var num = 2;
var add = outer(num);
console.log(`Adding 2 to num(${num}): ${add(2)}`);
add = outer(5);
console.log(add());
console.log(add(2));
In JavaScript, functions can act as regular data. If you are OK with the idea of passing a number or string around, then passing a function around is no different. This allows you the ability to do some very cool and powerful things.
Here, instead of the add function simply giving you your numeric answer, it's giving you back a function with your number embedded into it. This means that add doesn't really add anything, add is a function for creating functions (similar to the idea of a "Factory" in class based programming).
Changing the names may make things easier:
function createAddFunction(numberThatWillBeHardWiredIntoReturnedFunction) {
var resultingFunction= function(x) { //or x = 0
return numberThatWillBeHardWiredIntoReturnedFunction + (x || 0);
}
return resultingFunction;
}
var num = 2;
// This will cause add to be a function that is hard-wired to add 2 to another number
var add = createAddFunction(num);
console.log(`Adding 2 to num(${num}): ${add(2)}`);
// This will cause add to be a function that is hard-wired to add 5 to another number
add = createAddFunction(5);
console.log(add());
console.log(add(2));
Let's rename the functions to make it even clearer. The outer function takes a parameter and uses it to create a new function. This new function is returned for future use.
function createFunctionThatAdds(n){
var adds_n = function(x) { return n + (x || 0); };
return adds_n;
}
var adds_2 = createFunctionThatAdds(2);
var adds_5 = createFunctionThatAdds(5);
console.log(adds_2(10));
console.log(adds_5(10));
The technique used is called currying. It's part of functional javascript.
You can read more about it here.
The idea behind it is that you can use a function to generate another function, which you can use further in your code.
Currying is made possible, because of a closure.
There are a lot of libraries that are built based on that principe, for example Ramda.

refering to a method without creating an instance first / map a method with jQuery or any javascript map function

I have this:
var Coords = function(x, y){
this.x = x;
this.y = y;
}
Coords.prototype.toArray = function(){
return [this.x, this.y];
}
Now I have an array of Coords object. I'd like to convert each Coords instance into an array with the toArray method.
I could write a loop, but I'd rather use $.map, as it's shorter and more readable.
Unfortunately, this:
return $.map(coords_array, Coords.prototype.toArray);
doesn't work at all. It just stops the execution.
The problem might be about how to refer to a method independently of any object.
Any way of pointing to a method without creating an instance first?
Or to use $.map with a method?
Thanks for your insights.
EDIT: well, in fact, it doesn't stop the execution (this came from another problem) but $.map(coords_array, Coords.prototype.toArray); returns [null, null, null, null, null...].
I find this behavior strange.
Try something like:
return $.map(coords_array, function(val, i) { val.toArray(); });
And refer here for more reference on jQuery's map function.
Apparently, $.map does not set the context (this) to the element currently being processed (like e.g. $.each does).
You can either go with a wrapper:
$.map(coords_array, function(coord) { return coord.toArray(); });
or extend the toArray() method to also work with the first argument:
Coords.prototype.toArray = function() {
var self = this instanceof Coords ? this : arguments[0];
return [self.x, self.y];
}
The reason that:
> $.map(coords_array, Coords.prototype.toArray);
doesn't work as expected is that you are passing a reference to the function to map, so when it's called, its this keyword isn't set to the instance and defaults to the global obejct (or undefined in ES5 strict mode). You should be able to do:
$.map(coords_array, function(item, index) {
Coords.prototype.toArray.call(item);
});
so that the function's this is set to the instance.
Edit
See Jordan's answer.

Categories