Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

This repository was created with the intention of helping developers master their concepts in JavaScript. It is not a requirement, but a guide for future studies. It is based on an article written by Stephen Curtis and you can read it [here](https://medium.com/@stephenthecurt/33-fundamentals-every-javascript-developer-should-know-13dd720a90d1).

### Extra topics in this fork

- `topics/challenging-js-interview-questions.md` — challenging JavaScript interview questions with solutions and explanations.

## Community

Feel free to submit a PR by adding a link to your own recaps or reviews. If you want to translate the repo into your native language, please feel free to do so.
Expand Down
14 changes: 14 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
This folder contains runnable examples and small tests for selected deterministic interview questions from `topics/challenging-js-interview-questions.md`.

How to run (requires Node.js >= 12):

- Run an example:

node example-closures-loop-var-let.js

- Run tests:

node run-tests.js

Notes:
- Tests use Node's built-in `assert` and do not require extra dependencies.
27 changes: 27 additions & 0 deletions examples/example-closures-loop-var-let.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Example: closures + loop differences (var vs let)
// This script prints expected outputs and exposes behavior for tests.

function runVarLoop() {
const results = [];
for (var i = 0; i < 3; i++) {
// emulate async callbacks by pushing functions and calling later
results.push(() => i);
}
// call callbacks
return results.map(fn => fn());
}

function runLetLoop() {
const results = [];
for (let j = 0; j < 3; j++) {
results.push(() => j);
}
return results.map(fn => fn());
}

if (require.main === module) {
console.log('var loop:', runVarLoop());
console.log('let loop:', runLetLoop());
}

module.exports = { runVarLoop, runLetLoop };
22 changes: 22 additions & 0 deletions examples/example-event-loop-micro-macro.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Example: event loop order (microtasks vs macrotasks)
// This example returns the order of operations by instrumentation.

function recordOrder() {
const out = [];
out.push('script start');
setTimeout(() => out.push('timeout'), 0);
Promise.resolve().then(() => out.push('promise'));
out.push('script end');
// we need to return a promise that resolves after macrotask runs
return new Promise(resolve => {
setTimeout(() => {
resolve(out);
}, 10);
});
}

if (require.main === module) {
recordOrder().then(order => console.log(order));
}

module.exports = { recordOrder };
31 changes: 31 additions & 0 deletions examples/example-hoisting-tdz.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Example: hoisting with var vs temporal dead zone (let)

function hoistingVar() {
// var is hoisted and initialized to undefined
try {
// accessing 'a' before declaration returns undefined
const before = a; // eslint-disable-line no-undef
var a = 1;
return { before, after: a };
} catch (err) {
return { error: err.message };
}
}

function hoistingLet() {
try {
// accessing b before declaration throws ReferenceError
const before = b; // eslint-disable-line no-undef
let b = 2;
return { before, after: b };
} catch (err) {
return { error: err.name };
}
}

if (require.main === module) {
console.log('hoistingVar:', hoistingVar());
console.log('hoistingLet:', hoistingLet());
}

module.exports = { hoistingVar, hoistingLet };
22 changes: 22 additions & 0 deletions examples/example-this-binding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Example: this binding variations

const obj = {
x: 10,
getX() { return this.x; }
};

function plainGetX() {
return obj.getX;
}

function boundGetX() {
return obj.getX.bind(obj);
}

if (require.main === module) {
console.log('obj.getX():', obj.getX());
console.log('plain call:', plainGetX()());
console.log('bound call:', boundGetX()());
}

module.exports = { obj, plainGetX, boundGetX };
59 changes: 59 additions & 0 deletions examples/run-tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Simple test runner using Node's assert
const assert = require('assert');
const { runVarLoop, runLetLoop } = require('./example-closures-loop-var-let');
const { hoistingVar, hoistingLet } = require('./example-hoisting-tdz');
const { recordOrder } = require('./example-event-loop-micro-macro');
const { obj, plainGetX, boundGetX } = require('./example-this-binding');

function testClosures() {
const varResults = runVarLoop();
// since functions return current i which after loop is 3
assert.deepStrictEqual(varResults, [3,3,3], 'var loop should give [3,3,3]');

const letResults = runLetLoop();
assert.deepStrictEqual(letResults, [0,1,2], 'let loop should give [0,1,2]');
}

function testHoisting() {
const v = hoistingVar();
assert.strictEqual(v.before, undefined, 'var before should be undefined');
assert.strictEqual(v.after, 1, 'var after should be 1');

const l = hoistingLet();
// we expect a ReferenceError name
assert.strictEqual(l.error, 'ReferenceError', 'let before access should throw ReferenceError');
}

async function testEventLoop() {
const order = await recordOrder();
// expected: script start, script end, promise, timeout
assert.deepStrictEqual(order, ['script start','script end','promise','timeout']);
}

function testThis() {
assert.strictEqual(obj.getX(), 10, 'method call returns 10');
assert.strictEqual(plainGetX()(), undefined, 'plain function call returns undefined (strict mode)');
assert.strictEqual(boundGetX()(), 10, 'bound function returns 10');
}

async function runAll() {
console.log('Running tests...');
try {
testClosures();
console.log('Closures tests passed');
testHoisting();
console.log('Hoisting tests passed');
await testEventLoop();
console.log('Event loop test passed');
testThis();
console.log('this binding tests passed');
console.log('All tests passed ✅');
} catch (err) {
console.error('Test failed:', err.message);
process.exitCode = 1;
}
}

if (require.main === module) runAll();

module.exports = { runAll };
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading