Default argument values in JavaScript functions [duplicate] - javascript

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do I make a default value for a parameter to a javascript function
in PHP:
function func($a = 10, $b = 20){
// if func() is called with no arguments $a will be 10 and $ b will be 20
}
How can you do this in JavaScript?
I get a error if I try to assign values in function arguments
missing ) after formal parameters

In javascript you can call a function (even if it has parameters) without parameters.
So you can add default values like this:
function func(a, b){
if (typeof(a)==='undefined') a = 10;
if (typeof(b)==='undefined') b = 20;
//your code
}
and then you can call it like func(); to use default parameters.
Here's a test:
function func(a, b){
if (typeof(a)==='undefined') a = 10;
if (typeof(b)==='undefined') b = 20;
alert("A: "+a+"\nB: "+b);
}
//testing
func();
func(80);
func(100,200);

ES2015 onwards:
From ES6/ES2015, we have default parameters in the language specification. So we can just do something simple like,
function A(a, b = 4, c = 5) {
}
or combined with ES2015 destructuring,
function B({c} = {c: 2}, [d, e] = [3, 4]) {
}
For detailed explanation,
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/default_parameters
Default function parameters allow formal parameters to be initialized with default values if no value or undefined is passed.
Pre ES2015:
If you're going to handle values which are NOT Numbers, Strings, Boolean, NaN, or null you can simply use
(So, for Objects, Arrays and Functions that you plan never to send null, you can use)
param || DEFAULT_VALUE
for example,
function X(a) {
a = a || function() {};
}
Though this looks simple and kinda works, this is restrictive and can be an anti-pattern because || operates on all falsy values ("", null, NaN, false, 0) too - which makes this method impossible to assign a param the falsy value passed as the argument.
So, in order to handle only undefined values explicitly, the preferred approach would be,
function C(a, b) {
a = typeof a === 'undefined' ? DEFAULT_VALUE_A : a;
b = typeof b === 'undefined' ? DEFAULT_VALUE_B : b;
}

You have to check if the argument is undefined:
function func(a, b) {
if (a === undefined) a = "default value";
if (b === undefined) b = "default value";
}
Also note that this question has been answered before.

I have never seen it done that way in JavaScript. If you want a function with optional parameters that get assigned default values if the parameters are omitted, here's a way to do it:
function(a, b) {
if (typeof a == "undefined") {
a = 10;
}
if (typeof b == "undefined") {
a = 20;
}
alert("a: " + a + " b: " + b);
}

function func(a, b)
{
if (typeof a == 'undefined')
a = 10;
if (typeof b == 'undefined')
b = 20;
// do what you want ... for example
alert(a + ',' + b);
}
in shorthand
function func(a, b)
{
a = (typeof a == 'undefined')?10:a;
b = (typeof b == 'undefined')?20:b;
// do what you want ... for example
alert(a + ',' + b);
}

You cannot add default values for function parameters. But you can do this:
function tester(paramA, paramB){
if (typeof paramA == "undefined"){
paramA = defaultValue;
}
if (typeof paramB == "undefined"){
paramB = defaultValue;
}
}

Related

javascript function rules with multiple parameter braces

How would you write a function that is like this
f()()
f('it') == fit
f()('x') == fox
I have
function f(s){
return "f"+s;
}
I had to discern what you're looking for not only from your question, but also from your comments. It looks like every string begins with 'f', and each empty bracket-pair appends an 'o'. Finally, a non-empty bracket-pair appends its argument.
I actually think this is a cool metaprogramming challenge.
This should work:
let f = (str, depth=0) => str
? `f${'o'.repeat(depth)}${str}` // If given param, terminate
: str => f(str, depth + 1); // If no param, return func
// "fit"
console.log(f('it'));
// "fox"
console.log(f()('x'));
// "fortress"
console.log(f()('rtress'));
// "football"
console.log(f()()('tball'));
// "foooooool!!!"
console.log(f()()()()()()()('l!!!'));
You have only 3 required outputs and no additional behavior requirements explained. Hence, the simplest approach would be:
let f = arg =>
arg ? 'f' + arg : arg => arg ? 'fo' + arg : '';
console.log(f()()); // ''
console.log(f('it')); // 'fit'
console.log(f()('x')); // 'fox'
You could return a function for more than one call of the function and implement a toString method to get the final string.
function f(v) {
var s = 'f' + (v || 'o');
function g(v) {
s += v || 'o';
return g;
};
g.toString = function () { return s; };
return g;
}
console.log(f()()); // foo
console.log(f('it')); // fit
console.log(f()('x')); // fox
console.log(f()()('b')('a')('r')); // foobar
That's a very strange function to want, but you can do it by having your named function return an anonymous function if you didn't get a parameter the first time:
function f(s, str) {
if(typeof str === "undefined") {
str = "f"
}
if(typeof s === "undefined") {
return function(t) {
return f(t, str + "o")
}
} else {
return str + s;
}
}
Haha I saw this problem the other day, I used function currying:
var f = s => s ? `f${s}` : (g=o=>e=>e?`f${o+e}`:g(o+'o')) && g('o')
console.log(f('x'))
console.log(f()()('l'))
console.log(f()()()('bar'))

Passing string as parameter by reference

I want to alter the contents of a string in a function, for example
function appendSeparating(s, s2, separator) {
if (s != "")
s += separator;
s += s2;
}
I'd like to have s altered on return but as string is a primitive is being passed by value so the modifications do not affect the original.
What is the most efficient/clean way to deal with this? (I try to keep code concise)
JavaScript has no out parameters if that's what you mean. The simplest way of dealing with this is to pass the string in an object.
function appendSeparating(stringObj, s2, separator) {
if (stringObj.text != "")
stringObj.text += separator;
stringObj.text += s2;
}
Global Variables
While string primitives are not passed by reference, one option not mentioned is the ability to use global variables. Of my own conscience, I must advise against this, but not knowing your use case you should know of your options:
s = 'a' // created as a global variable
appendSeparating('b', '|') // function now takes only two arguments
console.log(s) // global variable affected
function appendSeparating(s2, separator) {
// s is a global variable
if (typeof s === 'undefined')
return;
if (s != "")
s += separator;
s += s2;
}
Return Assignment
Of course you could build your own function and use the return variable as an assignment. Below I've used a prototype function, but should also advise against this, without fully understanding the implications (experience can take years) — you may see that I'm teaching you what not to do:
String.prototype.append = function(str, delimiter) {
return [this, str].filter(v => v !== '').join(delimiter || '|')
};
let ex1 = 'a'
ex1 = ex1.append('b')
console.log('no delim: ', ex1)
let ex2 = 'a'
ex2 = ex2.append('b', '-')
console.log('w/ delim: ', ex2)
Here's a "better" way to do the same. Although efficient, the untrained eye might struggle to understand what is occurring in the body of the function. It's subjective, but for maintainability you might want to make something more readable:
let ex1 = 'a'
ex1 = append(ex1, 'b')
console.log('no delim: ', ex1)
let ex2 = 'a'
ex2 = append(ex2, 'b', '-')
console.log('w/ delim: ', ex2)
function append(prefix, suffix, delimiter) {
return [prefix, suffix].filter(v => v !== '').join(delimiter || '|')
};
Object Mutation / Scoping
The final thing you can do is modify an object. Not only will this get close to what it seems you'd like, but in larger applications is very nice to scope variables in objects to avoid collision and ease debugging (though, at the cost of a performance penalty):
const strings = {}
// Assuming key name
strings.s = 'foo'
append(strings, 'bar', ': ')
console.log(strings.s)
// Supplying key name
strings.x = 'x'
appendNamed(strings, 'x', 'y')
console.log(strings.x)
function append(str, suffix, delimiter) {
str.s = [str.s, suffix].filter(v => v !== '').join(delimiter || '|')
};
function appendNamed(str, strName, suffix, delimiter){
str[strName] = [str[strName], suffix].filter(v => v !== '').join(delimiter || '|')
};
A similar question was made here, and the answers include implementation alternatives.
Long story short: wrap the string you would like to "pass by reference" in an object, then modify the object, as shown in this fiddle
function concatStrings(stringObj, s2, separator) {
stringObj.value = stringObj.value + separator + s2;
}
var baseString = "hello";
var stringObj = {value: baseString};
var s2 = "world";
var separator = " ";
concatStrings(stringObj, s2, separator);
window.alert(stringObj.value);
You could return the new string.
function appendSeparating(s, s2, separator) {
s += s && separator;
return s + s2;
}
var x = '';
console.log(x = appendSeparating(x, 'one', ', '));
console.log(x = appendSeparating(x, 'two', ', '));
console.log(x = appendSeparating(x, 'three', ', '));
With an object, you could take the object, the separated key and the other parts and update this property.
function appendSeparating(object, key, s2, separator) {
object[key] += object[key] && separator;
return object[key] += s2;
}
appendSeparating(clients[index].address, 'postalCode', 'foo', ', ');

Javascript ING BANK 3 questions test interview

I had a test interview and for 3 questions I didn't know the answer:
Write a function that will insert underscore between characters: this will become t_h_i_s.
Write a function that will output this:
l('t') === 'lt'
l()('t') === 'l3t'
l()()('t') === 'l33t'
l()()('g') === 'l33g'
l()()()()()()()()()()()('t') === 'l33333333333t'
Why the output is true?
var bar = true;
function foo() {
bar = false;
return 5;
function bar() {}
}
foo();
console.log(bar);
Can someone help please with the answers?
Write a function that will insert underscore between characters: this will become t_h_i_s.
You want to write a function that iterates over all characters in a string, and appends an underscore between all characters.
For example:
function underscoreString(str) {
var result = str.charAt(0);
for (var i=1; i<str.length; i++) {
result += '_' + str.charAt(i);
}
return result;
}
console.log( underscoreString('this') );
Write a function that will output this:
You will need to write a function that returns another function, so you can chain the functions. Since Javascript allows you to store functions as variables, you can make use of this by re-calling the same function continuously until a proper argument is returned.
The following function is an example. It works as intended but is not the most beautiful.
function l(ch) {
var str = 'l';
if (ch) return str + ch;
else str += '3';
var newFunc = function (ch) {
if (ch) return str + ch;
str += '3';
return newFunc;
}
return newFunc
}
console.log( l('t') === 'lt' );
console.log( l()('t') === 'l3t' );
console.log( l()()('t') === 'l33t' );
console.log( l()()('g') === 'l33g' );
console.log( l()()()()()()()()()()()('t') === 'l33333333333t' );
Why the output is true?
var bar = true;
function foo() {
bar = false;
return 5;
function bar() {}
}
foo();
console.log(bar);
The bar that is within the function foo() is not referencing the global variable bar. Instead, it is referencing the function function bar() {}. This is because of hoisting, as mentioned in the comments.
Thus, the global bar variable is not touched at all by the function, and stays true at all times.
It really depends on the expected level of code. If you need to demonstrate understanding of algorithms or knowledge of how to use javascript constructs.
For example, the first one could be as simple as:
function insertUnderscore(x){
return x.split('').join('_');
}
2nd question a recursive method:
function l( end ){
var acc = '';
function iter( eChar ){
if( typeof eChar === "undefined"){
acc=acc+'3';
return iter;
}
return 'l'+acc+eChar;
}
if(typeof end === "undefined"){
acc = acc + '3';
return iter;
}
return iter(end);
}
Third question:
function bar(){} actually declares 'bar' within the local scope, so your assignment bar = false acts on local 'bar'.
This one simply returns the iterator function if the letter is undefined, When the letter is defined it repeats the character '3' n times.
The other two should be pretty easy to figure out
function l(letter) {
let count = 0
function iter(letter) {
if (typeof letter === 'undefined') {
count++
return iter
} else {
return 'l' + ('3'.repeat(count)) + letter
}
}
return iter(letter)
}
console.log(l('t') === 'lt')
console.log(l()('t') === 'l3t')
console.log(l()()('t') === 'l33t')
console.log(l()()('g') === 'l33g')
console.log(l()()()()()()()()()()()('t') === 'l33333333333t')
Question 1
Use a negative lookahead for the beginning of the string and a positive lookahead for a character. Replace the given empty string with an underscore.
function spacer(s) {
return s.replace(/(?!^.)(?=.)/g, '_');
}
console.log(spacer('this'));
Question 2
Use a closure and return for a non given paramter the function otherwise the extended value.
function l(v) {
var s = 'l';
fn = function (v) {
s += 3;
return v === undefined ? fn : s + v;
};
return v === undefined ? fn : s + v;
}
console.log(l('t') === 'lt');
console.log(l()('t') === 'l3t');
console.log(l()()('t') === 'l33t');
console.log(l()()('g') === 'l33g');
console.log(l()()()()()()()()()()()('t') === 'l33333333333t');
Question 3
Because function bar() {} is hoisted to the begin of the function and then overwritten with false. The outer bar variable has never changed it's content.
var bar = true;
function foo() {
bar = false;
console.log('foo\'s bar:', bar);
return 5;
function bar() {}
}
foo();
console.log(bar);

Fast way to check the biggest variable? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I need a way to get the name of the variable with the greatest value.
a = 55;
b = 13;
c = 45;
d = 5;
var top = '';
if((a>b)&&(a>c)&&(a>d)){ top = 'a'; }
if((b>a)&&(b>c)&&(b>d)){ top = 'b'; }
if((c>a)&&(c>b)&&(c>d)){ top = 'c'; }
if((d>a)&&(d>b)&&(d>c)){ top = 'd'; }
Is there a better or faster way to do this?
You can't get the variable name directly:
Very few languages support what you want to do because the variable
names only exist for your benefit in the source code. They do not
exist in the compiled executable code in that form anymore and
tracking them would be extremely expensive.
If you want to do this, there is something fundamentally wrong with your design as there is no reason that would preclude doing it the most idiomatic way possible which is to use an associative array, which in JavaScript means using an Object or an actual Map when available and where appropriate.
Object based approach:
Most compatible way if you do not have access to Map:
You can use an object and find the property name. The most concise way to do this is with the Array.reduce() function.
var obj = {a:55,b:13,c:45,d:5};
var maxPropertyName = Object.keys(obj).reduce(function(previous,key){
return obj[previous] > obj[key] ? previous : key;
})
console.log(maxPropertyName);
Output:
a
Map based approach:
For this case a Map seems more appropriate since this looks like a homogeneousCollection rather than a Type of something.
Map instances are only useful for collections, and
you should consider adapting your code where you have previously used
objects for such. Objects shall be used as records, with fields and
methods. If you're still not sure which one to use, ask yourself the
following questions:
Are keys usually unknown until run time, do you need to look them
up dynamically?
Do all values have the same type, and can be used interchangeably?
Do you need keys that aren't strings?
Are key-value pairs often added or removed? Do you have an
arbitrary (easily changing) amount of key-value pairs?
Is the collection iterated? Those all are signs that you want a Map
for a collection.
If in contrast you have a fixed amount of keys, operate on them
individually, and distinguish between their usage, then you want an
object.
Here is how to add a .reduce() method to Map:
Map.prototype.reduce = function(callback){
'use strict';
if (this == null) {
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
var t = Object(this), value;
if (t.size === 0) { value = undefined; }
else if (t.size === 1) { value = t.keys().next().value; }
else {
value = t.keys().next().value;
for (var kv of t) {
value = callback(value, kv[0]);
}
}
return value;
};
Same .reduce() code now works:
var m = new Map([["a",55],["b",13], ["c",45],["d",5]]);
var maxPropertyName = m.reduce(function(previous,key){
return m.get(previous) > m.get(key) ? previous : key;
})
console.log(maxPropertyName);
Output:
a
A simple way to do it, store everything in an object and loop over the keys:
// you can keep the input variables
var a = 55;
var b = 13;
var c = 45;
var d = 5;
var obj = {
a: a,
b: b,
c: c,
d: d
}
var max;
var varName;
Object.keys(obj).forEach(function(key) {
if (!max || max < obj[key]) {
max = obj[key];
varName = key;
}
});
snippet.log(max);
snippet.log(varName);
<script src="https://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
function high(obj) {
var highest = Number.NEGATIVE_INFINITY,
keyName = null;
for (var key in obj) {
if( obj[key] > highest ) {
highest = obj[key];
keyName = key;
}
}
return keyName;
}
In this way you can need not care about the variable name.Also need not repeat the variable name.
// init
var obj={};
var max=0,maxName="";
var x={};
for(var key in window){
x[key]=window[key];
}
// your code
a = 55;
b = 13;
c = 45;
d = 5;
// end of your code
// select the max num
for(var key in window){
if(typeof(window[key]) == "number" && typeof(x[key])!="number"){
if(window[key]>max){
max=window[key];
maxName=key;
}
}
}
// output the variable name
console.log(maxName);
And you can write a method to reuse:
function getTop(func){
// init
var obj={};
var max=0,maxName="";
var x={};
for(var key in window){
x[key]=window[key];
}
func();
// select the max num
for(var key in window){
if(typeof(window[key]) == "number" && typeof(x[key])!="number"){
if(window[key]>max){
max=window[key];
window[key]=undefined;
maxName=key;
}
}
}
// output the variable name
return maxName;
}
you can use the code to get the top varname:
var top=getTop(function(){
a=11;
b=22;
c=23;
d=14;
});
One way, if you cannot use object, then get max value and then check individual values to variable. Here you will not have very complex condition. Also its better to if...else if...else than multiple if
a = 55;
b = 13;
c = 45;
d = 5;
var max = Math.max(a,b,c,d);
var varName = "";
if(max === a){
varName = "a";
}
else if(max === b){
varName = "b";
}
else if(max === c){
varName = "c";
}
else{
varName = d;
}
alert(varName);

Expressions in ternary operators as functions

3>4?function1():function2()
Is it allowed to use functions in ternary operators?
I know you can use it for values, but for functions I am not certain.
You can. But like this
var func = 3 > 4 ? function(){
console.log("3 is not greater than 4");
} : function(){
console.log("3 IS greater than 4");
};
Now func has a function reference that has been set conditionally. Calling it func() will result in "3 IS greater than 4"
However, if you already have created the function, then just reference would be enough. You should not call it. Just pass the reference.
var func = 3 > 4 ? func1 : func2;
you can do
var f = 3>4?function(){console.log("left")}:function(){console.log("right")}
or with your edit
var f = 3>4?function1:function2
then f will be the function ( not the result of the function )
f()
or if you want the value that those functions return
var v = 3>4?function1():function2()
v will now be whatever those functions returned
This is valid JavaScript:
var b = true;
var a = b == true ? function(){ return 1; } : function(){return 2; }
a is a function that depended upon the ternary condition, exactly as you'd (hopefully) expect.
If you're wanting a to instead be the return value of the function - call it.
var b = true;
var a = b == true ? (function(){ return 1; }()) : (function(){return 2; }())

Categories

Resources