cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

The rest of the operators

Finish JavaScript's operator toolbox: ternary choices, type checks, property checks, delete, bitwise flags, shifts, comma, void, and the precedence table.

By the end, you can
  • 01
    Choose expressions on purposeUse the ternary operator when it stays readable, and avoid clever nests.
  • 02
    Inspect values and propertiesPick between typeof, instanceof, Array.isArray, in, and Object.hasOwn.
  • 03
    Read rare operators safelyDecode bitwise flags, shifts, comma, void, and precedence without guessing.

The last operator map

You already know the everyday operators: arithmetic, assignment, comparisons, logical operators, ??, and optional chaining. This lesson finishes the operator map. Some of these operators are common, like the ternary. Some are rare, like void. A few are powerful but easy to misuse, like bitwise operators.

The goal is not to make your code clever. In the Coding style lesson you learned to avoid tricks that make readers pause. Here you will learn what these operators mean so you can read them in real code, choose the clear ones, and know when to reach for a named helper or an if statement instead.

The short version

Use the ternary for one small choice, use type and property checks deliberately, treat bitwise operators as 32-bit integer tools, and use parentheses when precedence is not obvious.

Real-life analogyOperators are tools on a pegboard

A good workshop has more tools than you use every day. You do not hammer with a voltage tester, and you do not use delete to remove an array item from the middle. Knowing the tool’s shape helps you pick the right one and recognize it when someone else used it.

In real life: A screwdriver used every day
In JavaScript: +, ===, &&, and ??
In real life: A compact pocket tool
In JavaScript: The ternary for one small expression choice
In real life: A voltage tester
In JavaScript: typeof, instanceof, in, and Object.hasOwn
In real life: A specialized bit driver
In JavaScript: Bitwise operators for flags and binary data

Where the analogy stops: A real tool has one physical job. Operators can be combined, and JavaScript may convert values before using them, so always check the exact language rule.

We will move from the friendly, expression-sized ternary to type checks, property checks, bitwise operators, shifts, comma, void, and a practical precedence table you can use while reading code.

The conditional (ternary) operator

STEP THROUGH

The conditional operator is the only JavaScript operator with three operands. Its shape is:

Ternary shapeJavaScript
condition ? valueIfTrue : valueIfFalse

Read it like a quick fork in the road: if the condition is truthy, JavaScript takes the left path after ?; otherwise it takes the right path after :. Because the whole thing is an expression, it produces a value. That means you can store it, return it, or put it inside a template literal.

Real-life analogyA ternary is a quick fork in the road

Imagine a staff member checking an age and handing out one of two wristbands. There is no long conversation: one question, one of two answers. That is the sweet spot for a ternary.

In real life: The sign: “Age 18 or older?”
In JavaScript: The condition: age >= 18
In real life: Left path: adult wristband
In JavaScript: The true branch: "adult"
In real life: Right path: minor wristband
In JavaScript: The false branch: "minor"
In real life: The wristband you leave with
In JavaScript: The expression’s final value

Where the analogy stops: A real road can split into many paths. A ternary is best for one small two-way choice; nested ternaries quickly become hard to read.

Choose one expression with ? :
Step 0 of 5Ready
Your turn: follow the blue line

Predict which branch the condition chooses. Then step through the expression one event at a time.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
const label = age >= 18 ? "adult" : "minor";const sentence = `This visitor is an ${label}.`;console.log(sentence);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Change line 1: what age should the ternary test?

Changing the input starts a fresh run. Predict line 2 before you step again.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

A good ternary reads in one breath:

A clear expressionPop out in the code editor (opens in a new tab)JavaScript
const shipping = cartTotal >= 500 ? "free" : "₹50";
console.log(`Shipping is ${shipping}.`);

A nested ternary asks the reader to hold several forks in their head:

Prefer if/else when choices stack upPop out in the code editor (opens in a new tab)JavaScript
const label = score >= 90 ? "A" : score >= 80 ? "B" : "keep practicing";

let readableLabel;
if (score >= 90) {
  readableLabel = "A";
} else if (score >= 80) {
  readableLabel = "B";
} else {
  readableLabel = "keep practicing";
}

The next lesson is if, else & conditions. For now, use this rule: ternary for a small value choice; if / else when the logic needs room.

typeof & instanceof

STEP THROUGH

typeof asks, “what kind of value is this?” It is most useful for primitives: "string", "number", "boolean", "bigint", "symbol", "undefined", and "function". For most objects, it simply says "object".

instanceof asks a different question: “does this object come from this constructor’s family tree?” That is a simple way to use it today. The prototype chain lesson later explains the exact chain it walks.

Ask values what they are
Step 0 of 6Ready
Your turn: follow the blue line

Step through the checks. Notice where typeof, instanceof, and Array.isArray answer different questions.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
console.log(typeof values[0]);console.log(Array.isArray(values[1]));console.log(values[1] instanceof Array);console.log(values[1] instanceof Object);console.log(values[3] instanceof String);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Choosing a type check
QuestionGood checkWatch out
Is it a primitive string?typeof value === "string"new String("x") is an object, not a primitive.
Is it missing?value === null or value === undefinedtypeof null is the old quirk "object".
Is it an array?Array.isArray(value)typeof [] is "object".
Was it made by a constructor?value instanceof DateDifferent browser frames can have different constructors; learn the nuance later.
Fun fact: typeof null is still object

This is a very old JavaScript bug that cannot be changed without breaking existing websites. The Data types lesson introduced it; here you saw why professional code checks null directly.

in & delete

STEP THROUGH

"key" in object checks whether a property is available on an object. It includes inherited properties, so it answers “can this key be found?” not “did this object define the key itself?” For own properties, use Object.hasOwn(object, "key").

delete object.key removes a configurable property. It is useful for object dictionaries, but not for normal array removal: deleting an array element leaves a hole and keeps the same length.

Check and remove keys
Step 0 of 10Ready
Your turn: follow the blue line

Follow in, Object.hasOwn, and delete. Watch the array hole: length and existing keys are different ideas.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
console.log("name" in user);console.log("toString" in user);console.log(Object.hasOwn(user, "toString"));delete user.age;console.log("age" in user);const letters = ["a", "b", "c"];delete letters[1];console.log(letters.length);console.log(1 in letters);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Strict mode and undeletable properties

Some built-in properties are not configurable. For example, delete Object.prototype evaluates to false in sloppy scripts and throws a TypeError in strict mode. Modern modules are strict by default, so failed deletes are often loud instead of silent.

in compared with Object.hasOwn
CheckIncludes inherited keys?Beginner-friendly use
"name" in userYesFeature checks or cases where inherited methods count.
Object.hasOwn(user, "name")NoChecking data that should be stored directly on this object.
delete user.ageNot a checkRemove a configurable object property when absence has meaning.

Bitwise operators: & | ^ ~

INTERACTIVE

JavaScript numbers are 64-bit floating-point values, as you learned in Numbers & math. Bitwise operators are different: before they work, JavaScript converts the number to a 32-bit integer. Then it treats the integer as a row of 32 tiny switches: each switch is 0 or 1.

Real-life analogyBits are a row of light switches

Picture two rows of light switches. & asks which switches are on in both rows. | asks which are on in either row. ^ asks which switches differ. ~ flips the entire row.

In real life: Switch off
In JavaScript: Bit 0
In real life: Switch on
In JavaScript: Bit 1
In real life: Both switches must be on
In JavaScript: &
In real life: At least one switch is on
In JavaScript: |
In real life: Exactly one switch is on
In JavaScript: ^
In real life: Flip every switch
In JavaScript: ~

Where the analogy stops: The playground shows 8 switches so it fits on the page. JavaScript's bitwise operators actually work with 32 switches, which is why ~5 becomes -6.

Bitwise playground: eight visible switches
Bitwise sourcePop out in the code editor (opens in a new tab)JavaScript
const a = 12; // 00001100const b = 10; // 00001010console.log(a & b);  // both bits are 1console.log(a | b);  // either bit is 1console.log(a ^ b);  // bits are differentconsole.log(~a);     // flip 32 bitsconsole.log(a << 1); // shift leftconsole.log(a >> 1); // shift rightconsole.log(a >>> 1); // unsigned shift right
Live bits12 and 10
a = 12
b = 10
a & b = 800001000both bits are 1
a | b = 1400001110either bit is 1
a ^ b = 600000110bits differ
~a = -1311110011flip 32 bits
a << 1 = 2400011000slide left
a >> 1 = 600000110signed slide right
a >>> 1 = 600000110unsigned slide right
Try it yourself
Toggle a bit:

a is 12 (00001100), b is 10 (00001010). JavaScript computes these operators by first converting to 32-bit integers; this playground shows the low 8 bits so the switches fit on screen.

The visible bits are the low 8 bits. Operators like ~ and >>> still use all 32 bits, which is why ~12 is negative.
A few 32-bit surprisesPop out in the code editor (opens in a new tab)JavaScript
console.log(2 ** 32 | 0); // 0: wraps to a 32-bit signed integer
console.log(~5);        // -6: flip all 32 bits
console.log(-1 >>> 0);  // 4294967295: read all bits as unsigned

A realistic beginner-friendly use is permission flags. Give each permission one bit, combine flags with |, test one flag with &, and toggle a flag with ^.

Permission flagsPop out in the code editor (opens in a new tab)JavaScript
const READ = 1;    // 001
const WRITE = 2;   // 010
const EXECUTE = 4; // 100
let permissions = READ | WRITE;
console.log((permissions & WRITE) !== 0);
permissions = permissions ^ WRITE;
console.log((permissions & WRITE) !== 0);

Shifts, comma & void

STEP THROUGH

Shift operators slide the 32-bit switches left or right. << shifts left and fills with zeros on the right. >> shifts right while keeping the sign bit, so negative numbers stay negative. >>> shifts right and fills with zeros, producing an unsigned 32-bit result.

Shift examplesPop out in the code editor (opens in a new tab)JavaScript
console.log(5 << 1);  // 10
console.log(5 >> 1);  // 2
console.log(-1 >>> 0); // 4294967295

Two final operators mostly appear in older or specialized code. The comma operator evaluates expressions from left to right and keeps the last value. The void operator evaluates an expression, throws away its value, and produces undefined.

Comma keeps the last value; void keeps none
Step 0 of 7Ready
Your turn: follow the blue line

Comma evaluates in order and keeps the last value. void is a black hole: it always gives undefined.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
i++, j--;const kept = (1, 2, 3);const swallowed = void kept;console.log(i, j, kept, swallowed);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Legacy you may see, not copy

Old code sometimes used void 0 as a guaranteed undefined, or <a href="javascript:void(0)"> to make a link do nothing. Modern code should use real buttons, event handlers, and the normal undefined value instead.

The operator precedence table

SORTING GAME

Precedence answers: “which operator groups with its operands first?” It does not mean “which part is evaluated first” in every detail; many expressions still evaluate their operands left to right. For beginners, the practical rule is: when mixing unfamiliar operators, add parentheses.

Practical operator precedence, highest to lowest
LevelGroupOperatorsMemory hook
1Grouping(...)Forces an expression to happen first.
2Member access and calls., [], ?., ()Read a property or call a function before most operators around it.
3Postfix updatex++, x--Use the current value, then update the variable.
4Unary!, ~, +x, -x, typeof, void, deleteOne-operand operators bind before binary math.
5Exponentiation**Right-associative: 2 ** 3 ** 2 means 2 ** (3 ** 2).
6Multiply / divide*, /, %Higher than addition and subtraction.
7Add / subtract+, -Also includes string concatenation with +.
8Shifts<<, >>, >>>Move 32-bit integer bits left or right.
9Relational<, >, <=, >=, in, instanceofComparisons and membership checks.
10Equality==, !=, ===, !==Usually prefer strict equality.
11Bitwise AND&Works on each bit.
12Bitwise XOR^Bits that differ.
13Bitwise OR|Bits from either side.
14Logical AND&&Short-circuits and returns an operand.
15Logical OR||Short-circuits and returns an operand.
16Nullish coalescing??Chooses the right side only for null or undefined.
17Conditionalcondition ? a : bChooses one of two expressions.
18Assignment=, +=, ??=, &&=, ||=Stores a value.
19Comma,Evaluates left to right and keeps the last value.

Sort the cards by whether they bind higher or lower than addition. If you are unsure, the feedback tells you where the operator sits.

Which operator binds tighter than +?
  • getTotal()
  • typeof value
  • price * tax
  • subtotal + tax
  • total - discount
  • flags << 1
  • ready && saved
  • ok ? a : b
  • first(), second()
Try it yourself
0 of 9 correct

Place each card. The goal is not memorizing the whole table; it is spotting when parentheses would make code clearer.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Where you’ll use this

In everyday front-end code, these operators show up in predictable places:

  • Use a ternary to choose a CSS class, label, or short message: const tone = error ? "danger" : "success";
  • Use typeof at API boundaries when a value might be a string, number, or function.
  • Use Array.isArray before calling array methods on data you did not create.
  • Use Object.hasOwn when reading plain object data where inherited keys should not count.
  • Read bitwise flags in libraries, file permissions, graphics, and low-level browser APIs, even if you do not write them often.
Small practical patternPop out in the code editor (opens in a new tab)JavaScript
function describeUpload(file) {
  const kind = Array.isArray(file.tags) ? "tagged" : "untagged";
  const owner = Object.hasOwn(file, "owner") ? file.owner : "unknown";
  return `A ${kind} file owned by ${owner}.`;
}

Common misconceptions

“A ternary is always shorter, so it is always better.”

Shorter is not the same as clearer. A one-line label choice is a good ternary. Multiple branches usually deserve if /else or a lookup object.

“typeof tells me the exact type of everything.”

typeof null is "object", arrays are "object", and dates are "object". Use more specific checks when you need them.

“in means the object owns that property.”

in includes inherited keys like toString. Use Object.hasOwn for own data properties.

“delete removes an array item like splice.”

It leaves a hole. Use array methods such as splice or filtering when you want a shorter array.

“Bitwise operators are just faster math.”

They force 32-bit integer conversion. Tricks like ~~x can hide bugs and go against the readability advice from Coding style.

“Precedence tables replace parentheses.”

Professionals still add parentheses when mixed operators might slow the reader down. Clarity wins.

Practice: the rest of the operators

5 EXERCISES
Exercise 1 · Warm-upPredict a ternary

Work out which branch is chosen before you run the code.

Starter codePop out in the code editor (opens in a new tab)JavaScript
const age = 15;
const label = age >= 18 ? "adult" : "minor";
console.log(label);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeRewrite a nested ternary

    Rewrite the nested ternary as an if / else if / else chain.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const label = score >= 90 ? "A" : score >= 80 ? "B" : "keep practicing";

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeBuild permission flags

      Predict the two printed boolean values.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const READ = 1;
      const WRITE = 2;
      const EXECUTE = 4;
      let permissions = READ | EXECUTE;
      console.log((permissions & WRITE) !== 0);
      permissions = permissions | WRITE;
      console.log((permissions & WRITE) !== 0);

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeCheck for an own property correctly

        Which call checks only the keys stored directly on user?

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const user = { name: "Ada" };
        console.log(Object.hasOwn(user, "toString"));

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengePredict two 32-bit results

          Predict both lines. This is where the hidden 32-bit conversion matters.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          console.log(~5);
          console.log(-1 >>> 0);

          Answer, then press Check. Spacing and letter case don’t matter.

            Quiz: check your understanding

            8 QUESTIONS

            Take your time. Every answer explains why it is right or wrong, and code questions are based on real JavaScript output.

            Lesson quiz · 8 questionsScore: first tries count
            1. Question 1 of 8What does the ternary print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const age = 20;
              console.log(age >= 18 ? "adult" : "minor");

              Choose an answer to see the explanation.

            2. Question 2 of 8Which check is the reliable way to detect arrays?

              Choose an answer to see the explanation.

            3. Question 3 of 8What do in and Object.hasOwn print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const user = { name: "Ada" };
              console.log(("toString" in user) + " " + Object.hasOwn(user, "toString"));

              Choose an answer to see the explanation.

            4. Question 4 of 8What does deleting an array element print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const letters = ["a", "b", "c"];
              delete letters[1];
              console.log(letters.length + " " + (1 in letters));

              Choose an answer to see the explanation.

            5. Question 5 of 8What do these bitwise expressions print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              console.log(~5 + " " + (-1 >>> 0));

              Choose an answer to see the explanation.

            6. Question 6 of 8Which expression tests whether the WRITE permission flag is present?

              Choose an answer to see the explanation.

            7. Question 7 of 8What do comma and void print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const value = (1, 2, 3);
              console.log(value + " " + (void value));

              Choose an answer to see the explanation.

            8. Question 8 of 8Which operator in this lesson has the lowest precedence?

              Choose an answer to see the explanation.

            Key takeaways

            • A ternary is an expression-sized two-way choice: condition ? left : right.
            • typeof is best for primitives; use Array.isArray for arrays and instanceof for constructor family checks.
            • in includes inherited properties; Object.hasOwn checks only direct keys.
            • delete removes object properties, but on arrays it leaves holes and keeps length.
            • Bitwise operators convert to 32-bit integers; flags are a clear use, clever number tricks are not.
            • Comma and void are rare; recognize them, but do not reach for them first.
            • Precedence explains grouping, but parentheses explain your intent to humans.

            Remember the one-liner.
            The “other operators” are specialized expression tools: useful when they make a choice, check, flag, or grouping clearer than the long form.

            Up next: if, else & conditions, where choices get full statements, blocks, and room to breathe.

            CompleteFrontend Clear concepts. Working examples.