March 23, 2018
TestsSource
- Function
- closure
- this "stuff"
Source Code
The source code we wrote during the event.
functions-features.spec.js
import assert from 'assert';
const globalScope = typeof window !== 'undefined' ? window : global;
describe('Function', function() {
it('is of type `Function`', () => {
assert.equal(typeof Function, 'function');
});
it('returns a function when used as constructor', () => {
assert.equal(typeof (new Function()), 'function');
});
it('returns a function when called', () => {
assert.equal(typeof (Function()), 'function');
});
it('executing a "new" Function', () => {
const fn = new Function('return 42');
assert.equal(fn(), 42);
});
it('executing a "new" Function (without `new`)', () => {
const fn = Function('return 42');
assert.equal(fn(), 42);
});
it('eval inside `Function`', () => {
const fn = Function('return eval("42")');
assert.equal(fn(), 42);
});
it('return "this" from inside `Function`', function() {
const fn = Function('return this');
assert.equal(fn(), globalScope);
});
it('return "this" from inside `new Function`', () => {
const fn = new Function('return this');
assert.equal(fn(), globalScope);
});
it('with 2 arguments', () => {
const fn = new Function('x', 'return x');
assert.equal(fn(42), 42);
});
xit('"normal function" the scope of `this` ???', function() {
function fn() { return this; };
assert.equal(fn(), this);
});
});
describe('closure', () => {
// - function has a ref to smthg that does not exist anymore
it('function has access to outside scope', () => {
function fn1() {
const someVar = 42;
return function fn2() {
return someVar;
}
}
assert.equal(fn1()(), 42);
});
it('inside^2 function still has outside scope access', () => {
function fn1() {
const someVar = 42;
return function fn2() {
const anotherVar = someVar;
return function fn3() {
return someVar + anotherVar;
}
}
}
assert.equal(fn1()()(), 84);
});
it('inside^3 function still has outside scope access', () => {
function fn1() {
const someVar = 42;
return function fn2() {
const anotherVar = someVar;
return function fn3(a) {
return someVar + anotherVar + a;
}
}
}
assert.equal(fn1()()('1'), 841);
});
it('duplicated names', () => {
function fn1() {
const someVar = 42;
return function fn2(someVar) {
return someVar;
}
}
assert.deepEqual(fn1()(), undefined);
});
describe('this "stuff"', function() {
xit('`this.x` in nested function', function() {
function fn1() {
this.x = 42;
// return function fn2() {
// return this.x;
// }
return this.x;
}
assert.deepEqual(fn1(), window.x);
});
});
it('immediatly invoked fn', (done) => {
var bar = '';
for (var x = 0; x<10; x++) {
const fn = function(y) {
// var y = x;
return function() {bar += y;}
}(x);
setTimeout(fn, 1);
}
setTimeout(() => {assert.equal(bar, '0123456789'); done();}, 2);
});
it('using `setTimeout`', (done) => {
var bar = '';
for (var x = 0; x<10; x++) {
const fn = (y) => { bar += y; };
setTimeout(fn, 1, x);
}
setTimeout(() => {assert.equal(bar, '0123456789'); done();}, 2);
});
it('using `bind`', (done) => {
var bar = '';
for (var x = 0; x<10; x++) {
const fn = (y) => { bar += y; };
setTimeout(fn.bind(null, x), 1);
}
setTimeout(() => {assert.equal(bar, '0123456789'); done();}, 2);
});
it('bind (1)', () => {
const fn = function() { return this.x }
assert.equal(fn.bind({x: 42})(), 42);
});
it('bind params', () => {
const fn = function(a, b, c, d) { return this.x + a + b + c + d}
const fnToCall = fn.bind({x: 42}, 1, 2);
assert.equal(fnToCall(5, 10), 60);
});
it('binding again does NOT change the scope', () => {
const fn = function() { return this.x}
const fnToCall = fn.bind({x: 42}).bind({x: 23});
assert.equal(fnToCall(), 42);
});
it('binding again, can bind another param', () => {
const fn = function(a, b) { return a + b}
const fnToCall = fn.bind(null, 1).bind(null, 2);
assert.equal(fnToCall(), 3);
});
});