Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

JavaScript (ES2026)  Module 1 – Start here: what JavaScript is and how to run it

JavaScript for Python developers

For Python developers: how JavaScript differs in numbers, truthiness, dicts and Map, sorting, defaults, this and async, both languages run side by side.

  • Beginner
  • 25 minutes
  • Examples run with Node.js 24.21.0, quickjs 0.32.0, Python 3.14.8 and Pyodide 314.0.7
  • By MySmartCoPilot
Free lesson, Pro answers: 25 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Map Python habits (truthiness, integers, dicts, comprehensions, exceptions, asyncio) to JavaScript
  • Avoid the traps that bite Python developers first, such as ==, number precision, sort order, in and this
  • Choose the JavaScript equivalent for common Python idioms

Before you start

What you’ll learn · Before you start

What you will learn

  • Map Python habits (truthiness, integers, dicts, comprehensions, exceptions, asyncio) to JavaScript
  • Avoid the traps that bite Python developers first, such as ==, number precision, sort order, in and this
  • Choose the JavaScript equivalent for common Python idioms

Before you start

On this page

If you write Python, most of JavaScript will feel familiar: functions are values, closures work the same way, exceptions are thrown and caught, async and await look the same, and f-strings have a close cousin in template literals. The differences are in the details, and they are the kind that let code run without an error and still give a wrong answer. JavaScript has one number type for whole and fractional numbers, so integers stop being exact after 2⁵³. Empty lists are truthy, and sort() compares numbers as text. Objects reorder number-like keys, and in checks keys, not values. A method taken off its object forgets the object, and an async function starts running the moment you call it. This lesson runs the same programs in Python 3.14.8 and Node.js 24.21.0, so you can see each difference in recorded output rather than take it on trust.

The same jobs in both languages

Here are three jobs you do every day in Python: counting words, sorting records by two keys, and reading a dictionary that may lack a key, written in both languages:

Count, sort and look up, in Python and in JavaScript

Python · side_by_side.py

# Three everyday jobs in Python: count words, sort records by two keys, read a dict safely.
from collections import Counter

text = "the cat sat on the mat by the door"
counts = Counter(text.split())
print("top three:", counts.most_common(3))

people = [{"name": "Ravi", "age": 31}, {"name": "Asha", "age": 31}, {"name": "Meera", "age": 27}]
oldest_first = sorted(people, key=lambda p: (-p["age"], p["name"]))
print("oldest first:", [p["name"] for p in oldest_first])

prices = {"tea": 20, "coffee": 35}
print("samosa, with a default:", prices.get("samosa", 0))
try:
    prices["samosa"]
except KeyError as error:
    print("samosa, without one: KeyError", error)

Output

top three: [('the', 3), ('cat', 1), ('sat', 1)]
oldest first: ['Asha', 'Ravi', 'Meera']
samosa, with a default: 0
samosa, without one: KeyError 'samosa'

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 side_by_side.py

JavaScript · side-by-side.mjs

// The same three jobs in JavaScript: count words, sort records by two keys, read a map safely.
const text = 'the cat sat on the mat by the door';
const counts = new Map();
for (const word of text.split(' ')) counts.set(word, (counts.get(word) ?? 0) + 1);
const topThree = [...counts].sort((a, b) => b[1] - a[1]).slice(0, 3);
console.log('top three:', topThree);

const people = [{ name: 'Ravi', age: 31 }, { name: 'Asha', age: 31 }, { name: 'Meera', age: 27 }];
const byName = (a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
const oldestFirst = people.toSorted((a, b) => b.age - a.age || byName(a, b));
console.log('oldest first:', oldestFirst.map((p) => p.name));

const prices = new Map([['tea', 20], ['coffee', 35]]);
console.log('samosa, with a default:', prices.get('samosa') ?? 0);
console.log('samosa, without one:', prices.get('samosa'));

Output

top three: [ [ 'the', 3 ], [ 'cat', 1 ], [ 'sat', 1 ] ]
oldest first: [ 'Asha', 'Ravi', 'Meera' ]
samosa, with a default: 0
samosa, without one: undefined

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node side-by-side.mjs

The two outputs say the same thing in two notations, and the code shows how the idioms map:

  • Counter becomes a Map. JavaScript has no Counter; the pattern counts.set(word, (counts.get(word) ?? 0) + 1) does its job, and ?? supplies 0 for a word not seen yet. Python’s most_common keeps words with equal counts in the order it first met them, and so did the JavaScript version: a Map remembers insertion order, and sort is stable, so equal elements keep their order.
  • A key tuple becomes a comparator. Python sorts by a key, (-age, name). JavaScript’s sort takes a comparator instead: a function given two items, whose result below zero, zero or above zero says which comes first. b.age - a.age || byName(a, b) sorts by age, oldest first, and by name when the ages are equal. toSorted returns a sorted copy, like sorted; sort sorts in place, like list.sort.
  • A missing key is not an error. prices.get('samosa') is undefined, where Python’s prices["samosa"] raises KeyError. prices.get('samosa') ?? 0 matches dict.get with a default. The quiet undefined is convenient and dangerous at once: a typo in a key gives you undefined instead of an exception, and the problem shows up later.

Nine questions, two different sets of answers

The next two programs ask both languages the same nine questions. Each line prints a question and its answer:

The same questions to Python and JavaScript

Python · gotchas.py

# Nine expressions whose answers a Python developer knows. gotchas.mjs asks JavaScript the same questions.
def add(item, items=[]):
    items.append(item)
    return items

add(1)
rows = [
    ("2 ** 53 + 1 equals 2 ** 53", 2 ** 53 + 1 == 2 ** 53),
    ("-7 % 3", -7 % 3),
    ("7 divided by 2, rounded down", 7 // 2),
    ("an empty list is truthy", bool([])),
    ("[10, 9, 1] sorted by default", sorted([10, 9, 1])),
    ("'a' is in ['a']", "a" in ["a"]),
    ("[1, 2] equals [1, 2]", [1, 2] == [1, 2]),
    ("add(2) after add(1)", add(2)),
    ("keys of {b: 1, 10: 1, 2: 1}", list({"b": 1, 10: 1, 2: 1})),
]
for label, value in rows:
    print(f"{label:31} {value!r}")

Output

2 ** 53 + 1 equals 2 ** 53      False
-7 % 3                          2
7 divided by 2, rounded down    3
an empty list is truthy         False
[10, 9, 1] sorted by default    [1, 9, 10]
'a' is in ['a']                 True
[1, 2] equals [1, 2]            True
add(2) after add(1)             [1, 2]
keys of {b: 1, 10: 1, 2: 1}     ['b', 10, 2]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 gotchas.py

JavaScript · gotchas.mjs

// The questions of gotchas.py, asked of JavaScript. Several answers differ.
function add(item, items = []) {
  items.push(item);
  return items;
}

add(1);
const rows = [
  ['2 ** 53 + 1 equals 2 ** 53', 2 ** 53 + 1 === 2 ** 53],
  ['-7 % 3', -7 % 3],
  ['7 divided by 2, rounded down', Math.floor(7 / 2)],
  ['an empty list is truthy', Boolean([])],
  ['[10, 9, 1] sorted by default', [10, 9, 1].sort()],
  ["'a' is in ['a']", 'a' in ['a']],
  ['[1, 2] equals [1, 2]', [1, 2] === [1, 2]],
  ['add(2) after add(1)', add(2)],
  ['keys of {b: 1, 10: 1, 2: 1}', Object.keys({ b: 1, 10: 1, 2: 1 })],
];
for (const [label, value] of rows) console.log(label.padEnd(31), value);

Output

2 ** 53 + 1 equals 2 ** 53      true
-7 % 3                          -1
7 divided by 2, rounded down    3
an empty list is truthy         true
[10, 9, 1] sorted by default    [ 1, 10, 9 ]
'a' is in ['a']                 false
[1, 2] equals [1, 2]            false
add(2) after add(1)             [ 2 ]
keys of {b: 1, 10: 1, 2: 1}     [ '2', '10', 'b' ]

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node gotchas.mjs

Side by side, from the two outputs:

Question Python 3.14.8 Node.js 24.21.0
2 ** 53 + 1 equals 2 ** 53 False true
-7 % 3 2 -1
7 divided by 2, rounded down 3 3
An empty list is truthy False true
[10, 9, 1] sorted by default [1, 9, 10] [ 1, 10, 9 ]
'a' is in ['a'] True false
[1, 2] equals [1, 2] True false
add(2) after add(1), with a list as the default [1, 2] [ 2 ]
Keys of {b: 1, 10: 1, 2: 1} ['b', 10, 2] [ '2', '10', 'b' ]

Eight of the nine answers differ. Here is why, row by row.

Numbers. Python’s int has unlimited precision. JavaScript has one number type for everything, the 64-bit floating-point double that Python uses for float, so whole numbers are exact only up to Number.MAX_SAFE_INTEGER, 2⁵³ − 1, which is 9,007,199,254,740,991. Past it, 2 ** 53 + 1 rounds to 2 ** 53. For larger exact integers JavaScript has a second type, BigInt, written with an n suffix: 2n ** 53n + 1n is exact. Money is safest as a whole number of the smallest unit, cents or paise, which stays exact to over 90 trillion rupees or dollars.

Remainder and division. % takes the sign of the dividend in JavaScript, so -7 % 3 is -1; Python’s takes the sign of the divisor and gives 2. Python’s // has no operator in JavaScript, where // starts a comment, so 7 // 2 silently means 7. Write Math.floor(7 / 2), which matches Python for negative numbers too, or Math.trunc, which rounds towards zero.

Truthiness. Python treats empty collections as false. In JavaScript only eight values are falsy: false, 0, -0, 0n, "", null, undefined and NaN. An empty array or an empty object is truthy, so if (items) is true for []; write if (items.length > 0).

Sorting. Without a comparator, sort turns the elements into strings and compares those, so 10 comes before 9 because "1" comes before "9". Sorting numbers always needs (a, b) => a - b.

in and equality. JavaScript’s in asks whether an object has a property with that key. For an array the keys are indices, so 0 in ['a'] is true and 'a' in ['a'] is false. Use includes for membership: ['a'].includes('a'). Equality has its own twist. JavaScript’s === compares objects by identity, like Python’s is, so two equal-looking arrays are not ===; compare their contents yourself. And == converts types before it compares ('1' == 1 is true), which is why JavaScript code uses ===.

Default arguments. Python evaluates a default once, when the function is defined, so the same list is shared by every call. JavaScript evaluates a default at every call that needs it, so add(2) gets a fresh [], and the famous mutable-default bug does not exist.

Key order. A Python dict keeps insertion order for every key. A JavaScript object lists keys that look like array indices first, in numeric order, and then the other keys in insertion order, which ECMA-262 specifies. Object keys are also always strings or symbols: obj[1] and obj['1'] are the same entry. A Map keeps insertion order and the type of every key, so a Map is the true counterpart of a dict whose keys are not plain words.

Python Online Compiler Run the Python side of these examples in your browser and change the questions.

Python idioms, translated

Python JavaScript
[x * 2 for x in xs if x > 0] xs.filter((x) => x > 0).map((x) => x * 2)
{k: v for k, v in pairs} Object.fromEntries(pairs), or new Map(pairs)
for i, x in enumerate(xs): for (const [i, x] of xs.entries())
for k, v in d.items(): for (const [k, v] of map), or Object.entries(obj) for an object
len(xs), len(d) xs.length, map.size
range(5) for (let i = 0; i < 5; i++), or Array.from({ length: 5 }, (_, i) => i)
f"{name} owes {amount}" `${name} owes ${amount}`
None null for “no value on purpose”; undefined is what missing properties and arguments give you
x is None x === null, or x == null to accept undefined too
set(xs), a | b, a & b new Set(xs), a.union(b), a.intersection(b) (ECMAScript 2025)
raise ValueError("…") throw new RangeError('…'), or TypeError for a wrong kind of value
try: … except ValueError as e: … try { … } catch (e) { if (!(e instanceof RangeError)) throw e; … }
isinstance(x, list) Array.isArray(x); typeof x === 'string' for primitives; x instanceof Map for objects
A tuple An array; Object.freeze stops changes, but there is no tuple type

Two Python tools have no direct counterpart in Node.js 24: zip (an Iterator.zip is planned for ECMAScript 2027) and math.fsum, whose counterpart Math.sumPrecise is part of ECMAScript 2026 but not yet in Node.js 24. A short loop does the job of either.

Methods and this

In Python a method taken off its object stays bound to it. In JavaScript it does not: the object a method works on, this, is decided by how the function is called, not where it was defined.

A method taken off its object

Python · bound.py

# A method taken off its object still knows the object in Python: it is a bound method.
class Counter:
    def __init__(self):
        self.n = 0

    def tick(self):
        self.n += 1
        return self.n


counter = Counter()
tick = counter.tick
print("tick() twice:", tick(), tick())

Output

tick() twice: 1 2

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 bound.py

JavaScript · bound.mjs

// The same move in JavaScript: a method taken off its object forgets the object.
class Counter {
  n = 0;

  tick() {
    this.n += 1;
    return this.n;
  }
}

const counter = new Counter();
const tick = counter.tick;
try {
  tick();
} catch (error) {
  console.log('tick() on its own:', error.name, '(this is undefined)');
}
const bound = counter.tick.bind(counter);
console.log('bound tick() twice:', bound(), bound());

Output

tick() on its own: TypeError (this is undefined)
bound tick() twice: 1 2

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node bound.mjs

Called as tick(), the function has no object in front of it, so this is undefined (modules are strict) and reading this.n throws. Passing counter.tick to setTimeout or map loses the object in the same way, and an event listener calls it with the element as this instead. counter.tick.bind(counter) makes a copy with this fixed, and an arrow function, () => counter.tick(), keeps the call in the form counter.tick(). The Java lesson of this module looks at this from another side.

async and await: the same words, another start

Both languages write async def or async function and await, but they start the work at different times:

When does an async function begin?

Python · async_start.py

# When does an async function start? In Python, only once it is awaited or scheduled.
import asyncio


async def fetch_data():
    print("fetch_data starts")
    await asyncio.sleep(0)
    print("fetch_data resumes")
    return 42


async def main():
    print("before the call")
    pending = fetch_data()
    print("after the call, before await")
    print("result:", await pending)


asyncio.run(main())

Output

before the call
after the call, before await
fetch_data starts
fetch_data resumes
result: 42

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 async_start.py

JavaScript · async-start.mjs

// When does an async function start? In JavaScript, at once: it runs until its first await.
async function fetchData() {
  console.log('fetchData starts');
  await null;
  console.log('fetchData resumes');
  return 42;
}

console.log('before the call');
const pending = fetchData();
console.log('after the call, before await');
console.log('result:', await pending);

Output

before the call
fetchData starts
after the call, before await
fetchData resumes
result: 42

Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node async-start.mjs

In Python, calling fetch_data() only creates a coroutine object, and the asyncio documentation stresses that calling a coroutine does not schedule it; its body starts when it is awaited. In JavaScript, calling fetchData() runs its body at once, up to the first await, and returns a promise for the rest. Three consequences matter when you port code:

  • There is no asyncio.run. Browsers and Node.js run an event loop all the time, so you call an async function and await its promise, at the top level of a module if you like.
  • Work starts when you call, not when you await. const a = load(1); const b = load(2); starts both loads at once, and await Promise.all([a, b]) collects them, much like asyncio.gather.
  • A promise that fails while nobody waits for it is not silent. Since Node.js 15 an unhandled rejection ends the process with an error by default, so every promise you start must eventually be awaited or handled.

Exercise: port an expense report

This is a small Python function that totals a trip’s expenses per category, in paise so that no rounding creeps in. It runs on Python 3.14.8:

totals.py: the Python version to port Python · totals.py
# The function to port: total a trip's expenses per category, in paise (whole numbers, so no rounding errors).
def totals_by_category(expenses):
    """Returns (category, total) pairs, largest total first, then by category name."""
    totals = {}
    for expense in expenses:
        amount = expense["amount_paise"]
        if not isinstance(amount, int) or isinstance(amount, bool):
            raise TypeError(f"amount must be a whole number of paise, got {amount!r}")
        category = expense.get("category") or "other"
        totals[category] = totals.get(category, 0) + amount
    return sorted(totals.items(), key=lambda pair: (-pair[1], pair[0]))


trip = [
    {"category": "food", "amount_paise": 45000},
    {"category": "travel", "amount_paise": 120000},
    {"category": "food", "amount_paise": 18050},
    {"category": "", "amount_paise": 9900},
    {"category": "travel", "amount_paise": -20000},
]
print(totals_by_category(trip))
print(totals_by_category([]))
try:
    totals_by_category([{"category": "food", "amount_paise": 12.5}])
except TypeError as error:
    print("TypeError:", error)

Output

[('travel', 100000), ('food', 63050), ('other', 9900)]
[]
TypeError: amount must be a whole number of paise, got 12.5

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 totals.py

Port it to JavaScript. The sample tests check the cases where a word-for-word port goes wrong: the comparator, the empty category, refunds and an amount that is not a whole number.

Exercise · Medium · JavaScript

Port a Python expense report to JavaScript

Port totals_by_category from the lesson's totals.py to JavaScript as totalsByCategory(expenses). Each expense is an object { category, amountPaise }; the function returns [category, total] pairs, largest total first, and pairs with the same total in alphabetical order of their category, exactly as the Python version does:

  • a missing or empty category counts as "other";
  • negative amounts are refunds and are added like the others;
  • an amount that is not a whole number throws a TypeError whose message starts with amount must be a whole number of paise;
  • no expenses give an empty array.

Watch the three places where a word-for-word port goes wrong: what sort does without a comparator, which values count as false, and how to recognise a whole number when JavaScript has one number type.

Starter code · totals.mjs

/**
 * A trip's expenses totalled per category, in paise.
 * @param {{ category?: string, amountPaise: number }[]} expenses
 * @returns {[string, number][]} pairs, largest total first, then by category name
 */
export function totalsByCategory(expenses) {
  return [];
}
The sample tests · totals.test.mjs
import { test, assert } from 'mysmartcopilot:test';
import { totalsByCategory } from './totals.mjs';

test('totals each category and puts the largest first', () => {
  const trip = [
    { category: 'food', amountPaise: 45000 },
    { category: 'travel', amountPaise: 120000 },
    { category: 'food', amountPaise: 18050 },
  ];
  assert.deepEqual(totalsByCategory(trip), [['travel', 120000], ['food', 63050]]);
});

test('sorts by the number, not by its digits', () => {
  const trip = [{ category: 'a', amountPaise: 900 }, { category: 'b', amountPaise: 10000 }];
  assert.deepEqual(totalsByCategory(trip), [['b', 10000], ['a', 900]]);
});

test('three categories come out by total, not in the order they were added', () => {
  const trip = [
    { category: 'stay', amountPaise: 500 },
    { category: 'food', amountPaise: 900 },
    { category: 'travel', amountPaise: 100 },
  ];
  assert.deepEqual(totalsByCategory(trip), [['food', 900], ['stay', 500], ['travel', 100]]);
});

test('equal totals are in alphabetical order of the category', () => {
  const two = [{ category: 'stay', amountPaise: 500 }, { category: 'food', amountPaise: 500 }];
  assert.deepEqual(totalsByCategory(two), [['food', 500], ['stay', 500]]);
  const three = [
    { category: 'stay', amountPaise: 500 },
    { category: 'food', amountPaise: 500 },
    { category: 'misc', amountPaise: 500 },
  ];
  assert.deepEqual(totalsByCategory(three), [['food', 500], ['misc', 500], ['stay', 500]]);
});

test('refunds subtract, and a missing or empty category is "other"', () => {
  const trip = [
    { category: 'travel', amountPaise: 120000 },
    { category: 'travel', amountPaise: -20000 },
    { amountPaise: 700 },
    { category: '', amountPaise: 300 },
  ];
  assert.deepEqual(totalsByCategory(trip), [['travel', 100000], ['other', 1000]]);
});

test('no expenses give an empty array', () => {
  assert.deepEqual(totalsByCategory([]), []);
});

test('an amount with paise fractions is rejected with a TypeError', () => {
  assert.throws(() => totalsByCategory([{ category: 'food', amountPaise: 12.5 }]), TypeError);
});
A hint

A Map keeps your categories in a dictionary the way Python's dict does: totals.get(key) ?? 0 plays the part of totals.get(key, 0), and [...totals] gives the pairs. Number.isInteger(x) is the test for a whole number. And sort needs a comparator that returns a number: (a, b) => b[1] - a[1] for the totals, then a second key for ties.

The sample tests run on this device, in your browser (QuickJS): nothing is sent to mysmartcopilot.com. The first run downloads JavaScript (about 0.6 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Check yourself

7 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.

  1. Question 1 of 7 What does if ([]) console.log('yes'); else console.log('no'); print in JavaScript?

    Choose one answer.

    Show the answer to question 1

    Answer: yes, because an empty array is an object, and every object is truthy

    Only eight values are falsy in JavaScript: false, 0, -0, 0n, "", null, undefined and NaN. Arrays and objects are truthy even when empty, so test items.length > 0 when you mean "has items".

  2. Question 2 of 7 A Python developer writes const half = 7 // 2 in JavaScript. What is half?

    Choose one answer.

    Show the answer to question 2

    Answer: 7, because // starts a comment, so the line is const half = 7

    JavaScript has no floor-division operator; // begins a line comment. Write Math.floor(7 / 2), which also matches Python for negative numbers, or Math.trunc(7 / 2) to round towards zero.

  3. Question 3 of 7 What is -7 % 3 in JavaScript?

    Choose one answer.

    Show the answer to question 3

    Answer: -1

    JavaScript's % keeps the sign of the dividend, -7, so the result is -1. Python's % keeps the sign of the divisor and gives 2. For a result from 0 to n − 1, write ((x % n) + n) % n.

  4. Question 4 of 7 Which expression asks whether the array names contains the string "Asha"?

    Choose one answer.

    Show the answer to question 4

    Answer: names.includes("Asha")

    in checks for a property key, and an array's keys are its indices, so "Asha" in names is false even when the name is there. Arrays have includes; has belongs to Set and Map.

  5. Question 5 of 7 In what order did the JavaScript version of "When does an async function begin?" print its lines?

    What does this program print? Choose one answer.

    // When does an async function start? In JavaScript, at once: it runs until its first await.
    async function fetchData() {
      console.log('fetchData starts');
      await null;
      console.log('fetchData resumes');
      return 42;
    }
    
    console.log('before the call');
    const pending = fetchData();
    console.log('after the call, before await');
    console.log('result:', await pending);
    Show the answer to question 5

    Answer: it prints

    before the call
    fetchData starts
    after the call, before await
    fetchData resumes
    result: 42

    Calling an async function in JavaScript runs its body at once, up to the first await, so "fetchData starts" comes before the line after the call. The second order is what Python printed, because calling a coroutine function only creates a coroutine, which starts when it is awaited.

  6. Question 6 of 7 In JavaScript, function add(item, items = []) { items.push(item); return items; } is called as add(1) and then add(2). What does the second call return?

    Choose one answer.

    Show the answer to question 6

    Answer: [2], because the default is evaluated again at each call

    JavaScript evaluates a default parameter at every call that needs it, so each call without a second argument gets a new array. Python evaluates a default once, when the function is defined, which causes the mutable-default bug.

  7. Question 7 of 7 In the example "The same questions to Python and JavaScript", how many of the nine questions got different answers in the two languages?

    Type a number.

    Show the answer to question 7

    Answer: 8

    Only "7 divided by 2, rounded down" gave 3 in both. Precision, remainder, truthiness, default sorting, in, equality of arrays, default arguments and key order all differ.

Interview questions

Fresher · Why does [10, 9, 1].sort() return [1, 10, 9] in JavaScript?

Because without a comparator sort turns each element into a string and orders those strings by their UTF-16 code units, the way a dictionary orders words. "1" comes first, then "10", because a shorter prefix sorts before a longer string, and "9" last: the numbers are never compared as numbers. Give it a comparator whose result says which item goes first, below zero, zero or above zero: [10, 9, 1].sort((a, b) => a - b) gives [1, 9, 10], and (a, b) => b - a sorts from largest to smallest. Two details complete the answer. sort reorders the array itself, while toSorted returns a sorted copy. And since ECMAScript 2019 the specification requires a stable sort, so items that compare as equal stay in their original order. A Python developer expects numeric order because Python compares the values themselves.

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Mid to senior

    You are porting a Python service to Node.js. It totals invoice amounts and counts items in dicts keyed by integer product ids, which arrive as JSON. Which differences in numbers and dictionaries can silently change its results, and how do you guard against each one?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Fresher to mid

    An asyncio script is ported to Node.js line by line. Some async functions were called without await, which did nothing in Python, and the port now runs them, in another order, and sometimes crashes with an unhandled rejection. Explain what happens and how to port the script correctly.

    Model answer, Pro. First step and follow-ups

Key takeaways

  • Numbers are doubles: integers are exact only up to 2⁵³ − 1. Use BigInt for larger exact integers and whole paise or cents for money.
  • % keeps the sign of the dividend, // is a comment, and empty arrays and objects are truthy.
  • sort() compares as strings unless you pass a comparator; in checks keys and indices; === compares objects by identity.
  • Defaults are evaluated at each call, objects put number-like keys first, and a Map is the counterpart of a dict.
  • A detached method loses this, an async function starts when called, and an unhandled rejection ends a Node.js process.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.