completefrontend
Open lab My progress
THE JAVASCRIPT FIELD GUIDE

Booleans inside the engine

See how V8 stores true and false as read-only oddballs, runs ToBoolean and branch bytecodes, and boxes Boolean objects.

By the end, you can
  • 01
    Find the real true and falseExplain why V8 keeps true and false as two shared values in read-only memory, and why writing a boolean never makes a new one.
  • 02
    Follow an if from value to jumpConnect the ToBoolean checks, the bytecode instructions, and comparison results to the branch the code takes.
  • 03
    Tell three things apartTell apart a boolean value (a pointer to a shared value), a bit inside fast code, and a Boolean wrapper object.

true and false are two shared values

You know true and false from everyday JavaScript. This lesson shows how a JavaScript engine stores them. An engine is the program that runs your code. We use V8, the engine inside Chrome and Node.js. Every fact here was checked in Node 22, which uses V8 version 12.4.

Inside V8, there is exactly one true and exactly one false. V8 makes them once, when it starts. V8 calls these special built-in values oddballs. A variable that holds a boolean only stores a pointer to one of them. A pointer is a memory address: it says where a value is. Writing true, writing false, or working out a < b never makes a new value.

This lesson builds on Tagged values, Smis & heap numbers. That lesson shows how V8 marks each stored value as either a small number or a pointer. The mark is called a tag, so a stored pointer is a tagged pointer. If you want the beginner rules for truthy and falsy values first, read Booleans & truthiness.

The main idea

A primitive boolean is a plain true or false value, not an object. In V8, it is a tagged pointer to one of two fixed oddballs, #true or #false. Both live in read-only space: a part of memory that nothing is allowed to change. A Boolean wrapper object is something different. Only new Boolean(...) makes one.

Booleans in everyday codePop out in the code editor (opens in a new tab)JavaScript
const first = true;const second = 3 < 5;console.log(first, second);console.log(typeof first);console.log(Boolean("non-empty"));

Line 1 stores the literal true. Line 2 stores the result of the comparison 3 < 5, which is also true. Line 3 prints both: true true. Line 4 prints boolean, because typeof tells you the type of a value. Line 5 turns a non-empty string into a boolean and prints true.

Two boxes, first and second, each with an arrow to the same true card. Below it is the one false card. V8 made both cards once.firstsecondthe one truetruefalsethe one false
first and second both point to the same true. V8 made one true and one false when it started, and every boolean points to one of them.

Where V8 keeps true and false

V8 is written in the C++ language, and its source code is public. So we can read how it builds true and false. The file oddball.h describes oddballs. Its comment says: “The Oddball describes objects null, undefined, true, and false.” So four values are oddballs: null, undefined, true, and false.

Each oddball stores a few ready-made answers, so V8 never has to work them out again:

  • to_number_raw and to_number: the value as a number.
  • to_string: the value as a string.
  • type_of: what typeof gives for the value.
  • kind: a small number that says which oddball this is.

For booleans, the kinds are kFalse = 0 and kTrue = 1. The same file defines kNotBooleanMask = ~1: a number with every bit set except the last one. In oddball-inl.h, the check IsBoolean tests (kind & kNotBooleanMask) == 0. That test passes only when the kind is 0 or 1. So only false and true pass.

What V8's source code says

The file setup-heap-internal.cc builds both values when V8 starts. It makes one boolean_map and gives it to both true_value and false_value. A map is V8's record of a value's type and shape. The file also fills in the ready-made answers:

  • true: as a number 1, as a string "true", and typeof "boolean".
  • false: as a number 0, as a string "false", and typeof "boolean".
Ask Node how it stores true and false (Node only)JavaScript
%DebugPrint(true);%DebugPrint(false);%DebugPrint(1 < 2);

%DebugPrint is a special V8 helper. It prints what V8 stores for a value. It only works when you start Node with node --allow-natives-syntax, so this block can't run on this page. The lesson's test runs it and checks the parts that are the same on every run:

  • [Oddball] in ReadOnlySpace: #true for true.
  • [Oddball] in ReadOnlySpace: #false for false.
  • The same map address for both values, within one run.
  • No undetectable flag on the boolean map. You'll meet this flag in the ToBoolean section.

Line 3 prints the result of 1 < 2. It is the same #true oddball.

Why read-only? V8's static roots article explains it. Core values such as undefined and true are roots: values the engine always needs. They live in the read-only part of the heap. (The heap is the memory where objects live.) V8 loads them from its startup snapshot, a saved copy of memory that V8 reads when it starts. The Startup performance lesson explains what snapshots cost and save.

The details differ between programs that use V8. Node 22 here uses V8 12.4 without pointer compression, a trick that stores pointers in fewer bytes. Chrome uses newer V8 versions with pointer compression and the sandbox, a fence that limits which memory V8 can touch. So addresses and memory layout differ. The idea of one shared, read-only true and false is the same.

Real-life analogyTwo light switch positions

A light switch has two fixed positions: on and off. Turning on the light doesn't build a new "on". It picks one of the two positions that are already there.

In real life: A switch has two positions: on and off
In JavaScript: V8 has one #true and one #false
In real life: Every room's switch uses the same two positions
In JavaScript: Every variable, property, and array item points to one of the two
In real life: The two positions are built into the switch
In JavaScript: Read-only space means the two values never change

Other engines store booleans in other ways. Each row below is one engine. It says how that engine stores true and false, and which source file shows it.

How three engines store true and false
EngineHow it stores true and falseWhere the source shows it
V8 12.4 (Node 22)true and false are two oddball objects in read-only memory. Variables hold tagged pointers to them.src/objects/oddball.h, setup-heap-internal.cc, and %DebugPrint in Node 22.
JavaScriptCore (Safari)The slot holds the number itself, not a pointer: 0x06 means false and 0x07 means true.The comments and the constants ValueFalse and ValueTrue in WebKit's JSCJSValue.h.
SpiderMonkey (Firefox)A JS::Value has the type mark JSVAL_TYPE_BOOLEAN and holds 0 or 1.Mozilla's js/public/Value.h defines the boolean type mark and setBoolean.

In JavaScriptCore, Safari's engine, comments in JSCJSValue.h list False: 0x06 and True: 0x07. These are not pointers. The stored value itself is the number 0x06 or 0x07. In SpiderMonkey, Firefox's engine, Value.h defines the type mark JSVAL_TYPE_BOOLEAN. It stores the boolean as the number uint32_t(b): 0 or 1.

Where variables keep their booleans

When a function runs, V8 gives that call a stack frame: a block of memory for that one call. V8's interpreter is the part of V8 that runs your code one small step at a time. It keeps each local variable in a register, a numbered slot in the stack frame.

When a slot holds a boolean, it holds a pointer to #true or #false. Object properties and array items work the same way. Because there is only one true, === between two booleans can come down to one question: do both pointers point to the same place? V8 first checks that both values really are booleans.

Array items are normal booleansPop out in the code editor (opens in a new tab)JavaScript
const flags = [true, false, true];console.log(flags[0] === true);console.log(flags[1] === false);console.log(flags.length);

Line 1 makes an array of three booleans. Lines 2 and 3 each print true: the items are the usual true and false. Line 4 prints 3, the length of the array.

Ask Node how it stores the array (Node only)JavaScript
const flags = [true, false];%DebugPrint(flags);

In Node 22 (V8 12.4), %DebugPrint([true, false]) reports PACKED_ELEMENTS. That is V8's name for an array of any values with no gaps. V8 has no special kind of array just for booleans. The items print as <true> and <false>: pointers to the same two oddballs. For the bigger memory picture, see Stack and heap and Heap layout.

Step through booleans inside a function
Step 0 of 5Ready
Your turn: follow the blue line

Step through a small function. Its variables and array items hold booleans. The box beside it is a simple model of the function's slots and the two shared values.

Running in
  1. script
Next: line 8
function chooseBadge(score) {  const passed = score >= 70;  const needsReview = !passed;  const pair = [passed, needsReview];  return { passed, needsReview, firstSlot: pair[0] };} 
CallStoreChangeResultBlue line: runs next. 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.

A simple model, not a real view of memory

The function's slots

score → 82passed → #trueneedsReview → #falsepair → Array object

The two shared values

#true [Oddball]#false [Oddball]

The function's slots, object properties, and array items all point to the same two shared values.

Press Step to walk through the replay. It runs the real code and shows the real values. The box beside it is a simple model of memory. It does not read real memory addresses from the engine.

How V8 turns any value into true or false

An if needs a yes-or-no answer. When you write if (value), JavaScript first turns value into true or false. The language rules call this step ToBoolean. The rules are a short table. These values become false:

  • undefined and null.
  • false.
  • The numbers +0, -0, and NaN.
  • BigInt zero, 0n.
  • The empty string, "".

Almost every other value becomes true. One odd exception, document.all, comes up below. Values that become false are called falsy. The rest are called truthy. V8 follows this table, with quick checks for the most common values.

Real-life analogyA door guard with a checklist

A door guard has a short checklist. The first questions catch the easy cases. Some answers need one more question. Anyone who gets past every question goes in.

In real life: The first questions catch the easy cases
In JavaScript: false, null, undefined, the empty string, and zero
In real life: Some answers need one more question
In JavaScript: Heap numbers and BigInts get an extra check
In real life: Anyone left after every question goes in
In JavaScript: Objects are always truthy
Playground: turn a value into true or false
The value you picked, checked two waysPop out in the code editor (opens in a new tab)JavaScript
const value = true;console.log(Boolean(value));if (value) {  console.log("truthy branch");} else {  console.log("falsy branch");}
Answertrue
Which check decidesthe shared true
Where V8 checks itShared boolean check
Boolean(value)true
Branch the if pickstruthy branch
Try it yourself

true: the shared true. The value already is V8's shared true, so the check answers true straight away. Real JavaScript gives Boolean(value) = true.

The order of checks is a simple model based on V8 12.4's source code. The true or false result comes from real JavaScript.

V8's checks use two words from the value-representation lesson. A Smi is a small whole number stored right in the slot. A heap number is a number stored as its own object on the heap.

Two places in V8's source

V8 has two versions of ToBoolean. Both follow the same table from the language rules.

  • CodeStubAssembler::BranchIfToBooleanIsTrue builds the fast version that V8's own machine code uses. It checks, in order: Smis; fixed values such as false, true, and the empty string; undetectable objects; heap numbers; BigInts. Anything left is truthy.
  • Object::BooleanValue is the C++ version. It checks, in order: a Smi that isn't zero; a boolean; null or undefined; WebAssembly's null, when that is turned on; undetectable objects; string length; heap numbers; BigInts. Anything left is true.

An undetectable object has a special bit on its map, and V8 treats it as falsy. Only null, undefined, and objects like the old document.all have this bit. That is how document.all can be falsy even though it is an object. Node has an internal helper, %GetUndetectable(), that makes such an object. The lesson test uses it to check that the object is falsy. Treat document.all as an old browser exception. Don't copy the idea in your own code.

The instructions V8 runs for an if

V8 doesn't run your source text directly. First it turns each function into bytecode: a list of small, simple instructions. V8's interpreter, called Ignition, runs those instructions one at a time. Each instruction has a short name, called a mnemonic. For example, Ldar a0 loads the first argument, a0, so the next instruction can use it. Return ends the function.

For a decision, Ignition uses a jump: an instruction that skips to another place in the list. Which jump it uses depends on one question: is the value already true or false?

Small functions that each check a boolean in a different wayJavaScript
function branchIf(x) {  if (x) return "yes";  return "no";} function lessIf(a, b) {  if (a < b) return "lt";  return "ge";} function doubleBang(x) {  return !!x;} function notValue(x) {  return !x;} function notLess(a, b) {  return !(a < b);} function andValue(a, b) {  return a && b;} function strictTrue(x) {  return x === true;}

Each function holds one pattern: if (x), if (a < b), !!x, !x, !(a < b), a && b, and x === true. Below is the bytecode Node printed for each one. Only the mnemonics are kept. Memory addresses and instruction positions change from run to run, so they are left out. a0 and a1 mean the first and second argument.

The bytecode names Node 22 printed for each functionText
branchIf:Ldar a0JumpIfToBooleanFalseReturn lessIf:Ldar a1TestLessThan a0JumpIfFalseReturn doubleBang:Ldar a0ToBooleanReturn notValue:Ldar a0ToBooleanLogicalNotReturn notLess:Ldar a1TestLessThan a0LogicalNotReturn andValue:Ldar a0JumpIfToBooleanFalseLdar a1Return strictTrue:LdaTrueTestReferenceEqual a0Return

The key difference is if (x) versus if (a < b):

  • if (x): x could be any value, so Ignition uses JumpIfToBooleanFalse. This one instruction turns the value into true or false, then jumps if it is false.
  • if (a < b): TestLessThan compares the two values. Its result is already true or false. So JumpIfFalse jumps without converting anything.
Top row, if (x): the value x goes to a make true or false step, then to jump. Bottom row, if (a < b): the comparison is already true or false, so it goes straight to jump.if (x)xmake true/falsejumpextra stepif (a < b)a < balready true or falsejump
x could be any value, so if (x) first turns it into true or false. A comparison already gives true or false, so if (a < b) jumps straight away.

The other functions follow the same idea:

  • !!x uses ToBoolean: turn the value into true or false.
  • !x uses ToBooleanLogicalNot: turn the value into a boolean, then flip it.
  • !(a < b) uses LogicalNot right after the comparison, because the result is already a boolean.
  • a && b uses JumpIfToBooleanFalse, the same jump as if (x).
  • x === true loads true with LdaTrue. Then TestReferenceEqual checks: do both pointers point to the same place? That is what this Node build prints.

Pick a value below, then step through label(value). The replay shows which check decides the branch.

Step through an if (value) branch
Step 0 of 4Ready
Your turn: follow the blue line

Step through an if as a replay: read the value, turn it into true or false, then jump to the matching return.

Running in
  1. script
Next: line 8
function label(value) {  if (value) {    return "truthy path";  }  return "falsy path";} 
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
Value passed to label

Picking a new value starts the replay again. Watch which step decides the branch.

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.
The function the replay steps throughJavaScript
function label(value) {  if (value) {    return "truthy path";  }  return "falsy path";} console.log(label(0));

Fast code can use a single bit

Bytecode always works with tagged values: pointers to #true and #false. For code that runs many times, V8 has a second compiler called TurboFan. It turns busy functions into fast machine code: instructions the computer's processor runs directly.

TurboFan can store a value in a smaller form. It calls each form a representation. The file machine-type.h defines MachineRepresentation::kBit: a single bit, 0 or 1. In representation-change.cc, ChangeBitToTagged turns a bit into a tagged boolean, and ChangeTaggedToBit goes the other way.

The names in V8's compiler sourceText
MachineRepresentation::kBitRepresentationChanger::InsertChangeBitToTaggedRepresentationChanger::GetBitRepresentationFor / ChangeTaggedToBit

So fast code can keep the result of a comparison as 0 or 1 in a CPU register. That is a tiny storage spot inside the processor, not the interpreter's register from earlier. Fast code only makes the real true or false pointer when your JavaScript needs to see the value, for example to store it or print it. This is how V8's compiler is designed. Your page can't see that register.

A card with the bit 1 inside fast code. An arrow, labelled when your code reads it, leads to the shared true card.1a bit in fast codewhen your code reads ittruethe shared true
Inside fast code, the result of a comparison can be just a bit: 0 or 1. V8 turns it into the shared true or false only when your code needs to see the value.

These three things are easy to mix up. Each row below says what one of them is and where you meet it.

A boolean value, a fast-code bit, and a Boolean object
ThingWhat it isWhere you meet it
A boolean valueA tagged pointer to the true or false oddball in V8.Everywhere in normal code. typeof true is "boolean", and === checks whether both point to the same oddball.
A bit in fast codeA 0 or 1 inside V8's compiler, stored as MachineRepresentation::kBit.Never directly. TurboFan can keep it in a CPU register until your code needs true or false.
new Boolean(false)A wrapper object on the heap, which V8 calls a JSPrimitiveWrapper. Inside, it points to the false oddball.Only when code uses new Boolean. The object is truthy, so don't use it.

Boolean objects made with new

Boolean(x) without new runs ToBoolean. It gives back true or false: one of the two shared values. new Boolean(x) is different. It makes a new wrapper object on the heap: an object that holds a boolean inside it. The wrapper is an object, and every object is truthy. So the wrapper is truthy even when it holds false.

Boolean() gives a value, new Boolean() gives an objectPop out in the code editor (opens in a new tab)JavaScript
const primitive = Boolean(false);const boxed = new Boolean(false); console.log(primitive, typeof primitive);console.log(Boolean(boxed), typeof boxed);console.log(boxed.valueOf());

Line 1 stores the plain value false. Line 2 makes a wrapper object around false. Line 4 prints false boolean. Line 5 prints true object: the wrapper is truthy, and its type is object. Line 6 calls valueOf(), which gives back the value inside the wrapper, so it prints false.

Left: Boolean(false) puts a plain false card in the box called primitive. It is falsy. Right: new Boolean(false) makes an object, a cart called boxed, with a false card inside. The object is truthy.Boolean(false)falseprimitiveplain false: falsynew Boolean(false)falseboxedan object: truthy
Boolean(false) gives the plain value false. new Boolean(false) gives an object with false inside, and every object is truthy.
Ask Node how it stores the wrapper (Node only)JavaScript
const boxed = new Boolean(false);%DebugPrint(boxed);%DebugPrint(Boolean(false));

The lesson test runs this in Node and checks the parts that are the same on every run:

  • [JSPrimitiveWrapper], V8's name for a wrapper object.
  • A value: field that points to <false>.
  • [Oddball] in ReadOnlySpace: #false for the plain value on line 3.

Using this in real code

What does all this mean for everyday code?

  • Don't try to speed up !!value versus Boolean(value). Both give the same result. Pick the one that is clearer to read.
  • Don't use new Boolean. It makes a truthy object, and readers won't expect that.
  • For millions of yes-or-no flags, think about memory and measure it. A normal array stores a pointer for each item. A typed array or a bitset stores small numbers instead.

A typed array holds numbers of one fixed size. Each item in a Uint8Array takes one byte. A bitset packs 8 flags into each byte, one bit per flag.

Two ways to store flags, with a rough size countPop out in the code editor (opens in a new tab)JavaScript
const featureFlags = [true, false, true, true];const packed = new Uint8Array([1, 0, 1, 1]); console.log(featureFlags.filter(Boolean).length);console.log(packed.reduce((sum, bit) => sum + bit, 0));console.log("model bytes", featureFlags.length * 8, packed.byteLength);

Line 1 stores four flags as booleans. Line 2 stores the same flags as the numbers 1 and 0 in a Uint8Array. Line 4 counts the true flags: filter(Boolean) keeps only the truthy items, so it prints 3. Line 5 adds up the numbers and also prints 3. Line 6 prints model bytes 32 4.

Line 6 is only a rough model. It counts 8 bytes per array item, the size of one pointer here, so 4 items make 32 bytes. packed.byteLength is the real size of the typed array's data: 4 bytes. Real arrays also need a header, storage for their items, and extra space that differs between engines. Pointer compression changes the sizes too. Before you change real code, measure with heap snapshots or speed tests.

Shared value, ToBoolean check, or heap object?
  • `true`
  • `false`
  • `a < b` result
  • `""` in `if (value)`
  • `0n` in `if (value)`
  • `new Boolean(false)`
  • `[true, false]`
Try it yourself
0 of 7 correct

Sort each item by the part of this lesson that explains it.

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

Common misconceptions

  • “A boolean is a wrapper object.” No. A boolean is a pointer to one of the two shared oddballs. Only new Boolean makes a wrapper object.
  • “Every if runs the same slow conversion.” No. A comparison already gives a boolean, so the bytecode can use JumpIfFalse with no conversion.
  • “Fast code's 0/1 bits are numbers your code can see.” No. They exist only inside the compiler. When your code reads the value, V8 turns it into true or false.
  • “new Boolean(false) acts like false in an if.” No. It is an object, so it is truthy.
  • “Node and Chrome store values in exactly the same way.” No. Node 22 here has pointer compression turned off. Chrome uses a newer V8 with pointer compression and the sandbox.

Practice exercises

6 EXERCISES
Exercise 1 · Warm-upA comparison gives a plain boolean

Predict the two outputs, in order.

Starter codePop out in the code editor (opens in a new tab)JavaScript
console.log(Boolean(3 < 5));
console.log((3 < 5) === true);

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

    Exercise 2 · Warm-upName the jump instruction

    In the lesson's bytecode list, which instruction decides the branch for if (x)?

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    function branchIf(x) {
      if (x) return "yes";
      return "no";
    }
    console.log(branchIf(0));

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

      Exercise 3 · PracticeSpot the wrapper trap

      What does Boolean(new Boolean(false)) print?

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const primitive = Boolean(false);
      const boxed = new Boolean(false);
      
      console.log(primitive, typeof primitive);
      console.log(Boolean(boxed), typeof boxed);
      console.log(boxed.valueOf());

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

        Exercise 4 · PracticeTurn a bit back into a boolean

        Which name from V8's compiler source turns a fast-code bit into a tagged boolean?

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

          Exercise 5 · PracticePick a compact way to store flags

          Which built-in typed array did the flags example use to store 0/1 flags?

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          const featureFlags = [true, false, true, true];
          const packed = new Uint8Array([1, 0, 1, 1]);
          
          console.log(featureFlags.filter(Boolean).length);
          console.log(packed.reduce((sum, bit) => sum + bit, 0));
          console.log("model bytes", featureFlags.length * 8, packed.byteLength);

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

            Exercise 6 · ChallengeReview a Boolean object

            A teammate stores flags as new Boolean(false). Should the code keep doing that?

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

              Quiz: check your understanding

              8 QUESTIONS
              Booleans inside the engine quiz · 8 questionsScore: first tries count
              1. Question 1 of 8In V8 12.4, what is the boolean value true?

                Choose an answer to see the explanation.

              2. Question 2 of 8What does this comparison code print?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                console.log(Boolean(3 < 5));
                console.log((3 < 5) === true);

                Choose an answer to see the explanation.

              3. Question 3 of 8Which pair of bytecode instructions runs for if (a < b)?

                Choose an answer to see the explanation.

              4. Question 4 of 8What does this wrapper snippet print?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                const boxed = new Boolean(false);
                console.log(Boolean(boxed));
                console.log(boxed.valueOf());

                Choose an answer to see the explanation.

              5. Question 5 of 8Why does if (a < b) skip the ToBoolean step?

                Choose an answer to see the explanation.

              6. Question 6 of 8What does Boolean(0n) print?

                Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
                console.log(Boolean(0n));

                Choose an answer to see the explanation.

              7. Question 7 of 8What does TurboFan's MachineRepresentation::kBit let fast code do?

                Choose an answer to see the explanation.

              8. Question 8 of 8Which rule is best for real code?

                Choose an answer to see the explanation.

              Key takeaways

              • In V8 12.4, true and false are two shared oddballs in read-only memory.
              • Variables, object properties, and array items hold pointers to those two values.
              • ToBoolean comes from the language rules. V8 runs it with quick checks for Smis, fixed values, strings, heap numbers, and BigInts.
              • Ignition uses JumpIfToBooleanFalse for a general if (x), and a plain JumpIfFalse after a comparison.
              • TurboFan can keep a boolean as a single bit (kBit) until your code needs the real true or false.
              • new Boolean(false) makes a truthy object. Don't use it in your code.

              One-liner: V8 has one true and one false; every boolean points to one of them, and conversions and jumps decide which one.

              Up next: undefined inside the engine. undefined is another oddball. You'll meet gaps in arrays, the check for using a variable too early, missing properties, and the LdaUndefined instruction.

              CompleteFrontend Clear concepts. Working examples.