Related
I find the named parameters feature in C# quite useful in some cases.
calculateBMI(70, height: 175);
What can I use if I want this in JavaScript?
What I don’t want is this:
myFunction({ param1: 70, param2: 175 });
function myFunction(params){
// Check if params is an object
// Check if the parameters I need are non-null
// Blah blah
}
That approach I’ve already used. Is there another way?
I’m okay using any library to do this.
ES2015 and later
In ES2015, parameter destructuring can be used to simulate named parameters. It would require the caller to pass an object, but you can avoid all of the checks inside the function if you also use default parameters:
myFunction({ param1 : 70, param2 : 175});
function myFunction({param1, param2}={}){
// ...function body...
}
// Or with defaults,
function myFunc({
name = 'Default user',
age = 'N/A'
}={}) {
// ...function body...
}
ES5
There is a way to come close to what you want, but it is based on the output of Function.prototype.toString [ES5], which is implementation dependent to some degree, so it might not be cross-browser compatible.
The idea is to parse the parameter names from the string representation of the function so that you can associate the properties of an object with the corresponding parameter.
A function call could then look like
func(a, b, {someArg: ..., someOtherArg: ...});
where a and b are positional arguments and the last argument is an object with named arguments.
For example:
var parameterfy = (function() {
var pattern = /function[^(]*\(([^)]*)\)/;
return function(func) {
// fails horribly for parameterless functions ;)
var args = func.toString().match(pattern)[1].split(/,\s*/);
return function() {
var named_params = arguments[arguments.length - 1];
if (typeof named_params === 'object') {
var params = [].slice.call(arguments, 0, -1);
if (params.length < args.length) {
for (var i = params.length, l = args.length; i < l; i++) {
params.push(named_params[args[i]]);
}
return func.apply(this, params);
}
}
return func.apply(null, arguments);
};
};
}());
Which you would use as:
var foo = parameterfy(function(a, b, c) {
console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
});
foo(1, 2, 3); // a is 1 | b is 2 | c is 3
foo(1, {b:2, c:3}); // a is 1 | b is 2 | c is 3
foo(1, {c:3}); // a is 1 | b is undefined | c is 3
foo({a: 1, c:3}); // a is 1 | b is undefined | c is 3
DEMO
There are some drawbacks to this approach (you have been warned!):
If the last argument is an object, it is treated as a "named argument objects"
You will always get as many arguments as you defined in the function, but some of them might have the value undefined (that's different from having no value at all). That means you cannot use arguments.length to test how many arguments have been passed.
Instead of having a function creating the wrapper, you could also have a function which accepts a function and various values as arguments, such as
call(func, a, b, {posArg: ... });
or even extend Function.prototype so that you could do:
foo.execute(a, b, {posArg: ...});
No - the object approach is JavaScript's answer to this. There is no problem with this provided your function expects an object rather than separate params.
Lots of people say to just use the "Pass an object" trick so that you have named parameters.
/**
* My Function
*
* #param {Object} arg1 Named arguments
*/
function myFunc(arg1) { }
myFunc({ param1 : 70, param2 : 175});
And that works great, except... when it comes to most IDEs out there, a lot of us developers rely on type / argument hints within our IDE. I personally use PhpStorm (along with other JetBrains IDEs, like PyCharm for Python and AppCode for Objective-C).
And the biggest problem with using the "Pass an object" trick is that when you are calling the function, the IDE gives you a single type hint and that's it... How are we supposed to know what parameters and types should go into the arg1 object?
So... the "Pass an object" trick doesn't work for me... It actually causes more headaches with having to look at each function's docblock before I know what parameters the function expects.... Sure, it's great for when you are maintaining existing code, but it's horrible for writing new code.
Well, this is the technique I use... Now, there may be some issues with it, and some developers may tell me I'm doing it wrong, and I have an open mind when it comes to these things... I am always willing to look at better ways of accomplishing a task... So, if there is an issue with this technique, then comments are welcome.
/**
* My Function
*
* #param {string} arg1 Argument 1
* #param {string} arg2 Argument 2
*/
function myFunc(arg1, arg2) { }
var arg1, arg2;
myFunc(arg1='Param1', arg2='Param2');
This way, I have the best of both worlds. New code is easy to write as my IDE gives me all the proper argument hints. And, while maintaining code later on, I can see at a glance, not only the value passed to the function, but also the name of the argument. The only overhead I see is declaring your argument names as local variables to keep from polluting the global namespace. Sure, it's a bit of extra typing, but it's trivial compared to the time it takes to look up docblocks while writing new code or maintaining existing code.
Update - 2022
JavaScript now has the ability to have something close to named parameters using object destructuring available in ES6. Most newer browsers can use this feature See browser support
This is how it works:
// Define your function like this
function myFunc({arg1, arg2, arg3}) {
// Function body
}
// Call your function like this
myFunc({arg1: "value1", arg2: "value2", arg3: "value3"})
// You can also have default values for arguments
function myFunc2({firstName, lastName, age = 21}) {
// Function body
}
// And you can call it with or without an "age" argument
myFunc({firstName: "John", lastName: "Doe"}) // Age will be 21
myFunc({firstName: "Jane", lastName: "Doe", age: 22})
The best part is that most IDE's now support this syntax and you get good argument hint support
TypeScript
For those of you using TypeScript, you can do the same thing using this syntax
function myFunc(
{firstName, lastName, age = 21}:
{firstName: string, lastName: string, age?: number}
) {
// Function body
}
OR, using an interface
interface Params {
firstName: string
lastName: string
age?: number
}
function myFunc({firstName, lastName, age = 21}: Params) {
// Function body
}
If you want to make it clear what each of the parameters are, rather than just calling
someFunction(70, 115);
do the following:
var width = 70, height = 115;
someFunction(width, height);
Sure, it's an extra line of code, but it wins on readability.
Another way would be to use attributes of a suitable object, e.g. like so:
function plus(a,b) { return a+b; };
Plus = { a: function(x) { return { b: function(y) { return plus(x,y) }}},
b: function(y) { return { a: function(x) { return plus(x,y) }}}};
sum = Plus.a(3).b(5);
Of course for this made up example it is somewhat meaningless. But in cases where the function looks like
do_something(some_connection_handle, some_context_parameter, some_value)
it might be more useful. It also could be combined with "parameterfy" idea to create such an object out of an existing function in a generic way. That is for each parameter it would create a member that can evaluate to a partial evaluated version of the function.
This idea is of course related to Schönfinkeling aka Currying.
Calling function f with named parameters passed as the object
o = {height: 1, width: 5, ...}
is basically calling its composition f(...g(o)) where I am using the spread syntax and g is a "binding" map connecting the object values with their parameter positions.
The binding map is precisely the missing ingredient, that can be represented by the array of its keys:
// map 'height' to the first and 'width' to the second param
binding = ['height', 'width']
// take binding and arg object and return aray of args
withNamed = (bnd, o) => bnd.map(param => o[param])
// call f with named args via binding
f(...withNamed(binding, {hight: 1, width: 5}))
Note the three decoupled ingredients: the function, the object with named arguments and the binding. This decoupling allows for a lot of flexibility to use this construct, where the binding can be arbitrarily customized in function's definition and arbitrarily extended at the function call time.
For instance, you may want to abbreviate height and width as h and w inside your function's definition, to make it shorter and cleaner, while you still want to call it with full names for clarity:
// use short params
f = (h, w) => ...
// modify f to be called with named args
ff = o => f(...withNamed(['height', 'width'], o))
// now call with real more descriptive names
ff({height: 1, width: 5})
This flexibility is also more useful for functional programming, where functions can be arbitrarily transformed with their original param names getting lost.
There is another way. If you're passing an object by reference, that object's properties will appear in the function's local scope. I know this works for Safari (haven't checked other browsers) and I don't know if this feature has a name, but the below example illustrates its use.
Although in practice I don't think that this offers any functional value beyond the technique you're already using, it's a little cleaner semantically. And it still requires passing a object reference or an object literal.
function sum({ a:a, b:b}) {
console.log(a+'+'+b);
if(a==undefined) a=0;
if(b==undefined) b=0;
return (a+b);
}
// will work (returns 9 and 3 respectively)
console.log(sum({a:4,b:5}));
console.log(sum({a:3}));
// will not work (returns 0)
console.log(sum(4,5));
console.log(sum(4));
Coming from Python this bugged me. I wrote a simple wrapper/Proxy for node that will accept both positional and keyword objects.
https://github.com/vinces1979/node-def/blob/master/README.md
NB. My answer of 2016 is not correct and misleading as mentioned in comments.
Trying Node-6.4.0 ( process.versions.v8 = '5.0.71.60') and Node Chakracore-v7.0.0-pre8 and then Chrome-52 (V8=5.2.361.49), I've noticed that named parameters are almost implemented, but that order has still precedence. I can't find what the ECMA standard says.
>function f(a=1, b=2){ console.log(`a=${a} + b=${b} = ${a+b}`) }
> f()
a=1 + b=2 = 3
> f(a=5)
a=5 + b=2 = 7
> f(a=7, b=10)
a=7 + b=10 = 17
But order is required!! Is it the standard behaviour?
> f(b=10)
a=10 + b=2 = 12
This is admittedly pseudocode, but I believe it'll work (I know it works in TypeScript; I'm adopting it for JavaScript).
// Target Function
const myFunc = (a=1,b=2,c=3) => {a+b+c}
// Goal usage:
myFunc(a=5, b=6) // 14
myFunc(c=0) // 3
// Set your defaults
const myFuncDefaults = {a:1, b:2, c:3};
// Override them with passed parameters
const myFuncParams = (params) => { return Object.assign(myFuncDefaults, params)}
// Use the overloaded dict as the input
const myFunc2 = (params) => {
let {a, b, c} = myFuncParams(params);
return myFunc(a, b, c)
}
// Usage:
myFunc({a:5, b:6}) // 14
myFunc({c:0}) // 3
// Written more succinctly:
const myFunc = (params) => {
let {a,b,c} = Object.assign({a:1, b:2, c:3}, params)
return a + b + c
}
For what it's worth, TypeScript makes this kind of nice with hinting:
interface IParams {
a: number;
b: number;
c: number;
}
const myFunc = (params: Partial<IParams>): number => {
const default: IParams = {a:1, b:2, c:3};
let {a, b, c} = Object.assign(default, params)
return a + b + c
}
Yes, well, kind of. I've found two solutions. I'll explain just one.
In this solution, we give up positional arguments, though.
We can use an object (almost identical to a dict in Python) to pass the arguments.
In this example, I'm using the function to generate the name of a image file:
// First we define our function with just ONE argument
function name_of_img(img_desc){
// With this step, any undefined value will be assigned a value
if(img_desc.size == undefined) {img_desc.size = "400x500"}
if(img_desc.format == undefined) {img_desc.format = ".png"}
console.log(img_desc.size + img_desc.format)
}
// Notice inside our function we're passing a dict/object
name_of_img({size: "200x250", format : ".jpg"})
// In Python name_of_img(size="200x250" , format="jpg")
// returns "200x250.jpg"
name_of_img({size: "1200x950"})
// In Python name_of_img(size="1200x950")
// returns "1200x950.png"
We can modify this example, so we can use positional arguments too, we can also modify it so non valid arguments can be passed, I think I will make a GitHub repository about this.
Contrary to what is commonly believed, named parameters can be implemented in standard, old-school JavaScript (for boolean parameters only) by means of a simple, neat coding convention, as shown below.
function f(p1=true, p2=false) {
...
}
f(!!"p1"==false, !!"p2"==true); // call f(p1=false, p2=true)
Caveats:
Ordering of arguments must be preserved - but the pattern is still useful, since it makes it obvious which actual argument is meant for which formal parameter without having to grep for the function signature or use an IDE.
This only works for booleans. However, I'm sure a similar pattern could be developed for other types using JavaScript's unique type coercion semantics.
I've found this topic which I've implemented (see accepted answer):
javascript equivalent of PHP's call_user_func()
However, I am having a problem with multiple parameters. I realize what I was doing was turning my parameters into strings and treating it like 1 parameter, but I don't know how to fix this because I am dynamically creating the parameters.
Meaning, I have defined in my code the following:
var a = new Array();
a[0] = new Array();
a[0][0] = 'alert';
a[0][1] = '\'Hello World\'';
a[1] = new Array();
a[1][0] = 'setTimeout';
a[1][1] = 'alert("goodbye world")';
a[1][2] = '20';
Later, I was calling them like this:
var j = 0;
var len = 0;
var fx = '';
var params = '';
for( i in a ){
params = '';
len = a[i].length;
fx = a[i][0]; // getting the function name
a[i].splice( 0, 1 ); // removing it from array
if( len > 1 ){
params = a[i].join(", "); // trying to turn the parameters into the right format, but this is turning it into strings I think
params = params.replace(/\\'/g,'\''); // bc i was adding slashes with PHP
}
window[fx](params);
}
I don't have to use arrays to do this. I don't understand JS OOP (haven't tried yet), though I am comfortable with PHP OOP, so I don't know if there is a way to do this there.
Any help on passing multiple parameters would be appreciated.
Thanks.
First thing to do: Scrap your entire code, start over. Your approach will not get you anywhere where you'd want to be. (Unfortunately I can't tell you where you'd want to be because I cannot make sense of your example.)
There are three ways to call a function in JavaScript.
function foo() { console.log(arguments); }
// 1. directly
foo(1, 2, 3);
// 2. trough Function.call()
foo.call(this, 1, 2, 3);
// 3. trough Function.apply()
var args = [1, 2, 3];
foo.apply(this, args);
call and apply are similar. They let you decide which object the this keyword will point to inside the function (that's the important bit!).
apply accepts an array of arguments, call accepts individual arguments.
The closest thing to call() is PHP's call_user_func(). The closest thing to apply() is PHP's call_user_func_array().
JavaScript objects share something with PHP arrays: They are key/value pairs.
// an anonymous function assigned to the key "foo"
var obj = {
foo: function () { console.log(arguments); }
};
This means you can access object properties either with the dot notation:
// direct function call
obj.foo(1, 2, 3);
Or through square bracket notation (note that object keys are strings):
var funcName = "foo";
obj[funcName](1, 2, 3);
obj[funcName].call(obj, 1, 2, 3);
obj[funcName].apply(obj, [1, 2, 3]);
Square bracket notation gives you the freedom to choose an object property dynamically. If this property happens to be a function, apply() gives you the freedom to choose function arguments dynamically.
Every top-level function that has not been declared as the property of some object will become the property of the global object. In browsers the global object is window. (So the function foo() in my first code block above really is window.foo.)
Note that this does not work like in PHP. It will point to the object the function has been called on, not the object the function "belongs to". (The concept "belongs to" does not really exist in JavaScript. Things can be modeled that way, but it's only a convention.)
With direct calling (obj.foo(1, 2, 3)), this will point to obj. With call and apply, this will point to whatever object you want to. This is a lot more useful than it sounds at first. Most of the time when you want to call functions dynamically, you will end up using apply.
Check out Function.apply:
function test(a, b) { console.log([a, b]) }
test.apply(null, [1, 2]); // => [ 1, 2 ]
Late to the party, but now with ES6 you can simply do
function FunctionX(a,b,c,d){
return a + b + c + d;
}
let fx = "FunctionX";
let params = [ 1, 10, 100, 200 ];
let answer = window[fx]( ... params);
let answer2 = globalThis[fx]( ... params ); // this is more cross-platform
to unpack your argument array
I'm learning JavaScript and while browsing through the jQuery library I see : (colon) being used a lot. What is this used for in JavaScript?
// Return an array of filtered elements (r)
// and the modified expression string (t)
return { r: r, t: t };
var o = {
r: 'some value',
t: 'some other value'
};
is functionally equivalent to
var o = new Object();
o.r = 'some value';
o.t = 'some other value';
And also, a colon can be used to label a statement. for example
var i = 100, j = 100;
outerloop:
while(i>0) {
while(j>0) {
j++
if(j>50) {
break outerloop;
}
}
i++
}
You guys are forgetting that the colon is also used in the ternary operator (though I don't know if jquery uses it for this purpose).
the ternary operator is an expression form (expressions return a value) of an if/then statement. it's used like this:
var result = (condition) ? (value1) : (value2) ;
A ternary operator could also be used to produce side effects just like if/then, but this is profoundly bad practice.
The ':' is a delimiter for key value pairs basically. In your example it is a Javascript Object Literal notation.
In javascript, Objects are defined with the colon delimiting the identifier for the property, and its value so you can have the following:
return {
Property1 : 125,
Property2 : "something",
Method1 : function() { /* do nothing */ },
array: [5, 3, 6, 7]
};
and then use it like:
var o = {
property1 : 125,
property2 : "something",
method1 : function() { /* do nothing */ },
array: [5, 3, 6, 7]
};
alert(o.property1); // Will display "125"
A subset of this is also known as JSON (Javascript Object Notation) which is useful in AJAX calls because it is compact and quick to parse in server-side languages and Javascript can easily de-serialize a JSON string into an object.
// The parenthesis '(' & ')' around the object are important here
var o = eval('(' + "{key: \"value\"}" + ')');
You can also put the key inside quotes if it contains some sort of special character or spaces, but I wouldn't recommend that because it just makes things harder to work with.
Keep in mind that JavaScript Object Literal Notation in the JavaScript language is different from the JSON standard for message passing. The main difference between the 2 is that functions and constructors are not part of the JSON standard, but are allowed in JS object literals.
It is part of the object literal syntax. The basic format is:
var obj = { field_name: "field value", other_field: 42 };
Then you can access these values with:
obj.field_name; // -> "field value"
obj["field_name"]; // -> "field value"
You can even have functions as values, basically giving you the methods of the object:
obj['func'] = function(a) { return 5 + a;};
obj.func(4); // -> 9
It can be used to list objects in a variable. Also, it is used a little bit in the shorthand of an if sentence:
var something = {face: 'hello',man: 'hey',go: 'sup'};
And calling it like this
alert(something.man);
Also the if sentence:
function something() {
(some) ? doathing() : dostuff(); // if some = true doathing();, else dostuff();
}
These are generally the scenarios where colon ':' is used in JavaScript
1- Declaring and Initializing an Object
var Car = {model:"2015", color:"blue"}; //car object with model and color properties
2- Setting a Label (Not recommended since it results in complicated control structure and Spaghetti code)
List:
while(counter < 50)
{
userInput += userInput;
counter++;
if(userInput > 10000)
{
break List;
}
}
3- In Switch Statement
switch (new Date().getDay()) {
case 6:
text = "Today is Saturday";
break;
case 0:
text = "Today is Sunday";
break;
default:
text = "Looking forward to the Weekend";
}
4- In Ternary Operator
document.getElementById("demo").innerHTML = age>18? "True" : "False";
Let's not forget the switch statement, where colon is used after each "case".
That's JSON, or JavaScript Object Notation. It's a quick way of describing an object, or a hash map. The thing before the colon is the property name, and the thing after the colon is its value. So in this example, there's a property "r", whose value is whatever's in the variable r. Same for t.
Another usage of colon in JavaScript is to rename a variable, that is:
const person = {
nickNameThatIUseOnStackOverflow: "schlingel",
age: 30,
firstName: "John"
};
let { nickNameThatIUseOnStackOverflow: nick } = person; // I take nickNameThatIUseOnStackOverflow but want to refer it as "nick" from now on.
nick = "schling";
This is useful if you use a third party library that returns values having awkward / long variable names that you want to rename in your code.
One stupid mistake I did awhile ago that might help some people.
Keep in mind that if you are using ":" in an event like this, the value will not change
var ondrag = (function(event, ui) {
...
nub0x: event.target.offsetLeft + event.target.clientWidth/2;
nub0y = event.target.offsetTop + event.target.clientHeight/2;
...
});
So "nub0x" will initialize with the first event that happens and will never change its value. But "nub0y" will change during the next events.
As can be seen in the Mozilla changlog for JavaScript 1.7 they have added destructuring assignment. Sadly I'm not very fond of the syntax (why write a and b twice?):
var a, b;
[a, b] = f();
Something like this would have been a lot better:
var [a, b] = f();
That would still be backwards compatible. Python-like destructuring would not be backwards compatible.
Anyway the best solution for JavaScript 1.5 that I have been able to come up with is:
function assign(array, map) {
var o = Object();
var i = 0;
$.each(map, function(e, _) {
o[e] = array[i++];
});
return o;
}
Which works like:
var array = [1,2];
var _ = assign[array, { var1: null, var2: null });
_.var1; // prints 1
_.var2; // prints 2
But this really sucks because _ has no meaning. It's just an empty shell to store the names. But sadly it's needed because JavaScript doesn't have pointers. On the plus side you can assign default values in the case the values are not matched. Also note that this solution doesn't try to slice the array. So you can't do something like {first: 0, rest: 0}. But that could easily be done, if one wanted that behavior.
What is a better solution?
First off, var [a, b] = f() works just fine in JavaScript 1.7 - try it!
Second, you can smooth out the usage syntax slightly using with():
var array = [1,2];
with (assign(array, { var1: null, var2: null }))
{
var1; // == 1
var2; // == 2
}
Of course, this won't allow you to modify the values of existing variables, so IMHO it's a whole lot less useful than the JavaScript 1.7 feature. In code I'm writing now, I just return objects directly and reference their members - I'll wait for the 1.7 features to become more widely available.
You don't need the dummy "_" variable. You can directly create "global" variables by using the window object scope:
window["foo"] = "bar";
alert(foo); // Gives "bar"
Here are few more points:
I wouldn't name this function
"assign" because that's too generic
a term.
To more closely resemble JS
1.7 syntax, I'd make the function take the destination as the first
argument and the source as the
second argument.
Using an object literal to pass the destination variables is cool but can be confused with JS 1.7 destructuring where the destination is actually an object and not an array. I prefer just using a comma delimited list of variable names as a string.
Here's what I came up with:
function destructure(dest, src) {
dest = dest.split(",");
for (var i = 0; i < src.length; i++) {
window[dest[i]] = src[i];
}
}
var arr = [42, 66];
destructure("var1,var2", arr);
alert(var1); // Gives 42
alert(var2); // Gives 66
Here's what I did in PHPstorm 10:
File -> Settings -> Languages & Frameworks -> ...
... set JavaScript language version to e.g. JavaScript 1.8.5...
-> click Apply.
In standard JavaScript we get used to all kinds of ugliness, and emulating destructuring assignment using an intermediate variable is not too bad:
function divMod1(a, b) {
return [ Math.floor(a / b), a % b ];
}
var _ = divMod1(11, 3);
var div = _[0];
var mod = _[1];
alert("(1) div=" + div + ", mod=" + mod );
However I think the following pattern is more idomatic:
function divMod2(a, b, callback) {
callback(Math.floor(a / b), a % b);
}
divMod2(11, 3, function(div, mod) {
alert("(2) div=" + div + ", mod=" + mod );
});
Note, that instead of returning the two results as an array, we pass them as arguments to a callback function.
(See code running at http://jsfiddle.net/vVQE3/ )
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What "Hidden Features" of JavaScript do you think every programmer should know?
After having seen the excellent quality of the answers to the following questions I thought it was time to ask it for JavaScript.
Hidden Features of HTML
Hidden Features of CSS
Hidden Features of PHP
Hidden Features of ASP.NET
Hidden Features of C#
Hidden Features of Java
Hidden Features of Python
Even though JavaScript is arguably the most important Client Side language right now (just ask Google) it's surprising how little most web developers appreciate how powerful it really is.
You don't need to define any parameters for a function. You can just use the function's arguments array-like object.
function sum() {
var retval = 0;
for (var i = 0, len = arguments.length; i < len; ++i) {
retval += arguments[i];
}
return retval;
}
sum(1, 2, 3) // returns 6
I could quote most of Douglas Crockford's excellent book
JavaScript: The Good Parts.
But I'll take just one for you, always use === and !== instead of == and !=
alert('' == '0'); //false
alert(0 == ''); // true
alert(0 =='0'); // true
== is not transitive. If you use === it would give false for
all of these statements as expected.
Functions are first class citizens in JavaScript:
var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };
var sum = function(x,y,z) {
return x+y+z;
};
alert( passFunAndApply(sum,3,4,5) ); // 12
Functional programming techniques can be used to write elegant javascript.
Particularly, functions can be passed as parameters, e.g. Array.filter() accepts a callback:
[1, 2, -1].filter(function(element, index, array) { return element > 0 });
// -> [1,2]
You can also declare a "private" function that only exists within the scope of a specific function:
function PrintName() {
var privateFunction = function() { return "Steve"; };
return privateFunction();
}
You can use the in operator to check if a key exists in an object:
var x = 1;
var y = 3;
var list = {0:0, 1:0, 2:0};
x in list; //true
y in list; //false
1 in list; //true
y in {3:0, 4:0, 5:0}; //true
If you find the object literals too ugly you can combine it with the parameterless function tip:
function list()
{ var x = {};
for(var i=0; i < arguments.length; ++i) x[arguments[i]] = 0;
return x
}
5 in list(1,2,3,4,5) //true
Assigning default values to variables
You can use the logical or operator || in an assignment expression to provide a default value:
var a = b || c;
The a variable will get the value of c only if b is falsy (if is null, false, undefined, 0, empty string, or NaN), otherwise a will get the value of b.
This is often useful in functions, when you want to give a default value to an argument in case isn't supplied:
function example(arg1) {
arg1 || (arg1 = 'default value');
}
Example IE fallback in event handlers:
function onClick(e) {
e || (e = window.event);
}
The following language features have been with us for a long time, all JavaScript implementations support them, but they weren't part of the specification until ECMAScript 5th Edition:
The debugger statement
Described in: § 12.15 The debugger statement
This statement allows you to put breakpoints programmatically in your code just by:
// ...
debugger;
// ...
If a debugger is present or active, it will cause it to break immediately, right on that line.
Otherwise, if the debugger is not present or active this statement has no observable effect.
Multiline String literals
Described in: § 7.8.4 String Literals
var str = "This is a \
really, really \
long line!";
You have to be careful because the character next to the \ must be a line terminator, if you have a space after the \ for example, the code will look exactly the same, but it will raise a SyntaxError.
JavaScript does not have block scope (but it has closure so let's call it even?).
var x = 1;
{
var x = 2;
}
alert(x); // outputs 2
You can access object properties with [] instead of .
This allows you look up a property matching a variable.
obj = {a:"test"};
var propname = "a";
var b = obj[propname]; // "test"
You can also use this to get/set object properties whose name is not a legal identifier.
obj["class"] = "test"; // class is a reserved word; obj.class would be illegal.
obj["two words"] = "test2"; // using dot operator not possible with the space.
Some people don't know this and end up using eval() like this, which is a really bad idea:
var propname = "a";
var a = eval("obj." + propname);
This is harder to read, harder to find errors in (can't use jslint), slower to execute, and can lead to XSS exploits.
If you're Googling for a decent JavaScript reference on a given topic, include the "mdc" keyword in your query and your first results will be from the Mozilla Developer Center. I don't carry any offline references or books with me. I always use the "mdc" keyword trick to directly get to what I'm looking for. For example:
Google: javascript array sort mdc
(in most cases you may omit "javascript")
Update: Mozilla Developer Center has been renamed to Mozilla Developer Network. The "mdc" keyword trick still works, but soon enough we may have to start using "mdn" instead.
Maybe a little obvious to some...
Install Firebug and use console.log("hello"). So much better than using random alert();'s which I remember doing a lot a few years ago.
Private Methods
An object can have private methods.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
// A private method only visible from within this constructor
function calcFullName() {
return firstName + " " + lastName;
}
// A public method available to everyone
this.sayHello = function () {
alert(calcFullName());
}
}
//Usage:
var person1 = new Person("Bob", "Loblaw");
person1.sayHello();
// This fails since the method is not visible from this scope
alert(person1.calcFullName());
Also mentioned in Crockford's "Javascript: The Good Parts":
parseInt() is dangerous. If you pass it a string without informing it of the proper base it may return unexpected numbers. For example parseInt('010') returns 8, not 10. Passing a base to parseInt makes it work correctly:
parseInt('010') // returns 8! (in FF3)
parseInt('010', 10); // returns 10 because we've informed it which base to work with.
Functions are objects and therefore can have properties.
fn = function(x) {
// ...
}
fn.foo = 1;
fn.next = function(y) {
//
}
I'd have to say self-executing functions.
(function() { alert("hi there");})();
Because Javascript doesn't have block scope, you can use a self-executing function if you want to define local variables:
(function() {
var myvar = 2;
alert(myvar);
})();
Here, myvar is does not interfere with or pollute the global scope, and disappears when the function terminates.
Know how many parameters are expected by a function
function add_nums(num1, num2, num3 ){
return num1 + num2 + num3;
}
add_nums.length // 3 is the number of parameters expected.
Know how many parameters are received by the function
function add_many_nums(){
return arguments.length;
}
add_many_nums(2,1,122,12,21,89); //returns 6
Here are some interesting things:
Comparing NaN with anything (even NaN) is always false, that includes ==, < and >.
NaN Stands for Not a Number but if you ask for the type it actually returns a number.
Array.sort can take a comparator function and is called by a quicksort-like driver (depends on implementation).
Regular expression "constants" can maintain state, like the last thing they matched.
Some versions of JavaScript allow you to access $0, $1, $2 members on a regex.
null is unlike anything else. It is neither an object, a boolean, a number, a string, nor undefined. It's a bit like an "alternate" undefined. (Note: typeof null == "object")
In the outermost context, this yields the otherwise unnameable [Global] object.
Declaring a variable with var, instead of just relying on automatic declaration of the variable gives the runtime a real chance of optimizing access to that variable
The with construct will destroy such optimzations
Variable names can contain Unicode characters.
JavaScript regular expressions are not actually regular. They are based on Perl's regexs, and it is possible to construct expressions with lookaheads that take a very, very long time to evaluate.
Blocks can be labeled and used as the targets of break. Loops can be labeled and used as the target of continue.
Arrays are not sparse. Setting the 1000th element of an otherwise empty array should fill it with undefined. (depends on implementation)
if (new Boolean(false)) {...} will execute the {...} block
Javascript's regular expression engine's are implementation specific: e.g. it is possible to write "non-portable" regular expressions.
[updated a little in response to good comments; please see comments]
I know I'm late to the party, but I just can't believe the + operator's usefulness hasn't been mentioned beyond "convert anything to a number". Maybe that's how well hidden a feature it is?
// Quick hex to dec conversion:
+"0xFF"; // -> 255
// Get a timestamp for now, the equivalent of `new Date().getTime()`:
+new Date();
// Safer parsing than parseFloat()/parseInt()
parseInt("1,000"); // -> 1, not 1000
+"1,000"; // -> NaN, much better for testing user input
parseInt("010"); // -> 8, because of the octal literal prefix
+"010"; // -> 10, `Number()` doesn't parse octal literals
// A use case for this would be rare, but still useful in cases
// for shortening something like if (someVar === null) someVar = 0;
+null; // -> 0;
// Boolean to integer
+true; // -> 1;
+false; // -> 0;
// Other useful tidbits:
+"1e10"; // -> 10000000000
+"1e-4"; // -> 0.0001
+"-12"; // -> -12
Of course, you can do all this using Number() instead, but the + operator is so much prettier!
You can also define a numeric return value for an object by overriding the prototype's valueOf() method. Any number conversion performed on that object will not result in NaN, but the return value of the valueOf() method:
var rnd = {
"valueOf": function () { return Math.floor(Math.random()*1000); }
};
+rnd; // -> 442;
+rnd; // -> 727;
+rnd; // -> 718;
"Extension methods in JavaScript" via the prototype property.
Array.prototype.contains = function(value) {
for (var i = 0; i < this.length; i++) {
if (this[i] == value) return true;
}
return false;
}
This will add a contains method to all Array objects. You can call this method using this syntax
var stringArray = ["foo", "bar", "foobar"];
stringArray.contains("foobar");
To properly remove a property from an object, you should delete the property instead of just setting it to undefined:
var obj = { prop1: 42, prop2: 43 };
obj.prop2 = undefined;
for (var key in obj) {
...
The property prop2 will still be part of the iteration. If you want to completely get rid of prop2, you should instead do:
delete obj.prop2;
The property prop2 will no longer will make an appearance when you're iterating through the properties.
with.
It's rarely used, and frankly, rarely useful... But, in limited circumstances, it does have its uses.
For instance: object literals are quite handy for quickly setting up properties on a new object. But what if you need to change half of the properties on an existing object?
var user =
{
fname: 'Rocket',
mname: 'Aloysus',
lname: 'Squirrel',
city: 'Fresno',
state: 'California'
};
// ...
with (user)
{
mname = 'J';
city = 'Frostbite Falls';
state = 'Minnesota';
}
Alan Storm points out that this can be somewhat dangerous: if the object used as context doesn't have one of the properties being assigned to, it will be resolved in the outer scope, possibly creating or overwriting a global variable. This is especially dangerous if you're used to writing code to work with objects where properties with default or empty values are left undefined:
var user =
{
fname: "John",
// mname definition skipped - no middle name
lname: "Doe"
};
with (user)
{
mname = "Q"; // creates / modifies global variable "mname"
}
Therefore, it is probably a good idea to avoid the use of the with statement for such assignment.
See also: Are there legitimate uses for JavaScript’s “with” statement?
Methods (or functions) can be called on object that are not of the type they were designed to work with. This is great to call native (fast) methods on custom objects.
var listNodes = document.getElementsByTagName('a');
listNodes.sort(function(a, b){ ... });
This code crashes because listNodes is not an Array
Array.prototype.sort.apply(listNodes, [function(a, b){ ... }]);
This code works because listNodes defines enough array-like properties (length, [] operator) to be used by sort().
Prototypal inheritance (popularized by Douglas Crockford) completely revolutionizes the way you think about loads of things in Javascript.
Object.beget = (function(Function){
return function(Object){
Function.prototype = Object;
return new Function;
}
})(function(){});
It's a killer! Pity how almost no one uses it.
It allows you to "beget" new instances of any object, extend them, while maintaining a (live) prototypical inheritance link to their other properties. Example:
var A = {
foo : 'greetings'
};
var B = Object.beget(A);
alert(B.foo); // 'greetings'
// changes and additionns to A are reflected in B
A.foo = 'hello';
alert(B.foo); // 'hello'
A.bar = 'world';
alert(B.bar); // 'world'
// ...but not the other way around
B.foo = 'wazzap';
alert(A.foo); // 'hello'
B.bar = 'universe';
alert(A.bar); // 'world'
Some would call this a matter of taste, but:
aWizz = wizz || "default";
// same as: if (wizz) { aWizz = wizz; } else { aWizz = "default"; }
The trinary operator can be chained to act like Scheme's (cond ...):
(cond (predicate (action ...))
(predicate2 (action2 ...))
(#t default ))
can be written as...
predicate ? action( ... ) :
predicate2 ? action2( ... ) :
default;
This is very "functional", as it branches your code without side effects. So instead of:
if (predicate) {
foo = "one";
} else if (predicate2) {
foo = "two";
} else {
foo = "default";
}
You can write:
foo = predicate ? "one" :
predicate2 ? "two" :
"default";
Works nice with recursion, too :)
Numbers are also objects. So you can do cool stuff like:
// convert to base 2
(5).toString(2) // returns "101"
// provide built in iteration
Number.prototype.times = function(funct){
if(typeof funct === 'function') {
for(var i = 0;i < Math.floor(this);i++) {
funct(i);
}
}
return this;
}
(5).times(function(i){
string += i+" ";
});
// string now equals "0 1 2 3 4 "
var x = 1000;
x.times(function(i){
document.body.innerHTML += '<p>paragraph #'+i+'</p>';
});
// adds 1000 parapraphs to the document
How about closures in JavaScript (similar to anonymous methods in C# v2.0+). You can create a function that creates a function or "expression".
Example of closures:
//Takes a function that filters numbers and calls the function on
//it to build up a list of numbers that satisfy the function.
function filter(filterFunction, numbers)
{
var filteredNumbers = [];
for (var index = 0; index < numbers.length; index++)
{
if (filterFunction(numbers[index]) == true)
{
filteredNumbers.push(numbers[index]);
}
}
return filteredNumbers;
}
//Creates a function (closure) that will remember the value "lowerBound"
//that gets passed in and keep a copy of it.
function buildGreaterThanFunction(lowerBound)
{
return function (numberToCheck) {
return (numberToCheck > lowerBound) ? true : false;
};
}
var numbers = [1, 15, 20, 4, 11, 9, 77, 102, 6];
var greaterThan7 = buildGreaterThanFunction(7);
var greaterThan15 = buildGreaterThanFunction(15);
numbers = filter(greaterThan7, numbers);
alert('Greater Than 7: ' + numbers);
numbers = filter(greaterThan15, numbers);
alert('Greater Than 15: ' + numbers);
You can also extend (inherit) classes and override properties/methods using the prototype chain spoon16 alluded to.
In the following example we create a class Pet and define some properties. We also override the .toString() method inherited from Object.
After this we create a Dog class which extends Pet and overrides the .toString() method again changing it's behavior (polymorphism). In addition we add some other properties to the child class.
After this we check the inheritance chain to show off that Dog is still of type Dog, of type Pet, and of type Object.
// Defines a Pet class constructor
function Pet(name)
{
this.getName = function() { return name; };
this.setName = function(newName) { name = newName; };
}
// Adds the Pet.toString() function for all Pet objects
Pet.prototype.toString = function()
{
return 'This pets name is: ' + this.getName();
};
// end of class Pet
// Define Dog class constructor (Dog : Pet)
function Dog(name, breed)
{
// think Dog : base(name)
Pet.call(this, name);
this.getBreed = function() { return breed; };
}
// this makes Dog.prototype inherit from Pet.prototype
Dog.prototype = new Pet();
// Currently Pet.prototype.constructor
// points to Pet. We want our Dog instances'
// constructor to point to Dog.
Dog.prototype.constructor = Dog;
// Now we override Pet.prototype.toString
Dog.prototype.toString = function()
{
return 'This dogs name is: ' + this.getName() +
', and its breed is: ' + this.getBreed();
};
// end of class Dog
var parrotty = new Pet('Parrotty the Parrot');
var dog = new Dog('Buddy', 'Great Dane');
// test the new toString()
alert(parrotty);
alert(dog);
// Testing instanceof (similar to the `is` operator)
alert('Is dog instance of Dog? ' + (dog instanceof Dog)); //true
alert('Is dog instance of Pet? ' + (dog instanceof Pet)); //true
alert('Is dog instance of Object? ' + (dog instanceof Object)); //true
Both answers to this question were codes modified from a great MSDN article by Ray Djajadinata.
You may catch exceptions depending on their type. Quoted from MDC:
try {
myroutine(); // may throw three exceptions
} catch (e if e instanceof TypeError) {
// statements to handle TypeError exceptions
} catch (e if e instanceof RangeError) {
// statements to handle RangeError exceptions
} catch (e if e instanceof EvalError) {
// statements to handle EvalError exceptions
} catch (e) {
// statements to handle any unspecified exceptions
logMyErrors(e); // pass exception object to error handler
}
NOTE: Conditional catch clauses are a Netscape (and hence Mozilla/Firefox) extension that is not part of the ECMAScript specification and hence cannot be relied upon except on particular browsers.
Off the top of my head...
Functions
arguments.callee refers to the function that hosts the "arguments" variable, so it can be used to recurse anonymous functions:
var recurse = function() {
if (condition) arguments.callee(); //calls recurse() again
}
That's useful if you want to do something like this:
//do something to all array items within an array recursively
myArray.forEach(function(item) {
if (item instanceof Array) item.forEach(arguments.callee)
else {/*...*/}
})
Objects
An interesting thing about object members: they can have any string as their names:
//these are normal object members
var obj = {
a : function() {},
b : function() {}
}
//but we can do this too
var rules = {
".layout .widget" : function(element) {},
"a[href]" : function(element) {}
}
/*
this snippet searches the page for elements that
match the CSS selectors and applies the respective function to them:
*/
for (var item in rules) {
var elements = document.querySelectorAll(rules[item]);
for (var e, i = 0; e = elements[i++];) rules[item](e);
}
Strings
String.split can take regular expressions as parameters:
"hello world with spaces".split(/\s+/g);
//returns an array: ["hello", "world", "with", "spaces"]
String.replace can take a regular expression as a search parameter and a function as a replacement parameter:
var i = 1;
"foo bar baz ".replace(/\s+/g, function() {return i++});
//returns "foo1bar2baz3"
You can use objects instead of switches most of the time.
function getInnerText(o){
return o === null? null : {
string: o,
array: o.map(getInnerText).join(""),
object:getInnerText(o["childNodes"])
}[typeis(o)];
}
Update: if you're concerned about the cases evaluating in advance being inefficient (why are you worried about efficiency this early on in the design of the program??) then you can do something like this:
function getInnerText(o){
return o === null? null : {
string: function() { return o;},
array: function() { return o.map(getInnerText).join(""); },
object: function () { return getInnerText(o["childNodes"]; ) }
}[typeis(o)]();
}
This is more onerous to type (or read) than either a switch or an object, but it preserves the benefits of using an object instead of a switch, detailed in the comments section below. This style also makes it more straightforward to spin this out into a proper "class" once it grows up enough.
update2: with proposed syntax extensions for ES.next, this becomes
let getInnerText = o -> ({
string: o -> o,
array: o -> o.map(getInnerText).join(""),
object: o -> getInnerText(o["childNodes"])
}[ typeis o ] || (->null) )(o);
Be sure to use the hasOwnProperty method when iterating through an object's properties:
for (p in anObject) {
if (anObject.hasOwnProperty(p)) {
//Do stuff with p here
}
}
This is done so that you will only access the direct properties of anObject, and not use the properties that are down the prototype chain.
Private variables with a Public Interface
It uses a neat little trick with a self-calling function definition.
Everything inside the object which is returned is available in the public interface, while everything else is private.
var test = function () {
//private members
var x = 1;
var y = function () {
return x * 2;
};
//public interface
return {
setx : function (newx) {
x = newx;
},
gety : function () {
return y();
}
}
}();
assert(undefined == test.x);
assert(undefined == test.y);
assert(2 == test.gety());
test.setx(5);
assert(10 == test.gety());