JavaScript offers three keywords for declaring variables: var, which is function-scoped, and let and const, both of which are block-scoped and were introduced in ES6. const declares a binding that cannot be reassigned, while let allows reassignment within its block. The language has seven primitive data types: string, number, bigint, boolean, undefined, null, and symbol. Primitives are immutable values, and you can identify a value's type with the typeof operator, which returns a string such as 'string' when given 'hello'.
A frequent source of confusion is the difference between null and undefined. null represents an intentional absence of a value, whereas undefined means a variable has been declared but not yet assigned. Interestingly, typeof null returns 'object', a long-standing historical bug in the language. JavaScript also performs automatic type coercion, converting values between types in operations such as '5' + 1, which yields the string '51'. To avoid surprises from coercion, developers are encouraged to use === for strict equality instead of ==, because === compares both value and type without converting them.
JavaScript provides the usual arithmetic operators—+, -, *, /, % (modulus), and ** (exponentiation)—all of which work on numbers. Comparison operators such as ==, ===, !=, !==, and the relational operators all return a boolean (true or false). Logical operators && (AND), || (OR), and ! (NOT) perform boolean logic and enable short-circuit evaluation, which is the basis for idiomatic patterns such as value && doSomething().