Skip to main content

·

[JS/TS] Do I Truly Understand the Programming Languages I Use?

What Is a Programming Language?

Hey everyone, long time no see! I'm back again with a new article in my in-depth Backend series, focusing specifically on Node.js. Through this series, I hope to share my personal knowledge and experience, and I also welcome your feedback and contributions so we can continue learning and improving together.
For this Node.js series, I want to start with something fundamental: programming languages.
Whether you're working in Backend, Software Engineering, IoT, AI, Blockchain, or other areas of the tech industry, programming languages are essential tools of the trade. But have you ever stopped to ask yourself whether you truly understand the programming language you use?
Before writing this article, my answer was "NO." After putting it together, I feel that I've gained a little more insight into the language I work with every day. I hope you'll share your thoughts and help us develop a deeper understanding of programming languages together.

What Is a Programming Language?

At its most basic, a programming language is a "language" used for "programming" (sad but true :))).
More specifically, it acts as an intermediary that allows developers to communicate with computers.
As we all know, computers fundamentally operate on binary data consisting of 0s and 1s. It would be extremely difficult for humans to issue commands directly in binary or interpret the information returned by computers in that form.
We need a more user-friendly tool: something easy to read, write, and understand, and closer to the languages we use in everyday communication, while still being translatable into instructions that computers can execute.
That's where programming languages come in. They provide a way to express instructions at a higher level of abstraction and translate them into machine-executable instructions.

Why Did I Choose This Programming Language?

Before answering this question, let's acknowledge that many of us don't initially get to choose which programming language we use. Circumstances often make that decision for us.
Perhaps it's the language introduced in your university curriculum that you're required to learn, or the language your manager or client asks you to use for a project.
Once you move beyond these circumstances and reach a point where you can make your own choices, have you ever looked back and asked yourself: Why did I—or my company—choose this programming language?
Today, many programming languages exist to serve different tasks and requirements. Even within the same field, developers have a wide variety of languages to choose from. So how do we decide why one language is a better fit than another?
  • The first factor I consider when exploring a programming language is its execution model. Is it interpreted or compiled? This can significantly affect performance, as well as how execution flows and how types are inferred or handled. Understanding these differences helps us anticipate potential issues later on.
    • ![Untitled]
  • The second factor is which programming paradigms the language supports and is best suited for: functional programming, object-oriented programming, event-driven programming, and so on.
  • The final factor is developer-friendliness: how readable the syntax is, how easy the language is to learn and use, and whether it has a sufficiently large and supportive community.
With these factors in mind, I'll focus on the two programming languages I use most frequently in my role as a Backend Node.js Engineer: JavaScript and TypeScript.
Let's explore them together!
![Untitled]

What Is JavaScript?

Concept

  • JavaScript uses a hybrid execution approach: it can be interpreted and also compiled just in time (JIT) by engines such as V8 and Chakra.
  • It was originally developed to run in browsers and create dynamic, interactive web pages.
  • It can also run on servers through runtimes powered by engines such as V8.
  • It supports multiple programming paradigms, including functional, object-oriented, and event-driven programming.

Key Characteristics

When discussing plain JavaScript, particularly the ES5 era, there are three key characteristics worth understanding.

1. Prototypes

In traditional JavaScript, the prototype-based inheritance model is fundamental. Unlike languages built around class-based inheritance, JavaScript uses prototypes to enable objects to inherit properties and behavior.
Functions are also objects in JavaScript. A function's prototype property can define properties that instances created through that function can inherit.
![Untitled]
The example above creates a constructor function named Person(_age, _name). The function's prototype object contains a property called height.
Therefore, an object created using this constructor can access three properties: age, name, and height.

2. Dynamic Types

Dynamic typing means that a variable's type is determined at runtime rather than being fixed through an explicit declaration.
let a = 0; a = "string"; // no error a = {}; // no error
In this example, the variable a can hold a number, a string, or an object without requiring a separate variable declaration for each type.

3. Constructor Functions

A constructor function is a special type of function used to initialize object instances. It uses the this keyword to assign properties to the newly created object and is typically invoked with the new operator.
// Constructor function User(name, age) { this.name = name; this.age = age; } var user1 = new User('Bob', 25); var user2 = new User('Alice', 27);
Here, User serves as a constructor function for creating user objects.

JavaScript ES6, ES7, ECMAScript 2015, and ECMAScript 2016: What Are They?

When working with JavaScript, we often encounter terms such as ES6, ES7, ECMAScript 2015 (ES2015), and ECMAScript 2016 (ES2016).
What do they actually mean?
Simply put, these are names for different editions of the ECMAScript specification, which defines the standards and features of JavaScript.

JavaScript Versions

Version
Release Date
Major Changes Compared with the Previous Version
Author
1
June 1997
The first edition.
Guy L. Steele Jr.
2
June 1998
Changes to align the specification with the international ISO/IEC 16262 standard.
Mike Cowlishaw
3
December 1999
Added regular expressions, improved string handling, introduced new control statements and exception handling, clarified error definitions, improved numeric output formatting, and introduced other enhancements.
Mike Cowlishaw
4
—
The fourth edition was abandoned because of disagreements and complexity surrounding the language's structure. Many proposed features were dropped.
—
5
December 2009
Introduced strict mode for more rigorous error checking and avoidance of problematic constructs. Clarified ambiguities in the third edition and addressed differences between the specification and real-world implementations. Added features such as getters and setters, JSON support, and improved object-property reflection.
Pratap Lakshman, Allen Wirfs-Brock
5.1
June 2011
Updated the specification to align with the ISO/IEC 16262:2011 international standard.
Pratap Lakshman, Allen Wirfs-Brock
6
June 2015
Initially called ECMAScript 6 (ES6), later renamed ECMAScript 2015 (ES2015). Introduced major syntax improvements for complex applications, including classes and modules, as well as for...of loops, arrow functions, binary data, promises, mathematical enhancements, reflection, and metaprogramming features.
Allen Wirfs-Brock
7
June 2016
Also known as ECMAScript 2016 (ES2016). Continued the language's evolution with two notable additions: the exponentiation operator and Array.prototype.includes().
Brian Terlson
Among these versions, two particularly popular milestones are ES6 (2015) and ES7 (2016).
Their notable features include:
  • ES6: Classes, modules, for...of loops, arrow functions, binary data, promises, numeric and mathematical enhancements, reflection, and more.
  • ES7: The exponentiation operator (*) and Array.prototype.includes().

Notable ES6 Features

1. Block-Scoped Variables: let and const

ES6 introduced let and const as alternatives to var for declaring variables.
  • var has function scope, or global scope when declared outside a function.
  • let allows a variable to be reassigned and is scoped to its enclosing block.
  • const declares a block-scoped binding that cannot be reassigned.
These declarations help developers control variable scope and distinguish between values that can be reassigned and bindings that should remain constant.

2. Arrow Functions

Arrow functions provide a more concise syntax for writing functions.
They also behave differently from traditional functions when it comes to this, making them particularly useful in callbacks.
When using arrow functions, keep these three limitations in mind:
  • They do not have their own this, arguments, or super bindings.
  • They cannot be used as constructors with the new operator.
  • They cannot use yield directly unless defined as generator functions—which arrow functions cannot be.
const materials = [ 'Hydrogen', 'Helium', 'Lithium', 'Beryllium' ]; console.log(materials.map(material => material.length)); // Expected output: Array [8, 6, 7, 9]
In this example, the arrow function provides a concise way to return the length of each string in the array.

3. Rest Parameters

Rest parameters provide a concise way to represent an arbitrary number of function arguments as an array, using the ... syntax.
function sum(...theArgs) { let total = 0; for (const arg of theArgs) { total += arg; } return total; } console.log(sum(1, 2, 3)); // Expected output: 6 console.log(sum(1, 2, 3, 4)); // Expected output: 10
The ...theArgs parameter collects all arguments passed to the function into an array, allowing the function to handle a variable number of inputs.

4. Destructuring Assignment in ES6

Destructuring allows multiple variables to be declared and assigned values from an array or object in a concise way.
let [a, b, c] = [1, 2, 3];
Here, a, b, and c are assigned the values 1, 2, and 3, respectively.

5. Default Parameters in ES6

ES6 allows us to specify default values directly in function parameter declarations.
function main(params = "default") { return params; }
If main() is called without an argument, params defaults to "default".

6. Template Literals in ES6

Template literals make it easier to embed variables and expressions inside strings by using ${...} syntax.
const name = "Kevin"; const last_name = "Nguyen"; console.log(`My name is ${name} ${last_name}`);
This approach is more readable than concatenating multiple strings and variables.

7. Multiline Strings in ES6

In ES5, creating multiline strings often required escape characters such as \n for line breaks and \t for tabs.
ES6 introduced template literals, which allow strings to span multiple lines directly using backticks.
var content = `hehemeomeo meomeohehe hemehemeo`;
The line breaks are preserved in the resulting string.

8. Enhanced Object Literals in ES6

ES6 introduced several improvements to object literal syntax.
Property value shorthand
When a variable and an object property share the same name, you can omit the repeated property name and value.
function createSinger(name, age, address, salary) { return { name, age, address, salary, ... }; }
This shorthand makes object creation more concise.
Computed property keys
You can also dynamically generate property names using expressions enclosed in square brackets.
function createSinger(name, age, address, salary) { return { ['salaryOf' + name]: salary, }; }
For example, if name is "Kevin", the generated property name will be salaryOfKevin.

9. Promises in ES6

The concept of a Promise—essentially, a representation of an eventual result—was a major addition in ES6.
Before Promises, developers commonly relied on callbacks in ES5. Asynchronous code written with deeply nested callbacks could become difficult to read and maintain, a problem often referred to as callback hell.
Promises provide a more structured approach to handling asynchronous operations. I'll save a more detailed discussion of this topic for a future article.
![Untitled]

10. Classes in ES6

As mentioned earlier, JavaScript traditionally relied on prototype-based inheritance rather than class-based inheritance.
With ES6, the class syntax was introduced, making object-oriented programming more familiar to developers coming from languages such as Java or C++.
Although the syntax resembles class-based languages, JavaScript classes still use prototype-based inheritance under the hood.
Developers familiar with OOP can therefore work with JavaScript classes using a more recognizable syntax.
// Declaration class Rectangle { constructor(height, width) { this.height = height; this.width = width; } } // Expression; the class is anonymous but assigned to a variable const Rectangle = class { constructor(height, width) { this.height = height; this.width = width; } }; // Expression; the class has its own name const Rectangle = class Rectangle2 { constructor(height, width) { this.height = height; this.width = width; } };
These examples demonstrate different ways to define a class in JavaScript.

What Is TypeScript?

Concept

TypeScript is an open-source programming language developed by Microsoft to address some of JavaScript's limitations, particularly around type safety and large-scale application development.
TypeScript code is compiled into JavaScript before execution, allowing it to run in JavaScript environments such as browsers and Node.js.

Key Characteristics

When working with TypeScript, there are three key characteristics worth understanding.
  • Static Typing: Unlike JavaScript's dynamic typing, TypeScript supports static type checking. Developers can specify the expected types of variables and other values, allowing many type-related errors to be detected before the code runs. This improves consistency and makes application logic easier to reason about.
  • Interfaces: TypeScript supports interfaces, which define contracts for the structure of objects. They help ensure consistency when working with data structures across different parts of an application.
  • Generics: Generics are one of TypeScript's powerful features, but they can also be challenging to understand because of their complexity. They allow developers to write reusable code that works with different types while preserving type information.
For example:
class GenericNumber<NumType> { zeroValue: NumType; add: (x: NumType, y: NumType) => NumType; }
We can then create instances using different types.
let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function (x, y) { return x + y; };
Or use the same generic class with strings:
let stringNumeric = new GenericNumber<string>(); stringNumeric.zeroValue = ""; stringNumeric.add = function (x, y) { return x + y; };
We can then call the method:
console.log( stringNumeric.add(stringNumeric.zeroValue, "test") );
This example demonstrates generics in TypeScript. A generic class can be reused with different data types while maintaining type information, without having to define an entirely separate implementation for each type.

Features of TypeScript

Some notable features of TypeScript include:
  • Cross-Platform: The TypeScript compiler can be installed and used on operating systems such as Windows, macOS, and Linux.
  • Object-Oriented Programming: TypeScript provides features such as classes, interfaces, and modules, making it easier to apply object-oriented programming on both the client side and the server side.
  • Static Type Checking: TypeScript checks types during compilation, helping developers identify many errors while writing code, without having to execute it first.
  • Optional Static Typing: TypeScript allows developers to choose how explicitly they want to specify types. It supports type annotations when desired, while also providing type inference and the flexibility to work with dynamic values, similar to JavaScript.
  • DOM Manipulation: TypeScript can be used to interact with the Document Object Model (DOM), allowing developers to add, modify, or remove page elements while benefiting from type checking.
  • ES6 Features: TypeScript supports modern ECMAScript features, including classes, arrow functions, modules, and other language constructs.
![Untitled]

In Conclusion

Ultimately, these are just some of the pieces of knowledge I've gathered throughout my work and personal learning journey.
Mistakes and inaccuracies are inevitable, so if you have anything to add or correct, please leave a comment below. Let's help each other build a deeper and more accurate understanding of these technologies.
I'm Anhkolamgidauanhthe, and I've recently built a blog to bring together articles I've published across various tech and lifestyle forums over the past year.
Feel free to stop by, leave a comment on any article that interests you, or reach out if you'd like to grab a coffee and chat about something we have in common. ^^
HAPPY CODING!!!

Subscribe to the newsletter

Get new posts on Backend, Blockchain, DevOps, and life notes.

Loading Comments...