fancyscript

Fancy JavaScript

FancyScript

Fancy JavaScript

FancyScript aims to make developing in JavaScript easier and more powerful while remaining "just JavaScript". For a completely different approach with diverse syntax rules, and in the latter case, a powerful standard library, look toward CoffeeScript or ClojureScript. FancyScript compiles to plain ES5 JavaScript. Thanks @tarebyte for the name.

npm install -g fancyscript installs the FancyScript binary fancy so it can be used globally.

fancy input.fs compiles the FancyScript source file input.fs to plain JavaScript in input.js.

  • -b, --bare Compile without a top-level function wrapper.
  • -o, --out [DIR] Write all compiled JavaScript files into the specified directory.
  • -r, --repl Start an interactive FancyScript REPL. Interrupts all other options.
  • -w, --watch Watch specified files for changes.

FancyScript follows strict-mode JavaScript conventions. Unless the --bare option is passed, the compiled code is wrapped in an IIFE (Immediately-Invoked Function Expression) with "use strict"; inside. For the sake of clarity, other examples will not include the function wrapper and strict mode declaration.

var a = 42;
(function () {
    "use strict";
    var a = 42;
}).call(this);

Arrow functions in Harmony are a more concise syntax for function expressions, consisting of a parameter list and an automatically-returned expression or a statement block.

[1, 2, 3, 4].map(x => x * x);
[1, 2, 3, 4].map(function (x) {
    return x * x;
});

Use default arguments to provide a default value within the function's parameter list for any optional arguments.

function foo(a, b = 42, c, d = bar(), e) { }
function foo(a, b, c, d, e) {
    if (typeof b === 'undefined') { b = 42; }
    if (typeof d === 'undefined') { d = bar(); }
}

From the MDN page, rest parameters represent "an indefinite number of arguments as an array." A function declaration or function expression may have a rest parameter as its last argument which will absorb all the rest of the arguments when the function is called.

fn isEven (...x) {
    x.every(fn (x) { x % 2 === 0 });
}
function isEven() {
    var x = Array.prototype.slice.call(arguments, 0);
    return x.every(function (x) {
        return x % 2 === 0;
    });
}
 
isEven(2, 4, 6); // true

From the MDN page, the spread operator expands an expression into multiple arguments to a function or multiple elements in array literals. Currently only the former case is supported, but the latter is in progress.

var arr = ['b', 'c', 'd'];
console.log('a', ...arr, 'e');
var arr = ['b', 'c', 'd'];
console.log.apply(console.log, [].concat(['a'], arr, ['e'])); // a b c d e

Note that support for the spread operator in a call to Function.prototype.apply is neither available nor planned. A compelling use case would be needed.

Array destructuring can occur in variable declarations, assignment expressions, or function parameters.

var [a, b] = [11, 42];
console.log([a, b] = [b, a]); // [42, 11]
function show([, second]) {
    console.log(second);
}
show([a, b]); // 11
var $tmp = [11, 42], a = $tmp[0], b = $tmp[1];
console.log(function ($tmp) {
    a = $tmp[0];
    b = $tmp[1];
    return $tmp;
}([b, a]));
function show($tmp) {
    var second = $tmp[1];
    return console.log(second);
}
show([a, b]);

Like array destructuring, object destructuring is syntactic sugar for more easily creating objects or retrieving values from them. This can occur in variable declarations, function parameter lists, or as a shortcut in object expressions.

var { name, age: a } = getPerson(); // Declare variables "name" and "a"
var obj = { name, age: a }; // Shortcut to initialize obj.name to variable "name"
function ({ name, age: b}, cb) { }
({ name, age: a }) = getAnotherPerson();
var $tmp = getPerson(), name = $tmp['name'], a = $tmp['age'];
var obj = { name: name, age: a };
function ($tmp2, cb) {
    var name = $tmp2['name'], b = $tmp2['age'];
}
(function ($tmp3) {
    name = $tmp3['name'];
    a = $tmp3['age'];
    return $tmp3;
})(getAnotherPerson());

If the last statement of a function is an expression contained in an ExpressionStatement, it is automatically returned.

fn isEven (x) { x % 2 === 0 }
function isEven(x) {
    return x % 2 === 0;
}

fn is an alias to the function keyword and is interchangeable.

fn hello () {
    conole.log('Hello, world!');
}
function hello () {
    console.log('Hello, world!');
}
var isEven = (x, ...r) => x % 2 === 0 && (r.length ? isEven(...r) : true)
var isEven = function (x) {
    var r = Array.prototype.slice.call(arguments, 1);
    return x % 2 === 0 && (r.length ? isEven.apply(isEven, [].concat(r)) : true);
}
 
isEven(2, 4, 6, 7); // false
isEven(2, 4, 6, 8); // true

Licensed under the BSD 3-Clause License, the full text of which can be read in LICENSE.