assign value to function parameter, is it safe to reuse function arguments? - javascript

Is it a bad practice to reuse function parameter variables?
const reformat = (phone)=>{
phone = phone.replace("-", ",")
//... more operation using phone
return phone;
}
is there any reason such reusage should be avoided? or is it always safe to continue such usage?

For strings, like in your example, it's fine. Some people may think it could get confusing if you're trying to debug and log that variable to the console sometime after it's been changed, but that's mostly subjective. Use your best judgement.
For objects, which are always passed by reference, you should avoid making changes in the function because those changes will still be present outside the function as well.
E.G.:
var myObject = {
message: "Hello, world"
};
function alertMessage(msgObj){
msgObj.message = "Hello moto";
alert(msgObj.message);
}
alertMessage(myObject);
// The object has changed.
console.log(myObject);

No it's not. And it's memory saving sometimes, since when you use another new variable, it will take up your memory. And the function process is much longer many transformations then it will be not a good practice to do. So according to your questions,
Yes, you can use the same variable inside the function (But make sure to consider what are the types that you refer when passing as arguments)
Re-usage should be avoided when you are using a object and that will change the content of the origin object.

different cases to take care:
// argument is not a reference ( string, numbers )
function add_5(num)
{
num += 5
return num
}
let initial_num = 10
let returned_num = add_5(initial_num )
console.log( `initial_num-> ${initial_num}, returned_num-> ${returned_num}`)
// argument is reference ( objects )
function directArgObj( obj)
{
obj.num += 5
}
let initial_obj = { num: 10, abc:'xyz' }
directArgObj(initial_obj )
console.log( `initial_obj-> ${JSON.stringify(initial_obj)} `)

Related

Correct Syntax For Using The Returned Variable From A Function?

I have a function that returns a variable, I'd just like to know what's the correct syntax for doing something (such as doing math or writing a new variable using that returned variable.
Example Function:
function exampleFunction(number) {
var data_filter = number + number;
return data_filter;
}
The function returns data_filter, and I'd like to know what's the correct syntax for doing something with it, such as inputting it in another function.
What you have here is fine.
As one of the comment suggests typically you assign the result to a variable. Take a simple example here:
let myNumber = 10;
let myHalvedNumber = halveNumber(myNumber);
console.log(myNumber)
console.log(myHalvedNumber);
function halveNumber(numberToHalve){
return numberToHalve/2;
}
The best way to think about it in practice is to treat the function/input combination { f(x) } as a proxy for the result itself. This means that both of these examples are correct and how you choose to employ it is your own preference.
//These two approaches are identical and both valid:
//1) Assign to a variable for further use - typically better for variable re-use:
let myHalvedNumber = halveNumber(10);
aSecondFunction(myHalvedNumber);
//2) Use the result directly in a second call - typically shorter and arguably easier to maintain/read
aSecondFunction(halveNumber(10));
function halveNumber(myNumber){
return myNumber/2;
}
function aSecondFunction (myNumber){
console.log("the number is: " + myNumber)
}

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`;
}

Calling a function bypassing eval()

I am working with a Javascript code that uses eval function.
eval(myString)
The value of myString = myFunc(arg), I want to call myFunc directly without using eval.
I dont have any control over the function to call as I am getting that function as a String (here myString).
The arguments to that function is also part of the same string.
So, is there any way through which I can call the intended function without using eval?
I'm a bit skeptical of allowing users to provide function names at all, but... Assume you have the function name in a variable and the value of arg in a variable. Boom:
var myString = window[fn](arg);
arg is already presumably in an argument, so that's simple enough. The next part is exatracting the function name. Just a bit of regex:
var fn = /^([a-z0-9_]+)\(arg\)$/i.exec(str)[1];
if (fn && typeof window[fn] === 'function') {
window[fn](arg);
}
This does of course assume that the function is always in the global scope, but if it's not, you should be able to adjust accordingly for that. Also, my regex is just the first thing I came up with. It probably doesn't cover all possible function names.
If you wanted to limit the string to just a certain set of functions (and you almost certainly should), that becomes quite easy as well once you have the function name:
var allowedFunctions = {fn1: fn1, fn2: fn2, someOtherFunction: function() {} },
fn = /^([a-z0-9_]+)\(arg\)$/i.exec(str)[1];
if (fn && allowedFunctions[fn]) {
allowedFunctions[fn](arg);
} else {
// Hah, nice try.
}
(If arg isn't actually a variable name but is some kind of literal or perhaps an arbitrary expression, this gets a little more complicated and a lot less safe.)
JavaScript does not provide any way of calling a function represented as a string, other than using eval. There's nothing wrong about using it, though. Given that you have no other option.
Possibly you may try using Function:
var sure = function(s) {
return confirm(s);
};
var str = 'sure("Are you sure?")';
var rtn = new Function('return ' + str)();
alert(rtn);

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.

Can I detect unused extra parameters passed to javascript methods?

In Javascript I can call any method with more than the necessary amount of parameters and the extra parameters are silently ignored.
e.g.
letters = ['a','b','c']
//correct
letters.indexOf('a')
//This also works without error or warning
letters.indexOf('a', "blah", "ignore me", 38)
Are there ways to detect cases where this occurs?
My motivation is that in my experience cases where this occurs are usually bugs. Identification of these by code analysis or at runtime would help track these errors down.
These cases are especially prevalent where people are expecting alterations to base types which may not have occurred. Logging a warning where this happens
e.g.
Date.parse('02--12--2012', 'dd--MM--YYYY')
Notes:
To be clear I would like a solution that doesn't involve me sprinkling checks all over my code and other peoples' code.
You can use the arguments object.
function myFunction(param1,param2)
{
if (arguments.length!=2)
{
// wrong param number!
}
...
}
As per your edit: If you want to implement an automated form of check, without ever touching the original functions:
You still have to process each function with:
functionName = debug(functionName, numberOfExpectedArgs);
This operation wraps the function with a check of the number of arguments.
So we leave a sample function untouched:
// this is the original function... we want to implement argument number
// checking without insertint ANY debug code and ANY modification
function myFunction(a,b,c)
{
return a + " " + b + " " + c;
}
// the only addition is to do this...
myFunction = debug(myFunction,3); // <- implement arg number check on myFunction for 3 args
// let's test it...
console.log(myFunction(1,2,3));
console.log(myFunction(1,2));
You need to implement this debug() function:
function debug(f, n)
{
var f2 = f;
var fn = function()
{
if (arguments.length!=n) console.log("WARNING, wrong argument number");
return f2.apply(f2, arguments);
};
return fn;
}
​
This solution is TOTALLY transparent as per already defined functions, so it may be what you seek for.
I strongly suggest to check against deprecations (there are some) and crossbrowser compatibility.
The functions in JavaScript are objects. As such they have properties. What you want can be achieved with length MDN property, which specifies the number of arguments expected by the function.
function say ( hello, world ) {
alert (
"arguments length = " + arguments.length + "\n" +
"defined with = " + say.length
);
}
say ( "this ", "brave ", "new ", "world" );​
This works even on IE8. Demo. In your case you can do something like this.
Javascript is a very dynamic language and many of its useful features also make it impossible to do some checks statically.
The existance of the arguments implicit object means there is no way to automatically determine how many arguments a function is expecting for all functions. Many var-arg functions declare no formal arguments and uses the arguments object exclusively.
All you can reliably do is to check it manually in each function like Cranio suggested.
If you want to have automated checks, e.g. as part of your unit tests, you can make use of the length property of the Function objects, which returns the number of formal arguments. For var-arg functions, just don't include the check. For example:
function checkNumberOfArguments(args) {
if (args.length != args.callee.length) {
throw new Error('Wrong number of arguments');
}
};
// Use it like
function a(b) {
checkNumberOfArguments(arguments);
}
a(1);
a(1,2);
Inside function you can use arguments object, it contains an array of all the arguments that were supplied to the function when it was called.
function x(){
return arguments.length;
}
x()
=> 0
x(1,1,1,1,1,1,1,1,1)
=> 9

Categories