PHICYGNI

JavaScript for Python developers


JavaScript is similar to Python in many ways but there are some subtle differences one should definitely be aware of when first learning the language. Presented here are some of the most important and counter intuitive differences when approaching JavaScript from a Python perspective.



Table of Contents

  1. Introduction
  2. Truthy differences
  3. "In" keyword differences
  4. Nullish coalescing to test for null and undefined
  5. Array copy using spread syntax
  6. Negative array indices
  7. List and Array differences
  8. Python map with lambda equivalent
  9. Integer range
  10. Conclusion
  11. References

Introduction


JavaScript is one of the most ubiquitous languages in the world today [1, 2]. It is useful for not only front-end development but also for back-end functionality and therefore definitely a language almost all developers should know. If you are a Python developer learning JavaScript for the first time here are some tips and notable differences to help get up to speed and also avoid some potentially head-scratching bugs.


Truthy differences


One of the most important differences between Python and JavaScript is related to how values are evaluated using truthy and falsy syntax. For instance, in Python empty dictionaries and lists evaluate to a False boolean value whereas in JavaScript empty objects evaluate to a True value [3, 4]. In the example below take note how the nearly identical sets of code produce different results:


The Python code


#!/usr/bin/env python3.8
""" Python code - we can use truthy and falsy
evaluation to determine if dictionaries and
lists are empty or not.

"""

dctA = {}
# This will print False
print(True if (dctA) else False)

dctA = {'Name': 'John'}
# This will print True
print(True if (dctA) else False)

lstA = []
# This will print False
print(True if (lstA) else False)

lstA = [1, 2, 3]
# This will print True
print(True if (lstA) else False)


The JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - when we use truthy and falsy
* evaluation to determine if an object is empty
* we get the wrong result.
*/

objA = {};
// This will print true
console.log(objA ? true : false);

objA = { Name: 'John' };
// This will also print true
console.log(objA ? true : false);

objA = [];
// This will print true
console.log(objA ? true : false);

objA = [1, 2, 3];
// This will also print true
console.log(objA ? true : false);

Coming for Python perspective it is counter-intuitive for an empty JavaScript object to evaluate to a True value. This could potentially lead to some very unexpected bugs for those coming from a Python background going by assumption alone. Truthy evaluation, in JavaScript therefore, cannot be used to determine if an object is empty or not. The length property should be used instead as in the example below [5]:


The equivalent JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - We need to use the length
* property of an object to determine if it is
* empty or not.
*/

objA = {};
// This will print false
console.log(Object.keys(objA).length > 0 ? true : false);

objA = { Name: 'John' };
// This will print true
console.log(Object.keys(objA).length > 0 ? true : false);

objA = [];
// This will print false
console.log(objA.length > 0 ? true : false);

objA = [1, 2, 3];
// This will print true
console.log(objA.length > 0 ? true : false);

"In" keyword differences


In Python one is able to use the ‘in’ keyword to determine if an element is present in a list. In JavaScript, however, the same keyword will produce a different result compared to Python. See the example below:


The Python code


#!/usr/bin/python3.8
""" Python code - we can use the "in" keyword
in order to determine if an element is
present in a list.

"""

lstA = [10, 11, 12]
# This will print True
print(11 in lstA)
# This will print False
print(13 in lstA)


The JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - the "in" keyword does not
* produce the same result as the Python code.
*/

objA = [10, 11, 12];
// This will print false
console.log(11 in objA);
// This will print false
console.log(13 in objA);

The in keyword from the JavaScript code does not produce the same result as the Python equivalent. This is because the ‘in’ keyword in JavaScript cannot be used to determine if the value is present or not. It can only be used to determine if the index is present [6]. In JavaScript one should use the find() method to determine if a value is present in an array object as in this example [7]:


The equivalent JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - to replicate the Python "in"
* keyword functionality we need to use the JavaScript
* "find" method.
*/

objA = [10, 11, 12];
// This will print true
console.log(typeof objA.find((nItem) => nItem === 11) !== 'undefined');
// This will print false
console.log(typeof objA.find((nItem) => nItem === 13) !== 'undefined');


Nullish coalescing to test for null and undefined


In Python one can force a default when a value is None by using the ‘is’ operator and combining it with the ternary operator as in this example:


The Python code


#!/usr/bin/env python3.8
""" Python code - we can use the is operator combined
with ternary operator to determine if a function
returned a None value

"""


def dctDodgyFunc():
""" We have a function which returns
None when it should not do so.

Returns:
(None):
"""
return (None)


objA = dctDodgyFunc()
# This will correctly print out {}
print({} if objA is None else objA)


A default value will be returned when the value being tested is None. In JavaScript one might be tempted to try and mimic the same behaviour using the or (||) operator:


The JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - we cannot use the or (||)
* operator to determine if a function returned
* null or undefined because the right-hand side
* will be chosen over any falsy value.
*/

/**
* We have a function which
* adds two number together.
* 0 is a valid return value.
* @returns(number)
*/
const nAddFunc = (nA, nB) => {
return nA + nB;
};

nC = nAddFunc(-1, 1);
// This will incorrectly print out 'error'
console.log(nC || 'error');

The problem, however, is the right-hand side will be returned for any falsy left side value and not just for null or undefined. A more equivalent way of replicating the same Python behaviour would be to use the nullish coalescing operator “??” [8]. This operator returns the right-hand side value only when the left side is null or undefined which is more in line with the Python example above. Here’s an example of this in JavaScript:


The equivalent JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - we can the nullish coalescing
* operator to determine if a function returned
* null or undefined.
*/

/**
* We have a function which returns
* null when it should not.
* @returns(null)
*/
const nDodgyAddFunc = (nA, nB) => {
return null;
};

nC = nDodgyAddFunc(-1, 1);
// This will correctly print out 'error'
console.log(nC ?? 'error');

Array copy using spread syntax


In Python there are several ways to make a copy of a list. The one I use most often is the slicing colon operator (:). The equivalent in JavaScript is the spread operator (…) [9]. Here is an example demonstrating the functionality in both languages:


The Python code


#!/usr/bin/env python3.8
""" Python code - we can use the slicing colon
operator (:) in order to make a copy of a
list.

"""

lstA = [1, 2, 3, 4]

lstB = lstA[:]
# Will print [1, 2, 3, 4]
print(lstB)


The equivalent JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - in order to make a copy of
* an array we use the spread operator (...).
*/

objA = [1, 2, 3, 4];

objB = [...objA];
// This will print [ 1, 2, 3, 4 ]
console.log(objB);

Negative array indices


In Python it is possible to deference a list using a negative index. This is when we want to retrieve a value from a list using an index number counted downward from the right-hand side of the list. Here is an example:


The Python code


#!/usr/bin/env python3.8
""" Python code - we can use a negative index
value in order to dereference a list counting
downward from the right-hand side of the list.

"""

lstA = [1, 2, 3, 4, 5]

# This will print 5
print(lstA[-1])


In JavaScript, at first, it would seem it doesn’t provide the the same functionality for an array. However, by accessing the array with the at() method instead of brackets it is possible as seen in this example:


The equivalent JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - Different to Python we can
* only dereference an Array using a negative
* index if we make use of the "at" method.
*/

objA = [1, 2, 3, 4, 5];

// This will print undefined
console.log(objA[-1]);
// This will return 5
console.log(objA.at(-1));

List and Array differences


In Python one of the most useful Abstract Data Types (ADTs) is the list [10]. JavaScript provides the same ADT in the form of an Array but with methods which are sometimes named slightly differently to the Python equivalent [11]. Here is a table with the most notable differences and similarities:


Operation Python JavaScript
At item to end of list/array append(item) push(item)
Remove item from end of list/array pop() pop()
Add item at beginning of list/array insert(item, 0) unshift(item)
Remove item from the beginning of list/array pop(0) shift()
Sort list/array sort() sort()
Reverse items in list/array reverse() reverse()

Python map with lambda equivalent


In Python we can apply a function to an iterable by using the map function. We can, furthermore, combine this functionality with a lambda anonymous function to produce a list mapping consisting of just one line of code, as in this example:


The Python code


#!/usr/bin/env python3.8
""" Python code - we can produce a list mapping
from just one line of code by combining the
map function and an anonymous lambda fuction.

"""

lstA = list(range(10))

# This will print [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lstA)

lstB = list(map(lambda x: x + 1, lstA))

# This will print [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(lstB)


In JavaScript we have the same functionality available by combining the Array map method and an anonymous arrow function [12]. Here’s an example:


The equivalent JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - when we reproduce the same
* functionality as the python code by combining
* an Array map method with an anonymous arrow
* function.
*/

objA = [...Array(10).keys()];

// This will print [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
console.log(objA);

objB = objA.map((x) => x + 1);

// This will print [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(objB);


Integer range


In Python we can combine the range function with the list function to generate a list of in sequence integer numbers, as in this example:


The Python code


#!/usr/bin/env python3.8
""" Python code - we can generate a list of in
sequence integer numbers by using the range
function combined with the list function.
"""

lstA = list(range(10))

# This will print [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lstA)


In JavaScript we can recreate the same functionality by combining the Array function with the keys function as in this example:

The equivalent JavaScript code


#!/usr/bin/env node
/**
* JavaScript code - we can generate a list of in
* sequence integer numbers by using the Array
* function combined with the keys method.
*/

objA = [...Array(10).keys()];

// This will print [0,1,2,3,4,5,6,7,8,9]
console.log(objA);

Conclusion


Python and JavaScript are similar in many ways but there are subtle differences as shown in the examples above. Coming from a Python background one might assume the functionality is the same and then introduce bugs by using the same syntax or be unaware that the same functionality exists but in a different form. The above examples hopefully made it clear which differences are important and how to reproduce the same Python functionality in JavaScript.


References


[1] https://bootcamp.berkeley.edu/blog/most-in-demand-programming-languages/

[2] https://www.geeksforgeeks.org/top-10-programming-languages-to-learn-in-2022/

[3] https://www.freecodecamp.org/news/truthy-and-falsy-values-in-python/#-falsy-values

[4] https://developer.mozilla.org/en-US/docs/Glossary/Truthy

[5] https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object

[6] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in#basic_usage

[7] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

[8] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

[9] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#spread_in_array_literals

[10] https://docs.python.org/3/tutorial/datastructures.html

[11] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

[12] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map