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
- Class form์ this๋ก ๊ฐ์ฒด ์ธ์คํด์ค์ ์ ๊ทผํ์ฌ ๋ฉ์๋์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๋ฐ๋ฉด์ Modules๋ ์๋ณ์ ๋ณ์๋ก ์ ๊ทผํ๋ค.
- ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ธ์คํด์ค์ "API"๊ฐ ํด๋์ค ์ ์์ ๋ดํฌ๋์ด ์์ผ๋ฉฐ ๋ชจ๋ ๋ฐ์ดํฐ์ ๋ฉ์๋๊ฐ ๊ณต๊ฐ๋๋ ๋ฐ๋ฉด์ ๋ชจ๋ ๋ฐ์ดํฐ ๋๋ ๊ธฐํ ์ฐธ์กฐ๋์ง ์์ ๋ฉ์๋๋ ํฉํ ๋ฆฌ ํจ์ ๋ด์์ ๋น๊ณต๊ฐ๋ก ์ ์ง ํ ์ ์๋ค.
- Factory function form ์๋ AMD (Asynchronous Module Definition), UMD (Universal Module Definition), and CommonJS (classic Node.js-style modules)๊ฐ ์๋ค.