Chapter 2: Surveying JS - hochan222/Everything-in-JavaScript GitHub Wiki

Each File is a Program

JS์—์„œ .js๋กœ ๋‚˜๋ˆ ์ง„ ํŒŒ์ผ๋“ค์€ ์ž์ฒด ๋ณ„๋„ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค. JS๋Š” ํŒŒ์ผ์„ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์ทจ๊ธ‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•œ ํŒŒ์ผ์ด ์‹คํŒจ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ (ํŒŒ์‹ฑ / ์ปดํŒŒ์ผ ๋˜๋Š” ์‹คํ–‰ ์ค‘์—) ๋ฐ˜๋“œ์‹œ ๋‹ค์Œ ํŒŒ์ผ์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฒƒ์„ ๋ง‰์ง€๋Š” ์•Š๋Š”๋‹ค.
์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๊ณ  "global scope"๋ฅผ ํ†ตํ•ด ์ด ์ „์—ญ ๋ฒ”์œ„ ๋„ค์ž„ ์ŠคํŽ˜์ด์Šค์—์„œ ํ•จ๊ป˜ ํ˜ผํ•ฉ๋˜์–ด ์—ฌ๋Ÿฌ ๋…๋ฆฝํ˜• .js ํŒŒ์ผ๋“ค์ด ๋‹จ์ผ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ๋Ÿฐํƒ€์ž„์— ์ „์ฒด๋กœ ์ž‘๋™ํ•œ๋‹ค.

ES6 ์ดํ›„ JS๋Š” ์ผ๋ฐ˜์ ์ธ ๋…๋ฆฝํ˜• JS ํ”„๋กœ๊ทธ๋žจ ํ˜•์‹ ์™ธ์—๋„ ๋ชจ๋“ˆ ํ˜•์‹๋„ ์ง€์›ํ•œ๋‹ค. ๋ชจ๋“ˆ๋„ ํŒŒ์ผ ๊ธฐ๋ฐ˜์ด๋‹ค.

Values

๊ฐ’์€ ๋ฐ์ดํ„ฐ์ด๋ฉฐ ํ”„๋กœ๊ทธ๋žจ์ด ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. JS์—์„œ ๊ฐ’์€ primitive์™€ object ๋‘ ๊ฐ€์ง€ ํ˜•ํƒœ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

1. console.log("name: ${ firstName }."); // name ${ firstName }.
2. console.log('name: ${ firstName }.'); // name ${ firstName }.
3. console.log(`name: ${ firstName }.`); // name holee.

3๋ฒˆ์งธ ๋ฐฉ์‹์ด interpolation(๋ณด๊ฐ„) ๋ฐฉ์‹์ด๋‹ค. ๋ฆฌํ„ฐ๋Ÿด ๋ฌธ์ž์—ด ๋ฌธ๋ฒ•์„ ์—†์• ๋ฏ€๋กœ ํ•„์š”ํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜์ž.

Primitive types

Javascript์—์„œ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ž๋ฃŒํ˜•์„ ๋งํ•œ๋‹ค. ๊ทธ ์ข…๋ฅ˜๋กœ๋Š” Boolean, Null, Undefined, Number, String, Symbol ์ด ์žˆ๋‹ค.

Null ์ด๋ž€ ์–ด๋–ค ๊ฐ’์ด ์˜๋„์ ์œผ๋กœ ๋น„์–ด์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ๋ณ€์ˆ˜ ๊ฐ’์ด null๋กœ ์ •์˜๋Š” ๋˜์—ˆ์œผ๋‚˜, ๊ทธ ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.
๋ฐ˜๋ฉด, Undefined๋Š” ๋ณ€์ˆ˜๋กœ ์ •์˜๋˜์—ˆ์œผ๋‚˜, ์–ด๋– ํ•œ ๊ฐ’์„ ํ• ๋‹น๋ฐ›์ง€ ์•Š์€ ์ƒํƒœ์ž„์„ ์˜๋ฏธํ•œ๋‹ค.

let sample;
console.log(sample); // undefined
sample = null;
console.log(sample); // null

Arrays And Objects

primitive ์™ธ์—๋„ JS์˜ ๋‹ค๋ฅธ value ์œ ํ˜•์œผ๋กœ object๊ฐ€ ์žˆ๋‹ค.
Object๋Š” ๋‹ค์–‘ํ•œ ๊ฐ’์˜ ์ •๋ ฌ๋˜์ง€ ์•Š์€ ํ‚ค ์ปฌ๋ ‰์…˜์ด๋‹ค.

Arrays are a special type of object thatโ€™s comprised of an ordered and numerically indexed list of data

๋˜ํ•œ, ๋ฐฐ์—ด์€ ์ˆœ์„œ๊ฐ€ ์ง€์ •๋˜๊ณ  ์ˆซ์ž๋กœ ์ƒ‰์ธ์ด ์ง€์ •๋œ ๋ฐ์ดํ„ฐ ๋ชฉ๋ก์œผ๋กœ ๊ตฌ์„ฑ๋œ ํŠน์ˆ˜ํ•œ ์œ ํ˜•์˜ ๊ฐ์ฒด์ด๋‹ค.

Value Type Determination

typeof ์—ฐ์‚ฐ์ž๋Š” ๊ธฐ๋ณธ ์œ ํ˜•์ธ ๊ฒฝ์šฐ primitive ์œ ํ˜•์„, ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ "๊ฐ์ฒด"๋ฅผ ์•Œ๋ ค์ค€๋‹ค.

typeof 42;                 // "number"
typeof "abc";              // "string"
typeof true;               // "boolean"
typeof undefined;          // "undefined"
typeof null;               // "object" << ??? bug??
typeof { "a": 1 };         // "object"
typeof [1,2,3];            // "object"
typeof function hello(){}; // "function"

์ •๋ณด: ์ฐพ์•„๋ณด๋‹ˆ typeof null; ์ด "object"์ธ ์ด์œ ๋Š” ํ•˜์œ„ ํ˜ธํ™˜์„ ์œ„ํ•ด ์–ด์ฉ” ์ˆ˜ ์—†์ด "object"๋กœ ํ–ˆ๋‹ค๊ณ  ํ•œ๋‹ค.

ํ•œ ๊ฐ’ ์œ ํ˜•์—์„œ ๋‹ค๋ฅธ ๊ฐ’ ์œ ํ˜•์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š”๊ฒƒ์„ 'coercion' ์ด๋ผ๊ณ  ํ•œ๋‹ค.
๋˜ํ•œ, ๊ธฐ๋ณธ ๊ฐ’๊ณผ ์˜ค๋ธŒ์ ํŠธ ๊ฐ’์€ ํ• ๋‹น๋˜๊ฑฐ๋‚˜ ์ „๋‹ฌ ๋  ๋•Œ ๋‹ค๋ฅด๊ฒŒ ์ž‘๋™ํ•œ๋‹ค.

The history of โ€œtypeof nullโ€
์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์˜ typeof์˜ c ์ฝ”๋“œ์ด๋‹ค.

    JS_PUBLIC_API(JSType)
    JS_TypeOfValue(JSContext *cx, jsval v)
    {
        JSType type = JSTYPE_VOID;
        JSObject *obj;
        JSObjectOps *ops;
        JSClass *clasp;

        CHECK_REQUEST(cx);
        if (JSVAL_IS_VOID(v)) {  // (1)
            type = JSTYPE_VOID;
        } else if (JSVAL_IS_OBJECT(v)) {  // (2)
            obj = JSVAL_TO_OBJECT(v);
            if (obj &&
                (ops = obj->map->ops,
                 ops == &js_ObjectOps
                 ? (clasp = OBJ_GET_CLASS(cx, obj),
                    clasp->call || clasp == &js_FunctionClass) // (3,4)
                 : ops->call != 0)) {  // (3)
                type = JSTYPE_FUNCTION;
            } else {
                type = JSTYPE_OBJECT;
            }
        } else if (JSVAL_IS_NUMBER(v)) {
            type = JSTYPE_NUMBER;
        } else if (JSVAL_IS_STRING(v)) {
            type = JSTYPE_STRING;
        } else if (JSVAL_IS_BOOLEAN(v)) {
            type = JSTYPE_BOOLEAN;
        }
        return type;
    }

ใ…‹ใ…‹ใ…‹ใ…‹ NULL ๊ฒ€์‚ฌ๊ฐ€ ์—†๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์—ญ์‚ฌ์ ์œผ๋กœ ๊ต‰์žฅํžˆ ๋น ๋ฅธ ์‹œ๊ฐ„์— ๊ธ‰ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์กŒ์œผ๋ฏ€๋กœ ์ฒ˜์Œ ๋งŒ๋“ค๋•Œ ๋นผ๋จน์—ˆ๋‚˜๋ณด๋‹ค. ๋‚˜์ค‘์—๋Š” ํ˜ธํ™˜์„ฑ๋•Œ๋ฌธ์— ๊ณ ์น˜์ง€๋„ ๋ชปํ•˜๋Š”๊ฒƒ๊ฐ™๋‹ค.. ์•ž ๋‹จ์›์—์„œ ๊ทธ๋ ‡๊ฒŒ ๋ณด์ˆ˜์ ์ด์—ˆ์œผ๋‹ˆ ๊ทธ๋Ÿด๋งŒ๋„ ํ•˜๋‹ค.

Declaring and Using Variables

var์— ๋น„ํ•ด let ์€ โ€œblock scopingโ€์„ ๊ฐ–๊ณ  ์žˆ๋‹ค. ๋‹ค๋งŒ, ํ”ํžˆ ์šฐ๋ฆฌ๋Š” var์„ ๋ฐฐ์ฒ™์„ ํ•ด์•ผํ•œ๋‹ค๋Š” ์ƒ๊ฐ์„ ๊ฐ–์œผ๋ คํ•˜๋Š”๋ฐ ์ด ์ฑ…์—์„œ๋Š” ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ var์„ ๋ฐฐ์ฒ™ํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์“ฐ๋Š” ์ƒํ™ฉ์— ๋งž๊ฒŒ ์ž˜ ์“ฐ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค๊ณ  ๋งํ•œ๋‹ค.

const๋Š” ๋‚˜์ค‘์— ๋‹ค๋ฅธ ๊ฐ’์„ ๋‹ค์‹œ ํ• ๋‹น ํ•  ์ˆ˜ ์—†๋‹ค. ์ฃผ์˜ํ• ์ ์€ const๋กœ ์„ ์–ธํ•œ ๋ณ€์ˆ˜๋Š” ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š”๊ฒŒ์•„๋‹ˆ๊ณ  ์žฌํ• ๋‹น ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์ ์ด๋‹ค. ๋”ฐ๋ผ์„œ, object์™€ ํ•จ๊ป˜ const๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ข‹์ง€ ๋ชปํ•˜๋‹ค. ๋ณ€์ˆ˜๋ฅผ ์žฌํ• ๋‹น ํ•  ์ˆ˜ ์—†๋Š”๋ฐ๋„ ๋ณ€๊ฒฝ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

const actors = [
    "Morgan Freeman", "Jennifer Aniston"
];

actors[2] = "Tom Cruise";   // OK :(
actors = [];                // Error!

๋”ฐ๋ผ์„œ, primitive value์—๋งŒ const๋ฅผ ์‚ฌ์šฉ์„ ์ง€ํ–ฅํ•˜์ž.

var / let / const๋ง๊ณ ๋Š” function์ด ์žˆ๋‹ค.

function hello(myName) { 
    console.log(`Hello, ${ myName }.`);
}

hello("Kyle");
// Hello, Kyle.

hello ๋ฐ myName์€ ์ผ๋ฐ˜์ ์œผ๋กœ var-declared์™€ ๊ฐ™์ด ๋™์ž‘ํ•œ๋‹ค.

variable์„ ์„ ์–ธํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฌธ๋ฒ•์€ catch๋‹ค.
err์€ let์œผ๋กœ ์„ ์–ธ ๋œ ๊ฒƒ์ฒ˜๋Ÿผ catch ์ ˆ ๋‚ด๋ถ€์—๋งŒ ์กด์žฌํ•˜๋Š” ๋ธ”๋ก ๋ฒ”์œ„ ๋ณ€์ˆ˜์ด๋‹ค.

try { 
    Error();
}
catch (err) {
    console.log(err); 
}

Functions

๋‹ค์Œ์€ ํ•จ์ˆ˜ ์„ ์–ธ๋ฌธ(function declaration)์ด๋ฉฐ ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์ •์˜๋œ๋‹ค.

function myfunction(props) { 
// ..
    return functionStuff; 
}

๋‹ค์Œ์€ ํ•จ์ˆ˜ ํ‘œํ˜„์‹(function expresstion)์ด๋ฉฐ ๋Ÿฐํƒ€์ž„์ผ ๋•Œ ํ•ด๋‹น statement๊ฐ€ ์žˆ์„ ๋•Œ๊นŒ์ง€ ์‹๋ณ„์ž์™€ ๊ด€๋ จ๋˜์–ด์ง€์ง€ ์•Š๋Š”๋‹ค.

var myfunction = function(props) { 
// ..
    return functionStuff; 
}

ํ•จ์ˆ˜๋Š” value์ด๋ฏ€๋กœ object์™€ array์•ˆ์— ๋“ค์–ด ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

var whatToSay = { greeting() {
    console.log("Hello!"); },
question() {
    console.log("What's your name?");
}, answer() {
    console.log("My name is Kyle."); }
}; 

whatToSay.greeting();
// Hello!

Comparisons

===๋Š” ๊ฐ•์ œ ๋ณ€ํ™˜์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ์‚ฌ์‹ค ===์—๋„ NaN๊ณผ -0์— ๋Œ€ํ•ด ๊ฑฐ์ง“๋œ ์ง„์‹ค์ด ์žˆ๋‹ค.

Nan === Nan     // false
0 === -0;       // true

NaN์˜ ๊ฒฝ์šฐ Number.isNaN()๋ฅผ ์‚ฌ์šฉํ•˜์ž. -0์— ๋Œ€ํ•ด์„œ๋Š” Object.is()๋ฅผ ์‚ฌ์šฉํ•˜์ž.
Object.is()๋Š” "quadruple-equals", ==== ์ •๋ง ์—„๊ฒฉํ•œ ๊ฒ€์‚ฌ์ด๋‹ค.

๋งŒ์•ฝ ๋น„๊ต ๋ฒ”์œ„๊ฐ€ primitive value์˜ ๋ฒ”์œ„๋ฅผ ๋„˜์–ด๊ฐ€๋ฉด ๊ต‰์žฅํžˆ ๋ณต์žกํ•ด์ง„๋‹ค.

[ 1, 2, 3 ]===[ 1, 2, 3 ];      //false 
{ a: 42 } === { a: 42 } // false 
(x => x * 2)===(x => x * 2)     //false

object์˜ content-aware comparison๋Š” "structural equality"์ด๋‹ค.
์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ===๋ฅผ "structural equality"๋กœ ์ •์˜ํ•˜์ง€ ์•Š๊ณ , "identity equality"๋กœ ์ •์˜ํ•œ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ชจ๋“  ๊ฐ์ฒด ๊ฐ’์€ ์ฐธ์กฐ๋กœ ์œ ์ง€๋œ๋‹ค. ๋น„๊ต ๋˜ํ•œ "reference (identity) equality"๋กœ ๋น„๊ต๋œ๋‹ค.

var x = [ 1, 2, 3 ];
// assignment is by reference-copy, so 
// y references the *same* array as x, 
// not another copy of it.

var y = x;
y === x;     // true 
y===[1,2,3]; //false 
x===[1,2,3]; //false

Coercive Comparisons

==๋Š” ๋น„๊ต ์ „์— ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๊ฐ’์ด ์ˆซ์ž๋กœ ๋จผ์ € ๋ณ€๊ฒฝ๋œ๋‹ค์Œ์— ๋น„๊ต๋œ๋‹ค. ๋น„๊ตํ•˜๋Š” ๋‘ ๊ฐ’์ด ๋ชจ๋‘ ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ์ด์ƒ ์ผ๋ฐ˜์ ์œผ๋กœ ์ˆซ์ž ๋น„๊ต๋ฅผ ํ•œ๋‹ค.

How We Organize in JS

Classes

โ€œobject-orientedโ€, โ€œclass-orientedโ€, โ€œclassesโ€...

Class Inheritance

class Publication { 
  constructor(title,author,pubDate) {
    this.title = title; 
    this.author = author; 
    this.pubDate = pubDate;
  }
  
  print() {
    console.log(`
       Title: ${ this.title } 
       By: ${ this.author } 
       ${ this.pubDate }
    `); 
  }
}

class Book extends Publication { 
  constructor(bookDetails) {
    super(
      bookDetails.title, 
      bookDetails.author, 
      bookDetails.publishedOn
    );
    this.publisher = bookDetails.publisher; 
    this.ISBN = bookDetails.ISBN;
  }
  
  print() { 
    super.print();
    console.log(`
      Publisher: ${ this.publisher }
      ISBN: ${ this.ISBN } 
    `);
  }
}

class BlogPost extends Publication { 
  constructor(title,author,pubDate,URL) {
    super(title,author,pubDate);
    this.URL = URL; 
  }
  print() { 
    super.print();
    console.log(this.URL); 
  }
}

์ƒ์† ๋œ ๋ฉ”์„œ๋“œ์™€ ์žฌ์ •์˜ ๋œ ๋ฉ”์„œ๋“œ๊ฐ€ ๊ฐ™์€ ์ด๋ฆ„์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ  ๊ณต์กด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ๋‹คํ˜•์„ฑ์ด๋ผ๊ณ  ํ•œ๋‹ค.

Modules

Classic Modules

  1. Class form์€ this๋กœ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค์— ์ ‘๊ทผํ•˜์—ฌ ๋ฉ”์„œ๋“œ์™€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ˜๋ฉด์— Modules๋Š” ์‹๋ณ„์ž ๋ณ€์ˆ˜๋กœ ์ ‘๊ทผํ•œ๋‹ค.
  2. ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ธ์Šคํ„ด์Šค์˜ "API"๊ฐ€ ํด๋ž˜์Šค ์ •์˜์— ๋‚ดํฌ๋˜์–ด ์žˆ์œผ๋ฉฐ ๋ชจ๋“  ๋ฐ์ดํ„ฐ์™€ ๋ฉ”์„œ๋“œ๊ฐ€ ๊ณต๊ฐœ๋˜๋Š” ๋ฐ˜๋ฉด์— ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๋˜๋Š” ๊ธฐํƒ€ ์ฐธ์กฐ๋˜์ง€ ์•Š์€ ๋ฉ”์„œ๋“œ๋Š” ํŒฉํ† ๋ฆฌ ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋น„๊ณต๊ฐœ๋กœ ์œ ์ง€ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. Factory function form ์—๋Š” AMD (Asynchronous Module Definition), UMD (Universal Module Definition), and CommonJS (classic Node.js-style modules)๊ฐ€ ์žˆ๋‹ค.