JavaScript 기본 - 1

Flex·2022년 2월 28일
0

JavaScript 모음

목록 보기
1/8
post-thumbnail

JavaScript 의 기본에 대해 알아봅시다.
개념, 입출력, 코드 구성, 변수와 상수, 자료형, 객체 복사 에 대해 정리되어있습니다.


☕️ JavaScript의 개념

  • 객체(Object) 기반의 스크립트 프로그래밍 언어입니다.

  • ECMAScript 사양을 준수하는 범용 스크립팅 언어입니다.

  • 자바와 직접적인 연관은 없으며, 웹의 동적 동작을 구현하기 위해 제작되었습니다.

  • Mocha --> LiveScript --> JavaScript 로 명칭이 변경되었습니다.

  • JavaScript는 JS 엔진 위에서 수행되며,
    Google V8, Firefox SpiderMonkey, EdgeChakra 가 존재합니다.

아래 문서에서 JavaScript 의 명확한 정의를 더 볼 수 있습니다.
🦊 JavaScript | MDN

ECMAScript 란? 🤔

  • Ecma International 이 ECMA-262 기술 규격에 따라 정의하고 있는 표준화된 스크립트 프로그래밍 언어입니다.

  • JavaScript 를 표준화하기 위해 만들어졌으며, 액션스크립트와 J스크립트 등 다른 구현체도 포함합니다.

  • Ecma International : 정보 통신에 대한 표준을 제정하는 비영리 표준화 기구입니다.

  • ECMA-262 : Ecma International 에서 제정한 기술 규격의 이름으로, 범용 스크립트 언어 명세를 기술합니다.

  • 97년 ES1 초판, 09년 ES5, 15년 ES2015(ES6) 로 매년 6월에 버전 갱신 중입니다.


☕️ 입출력

  • 사용자가 프로그램과 상호작용하기 위한 방법 = 입력/출력 의 개념

  • Input/Output 의 머리글자를 따서 I/O 로 줄여서도 표기합니다.

  • 운영 체제에서의 대표적인 입출력은 "표준 입력/표준 출력/표준 오류 출력" 입니다.

✅ 일상생활에서 사용자는 PC 에 입력하고, PC는 모니터에 결과를 출력합니다.

1. 표준 입력 (stdin)

  • 일반적으로 키보드의 응답을 받아 입력합니다.

  • 프로그램의 데이터를 추가하기 위한 입력 장치입니다.

  • 알고리즘에서는 문제의 Testcase 입력을 위해 사용합니다.

✅ 꼭 키보드 뿐만 아니라, 마우스나 기타 여러 디바이스 등에 의해 입력을 받을수도 있습니다.

2. 표준 출력 (stdout)

  • 일반적으로 모니터에 문자열로 출력됩니다.

  • 프로그램의 실행 상태 혹은 실행 결과를 보고 판단합니다.

  • 알고리즘에서는 문제의 정답 확인, 디버깅 용으로 사용됩니다.

💻 .txt 파일을 읽어오는 간단한 코드

const fs = require("fs");
const input = fs.readFileSync(
  ".txt 파일의 절대경로",
  "utf8"
);

console.log(input);
  • 위 예제를 실행하면 텍스트 파일의 내용이 출력되는 것을 확인할 수 있습니다.
    (fs : FileSystem의 약자로써, 파일 처리를 담당하는 모듈입니다.)

⚠️ Error

Error: ENOENT: no such file or directory, open './input.txt'
    at Object.openSync (node:fs:585:3)
    at Object.readFileSync (node:fs:453:35)
    at Object.<anonymous> (/Users/flex/Desktop/zero-base/workspace/js_practice/js_basic/main.js:2:18)
    at Module._compile (node:internal/modules/cjs/loader:1097:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1151:10)
    at Module.load (node:internal/modules/cjs/loader:975:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47 {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: './input.txt'
}

만약 위와 비슷한 에러가 발생한다면 파일 경로를 다시 한 번 확인하세요!
readFileSync 의 파일 경로는 절대경로여야 합니다. (Mac OS, nodejs 기준)
참조 : nodejs에서 fs.readFileSync 사용시 발생하는 에러 확인


☕️ JavaScript 코드 구성

  • JavaScript 는 문법의 대부분을 C, C++, Java 로부터 차용하여 제작된 스크립트 기반의 언어입니다.

  • 다수의 표현식(expression)으로 하나의 명령문(statement)이 만들어지며, 명령문으로 프로그램이 수행됩니다.

  • 하나의 명령문 끝은 개행 문자(Enter) 혹은 세미콜론(;) 으로 표시해줍니다.
    ⭐️ 개발을 처음 접하시는 분들이 가장 많이 간과하는것이 세미콜론을 빼먹어서 나는 에러들입니다. 꼭 습관을 들이도록 합시다!

  • name = value 의 형태로써 왼쪽의 이름에 오른쪽의 값을 집어넣습니다.

1. 키워드

  • JavaScript에서 문법을 만들 때 미리 정해진 용도로 동작하기 위해 정의해 놓은 단어입니다.
    ex) let, class, extends, await, import, if, else, ...

  • 일일이 외우지 않아도 실제 프로그래밍에는 아무런 지장이 없습니다.
    우리에겐 Google신이 있으니까요! 그리고 VSCode의 자동추천 기능도 사용합시다.

2. 식별자

  • 스크립트에서 변수나 함수에 이름을 붙일 때 사용하는 단어입니다.

  • 대소문자를 구별하며 유니코드 문자셋을 이용합니다.

  • 자바스크립트 내 식별자 규칙
    1) 키워드 사용이 불가능합니다.
    2) 숫자로 시작할 수 없습니다.
    3) 특수문자_$ 만 허용합니다.
    4) 공백 문자를 포함할 수 없습니다.

3. 주석

  • 프로그램 구현 시 개발자의 설명 및 이해를 쉽게 도와주는 문장으로, 실제 실행 코드에는 포함되지 않습니다.

  • 주석의 종류는 단일 행 주석 //다중 행 주석 /**/ 이 존재합니다.
    꼭! 단일 행 주석은 실행되어야 하는 코드의 뒤쪽에 작성합시다.

💻 Example

  • 안녕, hi, HI 의 변수에는 각각 "하세요", "hello", "HELLO" 의 값이 배정됩니다.

  • 다중 행 주석 내부에 있는 출력문은 실행되지 않는것을 확인할 수 있습니다.

let 안녕 = "하세요";
let hi = "hello";
let HI = "HELLO";

console.log(안녕);
console.log(hi);
console.log(HI);

// single-line comments

/*
multi-line comments
여러 문장들이
개행으로 이어져도
주석처리 된다.
console.log("hello, world!");
*/

console.log("hello, world!");
  • 위 예제를 실행하면 아래와 같은 출력을 볼 수 있습니다.


☕️ 변수와 상수

1. 변수

  • 변경 가능한 값을 저장하기 위한 기억 공간(memory) 입니다.

  • 사용하기 전 반드시 선언이 필요합니다.

  • 중복 선언이 불가능합니다.

  • 키워드는 let 을 사용합니다.

  • 변수에 대한 접근으로 변수의 값을 수정할 수 있습니다.
    1) 선언 : let A = 123; --> 변수 A 의 값을 123 으로 초기화(선언)
    2) 수정 : A = 456 --> 변수 A 의 값이 456 으로 변경

⚠️ 중복 선언시 Error

변수를 중복 선언하게 되면 아래와 같은 SyntaxError 오류를 뿜어냅니다.

SyntaxError: Identifier 'A' has already been declared
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1026:15)
    at Module._compile (node:internal/modules/cjs/loader:1061:27)
    ...

2. 상수

  • 변경 불가능한 값을 저장하기 위한 기억 공간입니다.

  • 사용하기 전 반드시 선언이 필요합니다.
    선언과 동시에 초기화가 필요합니다.

  • 중복 선언이 불가능합니다.

  • 키워드는 const 를 사용합니다.

  • ❗️ 변수와는 달리 한번 선언되면 값을 변경할 수 없습니다. 잘 짚고 넘어갑시다!

변수와 상수로 나눠진 이유? 🤔

  • 사용되는 용도가 다르기 때문입니다. 아래 예제 코드를 참고해봅시다.
// 선언 후 할당
let hi;
hi = "hello";

// 선언과 동시에 초기화
let halo = "hello!";

// 한 줄에 여러 변수 선언하고 초기화
let name = "john",
  age = 13,
  msg = "hello";

// 상수는 보통 대문자로 표기
const TESTCASE = 5;
const BIRTHDAY = "2020. 1. 1";
  • 위와 같이 수정 가능한 값상수로 고정되어야 하는 값이 나누어져있는 경우가 많이 있습니다.

3. 호이스팅 (Hoisting)

  • 코드에 선언된 변수 및 함수를 유효한 범위의 코드 상단으로 끌어 올리는 작업입니다.

  • var의 변수/함수의 선언만 위로 올려지고, 할당은 올려지지 않습니다.

  • let/const 변수 선언과 함수 표현식에서는 호이스팅이 발생하지 않습니다.

// using var
console.log(name);
var name = "john";
console.log(name);

// hoisting
var name_2;
console.log(name_2);
name_2 = "john";
console.log(name_2);
  • 위 두 형식의 코드는 같은 출력결과를 나타냅니다.

  • 변수가 초기화되기 전에 출력문에 쓰였으므로 undefined 가 자동 할당됩니다.


☕️ 자료형

  • 목적에 따라 특별한 성질이나 정해진 범주를 갖고 있는 데이터의 종류입니다.

  • JavaScript에서는 6가지의 원시 타입 자료형과 1가지의 객체 타입 자료형으로 구성되어있습니다.

1. 원시 타입 (Primitive Type)

  1. boolean : 논리적 값. true, false
  2. null : 존재하지 않거나 유효하지 않은 주소를 표시합니다.
  3. undefined : 선언 후 값을 할당하지 않은 변수입니다.
  4. number : 정수, 실수 등의 숫자, 정수의 범위는 -253 ~ +253 입니다.
  5. string : 빈 문자열이나 글자들을 표현하는 문자열입니다.
  6. symbol : 문자열과 함께 객체 property로 사용되며, ES6에 추가되었습니다.

2. 객체 타입 (Object Type)

  1. object : 두 개 이상의 복잡한 개체를 저장할 수 있습니다.

typeof 란? 🤔

  • typeof인수의 자료형을 반환하는 연산자입니다.

  • 연산자인 typeof x와 함수인 typeof(x)로 문법을 지원합니다.

변수의 타입을 출력하는 간단한 예제

let str = "hello, world!";
console.log(typeof str);

console.log(typeof undefined);
console.log(typeof 123);
console.log(typeof 456n);
console.log(typeof 123.123);
console.log(true);
console.log(typeof "hello");
console.log(typeof Symbol("id"));
console.log(typeof Math);
console.log(typeof null);
console.log(typeof console.log);
  • 위 예제문의 출력은 아래와 같습니다.

  • 왜 아래처럼 출력되는지 자료형들을 통해 더 알아봅시다.

3. boolean

  • booloean은 논리적인 값을 표현하는 자료형입니다.
  • 참인 true와 거짓인 false, 두가지 값만 존재합니다.
  • 주로 조건문 등에서 동작 판단의 기준으로 사용됩니다.
let name_check = true;
let age_check = false;

let value_check = 10 > 3;
console.log(value_check); // true 출력

4. null & undefined

null

  • null은 값이 비어있다는 의미로 표현되는 자료형입니다.

  • 존재하지 않는(nothing), 비어 있는(empty), 알 수 없는(unknown) 값을 나타내는데 사용합니다.

console.log(typeof null); // object 출력

const null_check = null;
console.log(null_check === null); // true 출력

undefined

  • undefined는 값이 할당되어 있지 않은 상태를 나타낼 때 사용되는 자료형입니다.

  • 변수 선언 후 초기화하지 않는다면, undefined가 자동으로 할당됩니다.

let name;
console.log(name); // undefined 출력

5. number

  • number(숫자형)은 정수, 부동소수점(floating point) 숫자를 표현하는 자료형입니다.

  • number와 관련된 연산은 사칙연산(+,-,*,/) 이 대표적입니다.

  • number에는 일반적인 숫자 외에 Infinity, -Infinity, NaN(Not a Number) 같은 특수 숫자 값이 포함됩니다.

  • number에서는 253-1 보다 큰 값을 사용할 수 없으며, 더 큰 정수를 다루고 싶다면 bigint 자료형을 사용해야 합니다.

let num_1 = 123.0;
let num_2 = 123.456;
let num_3 = 1 / 0;

console.log(num_1 - num_2); // -0.45600000000000307 출력
console.log((num_1 - num_2).toFixed(3)); // -0.456 출력
console.log(num_3); // Infinity 출력
console.log(num_1 / "hello"); // NaN 출력

6. string

  • string은 문자, 문자열을 표현하는 자료형입니다.

  • JavaScript에서 문자열은 3가지 종류의 따옴표로 표현 가능합니다.
    --> 큰따옴표, 작은 따옴표, 백틱(역따옴표 : backtick)

let str_1 = "hello";
let str_2 = "hello";

let num = 3;
let str_3 = `hello_${num}`;
console.log(str_3); // hello_3 출력

7. object

object에 저장되는 개체들은 직접적으로 object 자료형에 저장되는 것이 아니고, 특정 메모리 공간을 할당받아 해당 장소에 저장됩니다.
object 자료형의 값은 이 메모리 주소를 참조(reference)하여 불러오게 됩니다.

  • object는 다수의 원시 자료형을 포함하거나 복잡한 개체(entity)를 표현할 수 있는 자료형입니다.

  • object는 Object() 혹은 중괄호({})를 통해 생성합니다.

  • object의 개체는 key: value 형태로 표현하며, 접근은 object.key 형태로 표현합니다.

object 의 간단한 예제

let user = {
  name: "john",
  age: 27,
};

console.log(typeof user); // object 출력
console.log(typeof user.name); // string 출력
console.log(typeof user.age); // number 출력

console.log(user); // { name: 'john', age: 27 } 출력
console.log(user.name); // john 출력
console.log(user.age); // 27 출력

user.age = 30;
console.log(user.age); // 30 출력

user.weight = 72; // user object에 weight 필드 추가
console.log(user); // { name: 'john', age: 27, weight: 72 } 출력

⚠️ 객체 복사 문제점

  • 위 예제에서 admin에 user object를 복사하면 따로따로 값이 적용될듯 하지만, 그렇지 않습니다.

  • 아래 의도적으로 일으킨 문제를 보면 알 수 있습니다.

let admin = user; // 객체 복사
console.log(admin);

admin.name = "park";
console.log(admin.name); // park 출력
console.log(user.name); // john --> park 출력

user.age = 30;
console.log(user.age); // 30 출력
console.log(admin.age); // 27 --> 30 출력
  • 이런 현상은 값을 복사하는 것이 아닌 주소(참조)를 복사하기 때문에 일어납니다.
    Call by Value / Call by Reference 라고 부르죠.
    결국 user 와 admin 은 같은 주소를 가리키게 됩니다.

객체 복사 문제점이 일어나는 이유? 🤔

  • object의 값을 복사할 때는 대상 전체가 아닌 object 내 주소 값만 복사되는 문제가 발생합니다.

  • 가리키는 대상 전체를 복사하는 방법은 얕은 복사(Shllow Copy), 깊은 복사(Deep Copy)를 통해 가능합니다.

💡 참고 사이트 : Javascript의 인자전달 Call by value or reference

얕은 복사 (Shallow Copy) 방법

  • 많이 쓰이는 얕은 복사 방법들을 알아봅시다.

  • 아래와 같은 방법으로 얕은 복사를 실행하면 각각의 개별적인 주소를 가져 서로 영향을 주지 않습니다.

for (let key in user) { // for문 사용
  admin[key] = user[key];
}

let admin_1 = Object.assign({}, user); // Object.assign 사용

let admin_2 = { ...user }; // ES6 부터 지원, 전개 연산자

⚠️ 얕은 복사 (Shallow Copy) 문제점

객체 내 또 다른 객체가 있다면 복사되지 않습니다!

  • 차분히 원리를 생각해보면,
    객체 내 객체를 얕은 복사 = 객체 내 객체의 주소를 복사
    이기 때문에 결국 객체 내 또 다른 객체의 주소를 그대로 사용하게 됩니다. 서로 영향을 주는거죠.

깊은 복사 (Deep Copy) 방법

  • 얕은 복사의 단점을 커버할 수 있는 깊은 복사를 알아봅시다.
let user = {
  name: "john",
  age: 27,
  sizes: {
    height: 180,
    weight: 72,
  },
};

let admin = { ...user }; // 얕은 복사 문제 발생

admin.sizes.height += 1;
console.log(admin.sizes.height); // 181 출력
console.log(user.sizes.height); // 181 출력

// "객체를 문자열화 --> 다시 해당 문자열을 객체화" 할 때 기존 객체와의 연결이 끊김
let admin_1 = JSON.parse(JSON.stringify(user)); // 깊은 복사 진행

admin_1.sizes.height += 1;
console.log(admin_1.sizes.height); // 182 출력
console.log(user.sizes.height); // 181 출력
  • 깊은 복사는 JSON 함수를 사용하면 한줄로 쉽게 실행시킬 수 있습니다.

  • 위 예제와 같이 깊은 복사를 실행할 수 있으며, 객체의 보다 완벽한 복사를 위해 깊은 복사를 권장합니다.

profile
💵 오늘을 살자

0개의 댓글