1. "use strict";

// strict 모드 적용
"use strict";


/* reference 에러가 발생하는 경우 */
a = 3;	// reference error



/* type 에러가 발생하는 경우 */

// 1. 예약어에 대한 할당
let undefined = 5;	// type error
let Infinity = 15;	// type error


// 2. 쓰기 불가능하도록 지정된 속성에 대한 할당
let obj = {};
Object.defineProperty(obj, "val", { value: 7, writable: false });

obj.val = 3;	// type error


// 3. setter가 정의 되지않은 속성에 대한 할당
let obj2 = {
	get val() { return 7; }
};
obj2.val = 3;	// type error


// 4. 확장 불가능한 객체에 속성 추가
let fixed_obj = {};
Object.preventExtensions(fixed_obj);
Object.defineProperty(fixed_obj, "val", {value: 7, writable: true});	// type error


// 5. 삭제 불가능한 속성에 대한 삭제시도
let obj3 = {};
Object.defineProperty(obj3, "val", { value: 7, configurable: false });

delete obj3["val"];	// type error


// 6. 원시(primitive) 값에 대한 프로퍼티 설정
(1).val = 11;	// type error
false.val = 3;	// type error



/* syntax 에러가 발생하는 경우 */

// 1. 중복되는 인자 이름(함수)
function func(a, a, b) { return a + b };	// syntax error


// 2. 8진구문 사용
// 8진법 구문은 사용할 일이 거의 없으며 실수가 발생하기 쉽기 때문에 구문오류로 처리
let a = 0o456;	// syntax error


// 3. with 구문의 사용
// with 구문 사용시 블록안에서 사용되는 이름과 블록 바깥의 이름이 같아진다면
// 둘 중 어느것을 의미하는지 모호한 코드가 되기 때문에 strict모드에서는 with문 자체를 금지
let obj = {x: 15};
let x = 3;
with(obj) {	// syntax error
	console.log(x);
}
  • "use strict"; 구문을 적어준 이후의 코드 실행에서는 strict 모드가 적용됨

  • 원래라면 에러를 발생시키지 않았던 자잘한 오류들이 모두 에러를 발생시키도록 엄격한 문법이 적용됨

  • strict 모드에서 에러를 발생시키도록 변경되는 사항들
    • 선언되지 않은 변수의 참조

    • 쓰기 불가능한 속성에 대한 할당
      • Infinity, undefined 등 예약된 값
      • 객체에서 writable: false로 정의된 속성값
      • setter가 정의되지 않은 속성(getter-only)

    • 확장 불가능하도록 지정된 객체에서 새 속성 할당

    • 삭제 불가능한 속성에 대한 삭제시도

    • 원시값에 대한 속성 설정 시도
    • 모호한 구문의 사용 금지
      • 함수 인자명 중복
      • 8진수 구문
      • with 구문

  • 위에 나열한 사항들 이외에도 많은 것들이 use strict에선 에러로 처리

 

 

2. 블록 strict모드

a = 3;
// func1 블록 내에서만 strict 모드 적용
function func1() {
	"use strict";
  b = 3;
}

func1();	// reference error 발생
  • strict 모드의 적용은 보다 안전한 코드를 짜기 위해 도움이 되지만 유연함이 부족하며
    다른 non-strict 모드 스크립트와의 결합시에도 문제가 발생할 여지가 있음

  • 이를 해결하기 위해 부분적으로 strict 모드를 적용 가능
    => 블록 내에 "use strict"; 구문을 추가할경우 블록 내에서만 strict 모드가 적용

 

 

※ strict 모드를 기존에 non-strict 모드로 작성한 JavaScript 코드에 적용하는 것은
   예상치 못한
에러를 대량으로 발생시킬 수 있기에 권장되지 않음. 처음 코드를
   작성할 때부터 strict 모드를
적용시킨 후 이를 고려하여 작성해나가는 것이 바람직함

'언어 > JavaScript' 카테고리의 다른 글

#11 템플릿 리터럴(Template Literal)  (0) 2022.02.23
#10 destructing  (0) 2022.02.23
#9 rest / spread 연산자  (0) 2022.02.23
#8 import / export  (0) 2022.02.21
#7 클래스(Class)  (0) 2022.02.21
let name = "David";
let age = "16";

// 템플릿 리터럴을 사용하여 변수값을 사용하여 문자열 포매팅
let string = `Hi, my name is ${name}. I'm ${age} years old.`;
console.log(string);
  • `...${<변수명>}...` 의 형태로 문자열의 원하는 위치에 변수의 값을 넣을 수 있음
  • 이 때, 템플릿 리터럴을 감싸는 기호는 따옴표(')가 아닌 백틱(`)을 사용해야함에 유의해야한다.

'언어 > JavaScript' 카테고리의 다른 글

#12 strict 모드  (0) 2022.02.23
#10 destructing  (0) 2022.02.23
#9 rest / spread 연산자  (0) 2022.02.23
#8 import / export  (0) 2022.02.21
#7 클래스(Class)  (0) 2022.02.21
// x, y, z 속성을 가진 객체 obj
let obj = {x: 3, y: 5, z: 2};

// destructing 구문을 사용하여 객체의 속성을 한번에 여러 변수에 나눠담음
const {x: a, y: b, z: c} = obj;

// a, b, c를 출력
console.log(a, b, c);	// 3 5 2
  • const { <속성이름>: <속성값을 저장할 변수>, ... } = <객체> 의 형태로 여러개의 속성값을 변수에 저장

  • Python의 언패킹과 유사하게 동작함

'언어 > JavaScript' 카테고리의 다른 글

#12 strict 모드  (0) 2022.02.23
#11 템플릿 리터럴(Template Literal)  (0) 2022.02.23
#9 rest / spread 연산자  (0) 2022.02.23
#8 import / export  (0) 2022.02.21
#7 클래스(Class)  (0) 2022.02.21

1. rest 연산자

// rest 연산자로 인자를 갯수제한 없이 배열의 형태(args)로 받아
// 모든 인자의 합을 반환
function sum(...args) {
    let res = args[0];
	for(let i=1; i<args.length; i++) {
    	res += args[i];
    }
    return res;
}

console.log(sum(1, 2, 3, 4));	// 10
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));	// 55
console.log(sum('Hello', 'World', '!'));	// "HelloWorld!"
  • rest 연산자(...)를 사용할 경우 갯수제한 없이 다수의 인자를 배열의 형태로 받아올 수 있음

  • Python의 애스터리스크(*)와 유사하게 사용 가능

 

 

2. spread 연산자

// spread 연산자를 사용하여 arr의 모든 요소를 arr_2의 0 다음에 나열
let arr = [1, 2, 3, 4, 5];
let arr_2 = [0, ...arr];

console.log(JSON.stringify(arr_2));	// "[0,1,2,3,4,5]"
  • rest 연산자와 같은 형태(...)

  • iterable한 (iterator를 반환할 수 있는) 객체의 값을 풀어 하나씩 나열한 것과 같은 효과를 가짐

  • rest와 마찬가지로 Python의 애스터리스크(*)와 유사하게 사용 가능

 

 

 

'언어 > JavaScript' 카테고리의 다른 글

#11 템플릿 리터럴(Template Literal)  (0) 2022.02.23
#10 destructing  (0) 2022.02.23
#8 import / export  (0) 2022.02.21
#7 클래스(Class)  (0) 2022.02.21
#6 객체(Object)  (0) 2022.02.18

1. import / export

/* file "a.js" */
// import func1 from "b.js"
import {func1} from "./b.js";

console.log(func1());	// It's b.js func1




/* file "b.js" */
// export func1
export const func1 = function() {
    return "It's b.js func1";
}
  • JavaScript ES6부터는 import, export 를 사용하여 자바스크립트 파일을 모듈처럼 import하고 export할 수 있음

  • export를 변수 앞에 붙이는 것으로 다른 파일에서 import 가능하도록 할 수 있음

  • import {<가져올 변수 이름>, ...} from "<모듈명>"; 와 같이 import문을 실행하여
    다른 파일(모듈)의 데이터를 가져올 수 있음

  • 가져올 변수명들은 중괄호 안에서 콤마(,)로 구분하여 나열 가능

  • 단, 이 기능을 사용할 때 script 태그에서 type="module" 속성값을 추가해주거나 node.js의 경우
    package.json 파일에 "type": "module" 을 추가해주지 않으면 module이 아닌 곳에서
    import문의 사용은 불가능하다는 에러가 발생

  • import, export문은 블록 내에서는 사용 불가능(전역에서만 사용가능)

 

 

2. 전체 import

/* file "a.js" */
// import all from "b.js"
import * as mod_b from "./b.js";

console.log(mod_b.func1());	// It's b.js func1
console.log(mod_b.func2());	// It's b.js func2



/* file "b.js" */
// export func1
export const func1 = function() {
    return "It's b.js func1";
}

// export func2
export const func2 = function() {
    return "It's b.js func2";
}
  • import * as <모듈이름> from "<모듈명>;  과 같이 모듈 전체를 import할 수도 있음

  • 이 경우 <모듈이름>.<export된 데이터> 의 형태로 접근 가능

 

 

3. 선언 이후 export

/* file "a.js" */
// import func1 from "b.js"
import {func1} from "./b.js";

console.log(func1());	// It's b.js func1




/* file "b.js" */
// declare func1
const func1 = function() {
    return "It's b.js func1";
}

// export func1
export { func1 }
  • 선언이 끝난 이후에도 export { <export할 변수들=""> } 의 형태로 </export할> export가 가능

 

 

4. export as

/* file "a.js" */
// import f1 from "b.js"
import {f1} from "./b.js";

console.log(f1());	// It's b.js func1




/* file "b.js" */
// declare func1
const func1 = function() {
    return "It's b.js func1";
}

// export func1
export { func1 as f1 }
  • export { <export할 변수> as <별칭> } 의 형태로 export에서도 as를 사용 가능

  • export as를 사용할 경우 import 할 때 별칭을 사용해야함

 

 

5. export default

/* file "a.js" */
// import f1 from "b.js"
import f1 from "./b.js";

// import f2 from "c.js"
import f2 from "./c.js";

console.log(f1());	// It's b.js func1
console.log(f2());	// It's c.js func1



/* file "b.js" */
// export func1 as default
export default function func1() {
    return "It's b.js func1";
}


/* file "c.js" */
// declare func1
const func1 = function() {
    return "It's c.js func1";
}

// export func1 as default
export { func1 as default }
  • export default 또는 선언 이후 export { <export할 변수> as default } 의 형태로 default하게 export가 가능

  • export default는 각 파일마다 하나의 변수만 가능

  • default로 export할 경우 import시에 중괄호가 필요없고 이름을 import시에 임의로 정할 수 있음
    => 그러나 혼란을 줄 수 있기에 원래의 이름 그대로 사용하는것이 약속

  • 보통은 default로 export할 하나의 메소드가 값만이 존재하는 파일에서만 사용하는것이 좋음

  • 아예 사용하지 않고 named export만을 사용할 것을 권장하는 경우도 많음

 

 

6. export from

/* file "a.js" */
// import f1 from "b.js"
import { f1 } from "./b.js";

console.log(f1());	// It's c.js func1



/* file "b.js" */
// import f1 from "c.js" and export again
export { f1 } from "./c.js";



/* file "c.js" */
// declare func1
const func1 = function() {
    return "It's c.js func1";
}

// export func1 as f1
export { func1 as f1 };
  • export { ... } from "module" 의 형태로 다른 파일에서 import해온 데이터를 그대로 다시 export 할 수 있음

  • 사용자가 여러 파일의 데이터를 하나의 파일에서 import 할 수 있게 해주는 index 파일을 만들기 위해 사용

  • 모든 데이터를 다시 export 하는 export * from "module" 을 실행 시 default export 된 데이터는 제외됨

  • default export 된 데이터는 export { default [as ...] } from "module" 과 같이 별도로 처리해주어야함

 

'언어 > JavaScript' 카테고리의 다른 글

#10 destructing  (0) 2022.02.23
#9 rest / spread 연산자  (0) 2022.02.23
#7 클래스(Class)  (0) 2022.02.21
#6 객체(Object)  (0) 2022.02.18
#5 기본 구문  (0) 2022.02.17

1. 정의

// 클래스 정의
class Student {
    constructor(id, name, grade) {
    	this.id = id;
        this.name = name;
        this.grade = grade;
    }
}


// 클래스의 생성자를 호출하여 객체 생성
// new <클래스명>(<생성자에 넘겨줄 인자>); 의 형태로 
// 클래스에 정의된 생성자(constructor)를 호출하여 객체를 생성할 수 있음
student_1 = new Student(1, "David", 3);

// 클래스 출력
// "{'id':1,'name':'David','grade':3}"
console.log(JSON.stringify(student_1));
  • class 키워드를 사용하여 class <클래스명> { ... } 의 형태로 클래스를 정의할 수 있음

  • class 내부에 생성자(constructor)를 정의하여 이 생성자를 호출하는 것으로 객체를 생성할 수 있음

  • 자주 쓰이는 형식의 객체는 클래스를 정의해두면 보다 간편하게 생성, 관리할 수 있음

 

 

2. protected property 와 accessor property(getter & setter)

// 클래스 정의
class Student {
    // 객체의 데이터 속성(property)들을 앞에 언더바(_)를 붙일경우 (protected)
    // 이 값을 접근자 프로퍼티를 사용하지않고 외부에서 직접 접근해선 안된다는 표시가 됨
    // 정말로 외부접근이 불가능한 것은 아니지만 일종의 약속에 가까움
    constructor(id, name, grade) {
    	this._id = id;
        this._name = name;
        this._grade = grade;
    }
    
    // 접근자 속성(Accessor Property)을 정의하여 사용자가 필드에
    // 제한된 방식으로만 접근할 수 있도록 허용해줄 수 있음
    // getter
    get id() {
    	return this._id;
    }
    get name() {
    	return this._name;
    }
    get grade() {
    	return this._grade;
    }
    get info() {
    	return `studnet_id: ${this._id} | name: ${this._name} | grade: ${this._grade}`
    }
    
    // setter
    set id(changedId) {
    	this._id = changedId;
    }
    set name(changedName) {
    	this._name = changedName;
    }
    set grade(changedGrade) {
    	this._grade = changedGrade;
    }
}


// 객체 생성
student_1 = new Student(2, 'Tom', 1);

// id, name, grade 등의 데이터 속성(property)은 모두 언더바를 붙여 선언했고
// info라는 속성은 아예 존재하지도 않지만 
// 접근자 프로퍼티인 getter와 setter를정의해두었기에
// 마치 실제로 존재하는 데이터속성에 접근하듯 접근할 수 있음

// studnet_1의 id, 이름, 학년을 각각출력
console.log(student_1.id);	// 2
console.log(student_1.name);	// "Tom"
console.log(student_1.grade);	// 3

// student_1의 info를 출력

console.log(student_1.info);	// "studnet_id: 2 | name: Tom | grade: 1"

// student_1의 name 속성값 변경
student_1.name = 'Benn';

// student_1의 info를 출력
console.log(student_1.info);	// "studnet_id: 2 | name: Benn | grade: 1"
  • 클래스 외부에서 클래스의 데이터 속성(data property) 혹은 필드(field)에 직접 접근을 허용하는 것은 
    보안적으로 권장되지 않기 때문에 클래스의 속성은 앞에 언더바를 붙여 protected하게 정의하는 것이 일반적
    (다만 이는 시스템적으로 보호되는 것이 아닌 일종의 약속이기 때문에 외부접근 자체는 가능하며 
    상속 관계에서 접근이 가능한 필드를 선언하는 Java의 protected와는 개념이 다름)

  • get <접근자 속성 이름>() { <반환값> } 의 형태로 getter를 정의하면 해당 클래스로 생성한 객체에서는
    <객체>.<접근자 속성 이름>으로 마치 존재하는 데이터 속성을 참조하듯이 반환값을 얻을 수 있음

  • set <접근자 속성 이름>(<값>) { ... } 의 형태로 setter를 정의하면 해당 클래스로 생성한 객체에서는
    <객체>.<접근자 속성 이름> = <값> 의 형태로 존재하는 데이터 속성의 값을 직접 변경하듯 값의 변경이 가능함

  • 만약 특정 속성을 읽기 전용으로 만들고 싶다면 단순히 setter를 정의하지 않으면 해결된다.

 

 

3. private

// 클래스 정의
class Student {
    // #을 붙인 private 필드를 선언
    #id;
    #name;
    #grade;
    
    constructor(id, name, grade) {
    	this.#id = id;
        this.#name = name;
        this.#grade = grade;
    }
    
    // 접근자 속성(Accessor Property)을 정의하여 사용자가 필드에
    // 제한된 방식으로만 접근할 수 있도록 허용해줄 수 있음
    // getter
    get id() {
    	return this.#id;
    }
    get name() {
    	return this.#name;
    }
    get grade() {
    	return this.#grade;
    }
    get info() {
    	return `studnet_id: ${this.#id} | name: ${this.#name} | grade: ${this.#grade}`
    }
    
    // setter
    set id(changedId) {
    	this.#id = changedId;
    }
    set name(changedName) {
    	this.#name = changedName;
    }
    set grade(changedGrade) {
    	this.#grade = changedGrade;
    }
}


// 객체 생성
student_1 = new Student(2, 'Tom', 1);

/* 접근자 프로퍼티를 사용할경우 private 필드에도 정상적으로 접근이 가능 */
// studnet_1의 id, 이름, 학년을 각각출력
console.log(student_1.id);	// 2
console.log(student_1.name);	// "Tom"
console.log(student_1.grade);	// 3

// student_1의 info를 출력
console.log(student_1.info);	// "studnet_id: 2 | name: Tom | grade: 1"

// student_1의 name 속성값 변경
student_1.name = 'Benn';

// student_1의 info를 출력
console.log(student_1.info);	// "studnet_id: 2 | name: Benn | grade: 1"


/* private 속성에는 직접 접근이 시스템적으로 불가능 */
// 직접 private 속성에 접근하려할 경우 문법오류 발생
console.log(student_1.#id);
console.log(student_1.#name);
console.log(student_1.#grade);
  • #을 붙여 시스템적으로 외부에서 접근 불가능한 private 필드를 선언할 수 있음

  • 개발자들간의 약속일뿐 실질적인 효력은 없는 protected 필드와 달리 문법적으로 강요되는 것이 장점

  • 하지만 상속관계에 있는 클래스에서도 접근 불가능하기 때문에 private 필드는 것은 과한 경우가 많음
    => protected가 시스템적인 효력이 없음에도 사용되는 이유

 

 

4. 메소드(Method)

// 클래스 정의
class Student {
    constructor(id, name, grade) {
    	this._id = id;
        this._name = name;
        this._grade = grade;
    }
    
    // 일반 메소드
    introduce() {
    	return `My name is ${this._name} and I'm in ${this._grade} grade. My student_id is ${this._id}`;
    }
    
    // static 메소드
    static classIntroduce() {
    	return 'This is Student class. It has three data property, id, name, and grade.';
    }
}


// 객체 생성
student = new Student(1, "David", 2);

// 일반메소드의 경우 클래스 자체에서의 호출은 불가능하며 생성된 객체(인스턴스)를 통해서만 호출가능
// Student.introduce()  => 오류 발생
console.log(student.introduce())


// static 메소드의 경우 클래스 자체에서의 호출이 가능하며 생성된 객체에서는 호출 불가능
console.log(Student.classIntroduce())
// student.classIntroduce()  => 오류 발생
  • 객체에 대한 설명에서도 언급했던 객체 내부의 함수인 메소드는 클래스에서도 정의 가능

  • 클래스의 메소드는 static 메소드와 non-static 메소드(일반 메소드)로 분류됨

  • static 메소드의 경우 클래스에서 직접 호출 가능한 메소드로, 인스턴스를 생성하지 않아도 호출 가능
    => 단, 인스턴스 생성 후에 생기는 값들, 즉 생성자(constructor)에서 선언되는 값 등에는 접근 불가능함 

  • non-static 메소드의 경우 클래스에서는 직접 호출 불가능하며 생성된 인스턴스에서만 호출 가능
    => 객체의 메소드를 정의할 때는 non-static으로 정의해야함.

'언어 > JavaScript' 카테고리의 다른 글

#9 rest / spread 연산자  (0) 2022.02.23
#8 import / export  (0) 2022.02.21
#6 객체(Object)  (0) 2022.02.18
#5 기본 구문  (0) 2022.02.17
#4 함수(Function)  (0) 2022.02.17

1. 생성

// 객체(object)의 선언
// 중괄호 내에 key: value 로 이루어진 속성(attribute)값들을 나열하여 선언
let sampleObject = {
    key1: value1,
    key2: value2,
    ...
}
  • JavaScript의 객체는 속성(Attribute)값들의 집합
  • 속성값은 key: value 쌍으로 구성
  • 속성의 이름에 해당하는 key 값에는 symbol, string 타입의 값을 사용 가능
  • 속성의 값에 해당하는 value에는 모든 타입의 값을 사용 가능

 

 

2. 참조

// name, std_id, class 속성을 가진 객체 student
let student = {
    name: 'David',
    std_id: 12345678,
    class: 'A'
}

// <객체>.<key> 혹은 <객체>["<key>"] 로 속성값 참조 가능 
console.log(student.name);
console.log(student["name"]);
  • . 연산자 혹은 대괄호([ ]) 를 사용하여 객체의 속성값을 참조 가능
  • 존재하지 않는 속성값을 참조할 경우 undefined 반환
  • 단, 숫자를 키값으로 사용할 경우 .연산자를 사용한 참조는 불가능

 

 

3. 속성 추가/수정

let obj = {
    id: 123,
    name: "Jack"
}

// . 연산자로 속성 추가
obj.height = 170;
console.log(obj.height);

// 대괄호 표현으로 속성 추가
obj["weight"] = 60;
console.log(obj.weight);
  • .연산자나 대괄호 표현으로 추가할 속성의 key를 명시한 뒤 값을 대입해주면 속성 추가 가능
  • 이미 존재하는 속성에 값을 대입할 경우 값을 수정할 수 있음

 

 

4. 속성 삭제

let obj = {
    id: 1234,
    name: "Tom",
    height: 150,
    weight: 45
}

// delete 연산자를 사용하여 속성 삭제
delete obj.height;
delete obj["weight"];

// 속성이 삭제되었기 때문에 undefined 반환
console.log(obj.height);
console.log(obj.weight);
  • delete 연산을 사용하여 속성을 삭제할 수 있음
  • 제거할 속성값을 참조한뒤 그 앞에 delete 키워드를 붙여주기만 하면 간단하게 삭제 가능
  • 배열또한 객체이기에 이 방법으로 element를 삭제할 수 있지만 배열에서 사용하는 것은 권장하지 않음

 

 

5. 빠른 생성

id = 123;
name = "David";
height = 157;


// 직접 key: value를 명시하여 생성
let obj1 = {
    "id": id,
    "name": name,
    "height": height
}

// 값을 저장한 변수의 이름을 그대로 key로 사용하여 빠른 생성
let obj2 = { id, name, height }

// 두 객체를 문자열화하여 출력시
// 둘 다 "{'id':123,'name':'David','height':157}" 로 같은 결과를 보임
console.log(JSON.stringify(obj1));
console.log(JSON.stringify(obj2));
  • 객체 선언시 value로 사용할 값을 저장한 변수를 그대로 넣어줄 경우 자동으로 변수명을 key로 사용

 

 

6. 메소드

// 일반적인 속성처럼 메소드를 정의 
let obj = {
	name: "Jerry",
    introduce: function() {
    	return `My name is ${ this.name }.`;
    }
}
console.log(obj.introduce());

// 빠른 메소드 정의
let obj2 = {
	name: "Susie",
    introduce() {
    	return `My name is ${ this.name }.`;
    }
}
console.log(obj2.introduce());
  • JavaScript의 객체는 함수를 값으로 가지는 속성인 메소드(method)를 가질 수 있음
  • 메소드는 다른 속성처럼 key: value 형태로 정의할 수 있음
  • key: value 형태대신 function키워드를 생략하고 함수를 정의하듯 정의할 수도 있음

 

 

7. 객체와 const

// 객체를 변경할 수 없도록 하기 위해 const키워드로 선언
const obj = {
    id: 123,
    name: "Jane"
}

// 속성값 변경 시도
obj.name = "Lina";

// 속성값이 변경되지 않았는지 확인하기 위해 출력
// 변경이 정상적으로 이루어졌음을 확인 가능
// 객체를 가리키는 변수를 const로 선언해도 const를 참조하여 
// 속성값을 변경하는 것은 막을 수 없음
console.log(obj.name);



// 객체의 변경을 제대로 방지하기 위해 Object.freeze 메소드 호출
Object.freeze(obj);

// 속성값 변경 시도
obj.name = "Jane";

// 속성값이 변경되지 않았는지 확인하기 위해 출력
// 이번에는 변경사항이 적용되지 않았음을 확인할 수 있음
console.log(obj.name);
  • const 키워드는 해당 이름이 가리키는 값을 재정의할 수 없도록 하기위한 키워드
  • const로 객체를 선언해도 그 변수에 다른 값을 대입할 수 없을 뿐 객체를 수정하는 것은 가능함
  • 객체를 수정 불가능하도록 만들려면 Object.freeze(<객체>) 메소드를 호출해줘야함

 

'언어 > JavaScript' 카테고리의 다른 글

#8 import / export  (0) 2022.02.21
#7 클래스(Class)  (0) 2022.02.21
#5 기본 구문  (0) 2022.02.17
#4 함수(Function)  (0) 2022.02.17
#3 배열(Array)  (0) 2022.02.15

1. 조건문

// if-else 구문
if (condition_1) {
	// condition_1이 참일 경우 실행될 코드
}
else if (condition_2) {
	// condition_1은 거짓이고 condition_2는 참일 경우 실행될 코드
}
else {
	// 모든 조건이 거짓일 경우 실행될 코드
}


// switch 구문
switch(condition) {
	case CASE1:
    	// condition 이 CASE1일 경우(condition === CASE1) 실행될 코드
        break;
	case CASE2:
    	// condition 이 CASE2일 경우(condition === CASE2) 실행될 코드
        break;
    case CASE3:
    	// condition 이 CASE3일 경우(condition === CASE3) 실행될 코드
        break;
    default:
    	// 어느 케이스에도 해당하지 않을 경우 실행될 코드
        break;
}
  • C나 Java의 조건문들과 동일하게 동작
  • switch문의 경우 case 값으로 숫자만이 아닌 문자열이나 다른 타입의 값도 사용 가능
  • condition 과 case의 비교는 일치(===)연산으로 이루어짐

 

 

2. 반복문

// 일반적인 for 반복문
for(let i=0; i<n; i++) {
	// 반복하여 실행될 코드
}


// for-in 구문
// JavaScript 의 for in 구문은 대상 객체(object)의 key값들을 순차적으로 참조
// 배열의 경우에는 물론 index가 key값이기에 index를 순차적으로 참조
// 대부분의 경우 배열에 대해 for in 구문을 사용하는 것은 권장되지않으며
// 배열의 element를 참조하는 것은 일반적인 for문을 통한 순회가 가장 효율적
let arr = [6, 2, 3, 7, 9];
for(let i in arr) {
	console.log(arr[i]);	// 라인마다 6 2 3 7 9 각각 출력
}


// while 구문
while(condition) {
	// condition이 참일 동안 반복 실행될 코드
}


// do-while 구문
do {
	// 처음 한번은 반드시 실행되며
    // 이후로는 condition이 참인 동안에만 반복 실행될 코드
} while(condition);
  • 기본적으로 C나 Java와 동일한 문법을 사용 가능
  • for-in 구문의 경우 객체(Object)의 속성을 순회하기 위한 수단으로 객체의 key값을 순차적으로 순회
  • 배열에 사용할 경우 물론 index를 얻을 수 있지만 단순 for문을 사용하는 것이 보다 효율적이고 빠름
  • forEach 메소드를 사용하여 객체를 순회하는 것도 가능하지만 모든 브라우저에서 지원을 보장받지는 않음

 

 

3. 삼항 조건 연산자(Tenary Conditional Operator)

score = 82

// if 문을 사용한 학점분류
let grade; 
if(score >= 90) {
	grade = 'A';
}
else if(score >= 80) {
	grade = 'B';
}
else {
	grade = 'C';
}
console.log(grade);	// "B"

// 삼항 조건 연산자를 사용
grade = (score >= 90) ? 'A' : ((score >= 80) ? 'B' : 'C')
console.log(grade);	// "B"
  • C나 Java와 마찬가지로 condition ? val_if_true : val_if_false  의 형태로 삼항 조건 연산자 사용 가능

'언어 > JavaScript' 카테고리의 다른 글

#7 클래스(Class)  (0) 2022.02.21
#6 객체(Object)  (0) 2022.02.18
#4 함수(Function)  (0) 2022.02.17
#3 배열(Array)  (0) 2022.02.15
#2 문자열(String)  (0) 2022.02.14

1. 정의

// 일반적인 함수 정의
function functionName (arg1, arg2, arg3=<default>) {
	// 코드
}
  • C나 Java와 유사하지만 return type 대신 function 키워드를 사용하여 함수를 정의할 수 있음
  • 인자에 =<디폴트값> 을 붙여 인자가 전달되지 않을경우 사용될 기본값을 설정 가능
  • JavaScript에서 함수 바깥에서 정의된 모든 변수는 Global Scope를 가짐
  • 함수는 아무 값도 반환하지 않을 경우 실행결과로 undefined를 반환
  • JavaScript의 경우 함수를 first-class citizen으로 취급하기에 함수를 변수에 저장하거나 인자로 넘길 수 있음

 

 

2. 익명 함수(Anonymous Function)

// 익명함수 정의
let a = function() {
	// 코드
}
  • 함수 이름을 생략한 익명 함수를 정의할 수도 있음
  • 일회성 함수의 경우 굳이 이름을 가진 함수로 정의하지 않고 익명함수로 정의하여 사용
  • 함수를 정의하여 바로 변수에 저장하거나 인자로 넘기는 경우에도 사용

 

 

3. 람다 함수(Lambda Function)

// 람다식으로 함수 정의
let a = (<매개변수>) => <반환값>
  • ( <매개변수> ) => <반환값>의 형태로 함수 정의 가능
  • 동작이 단순한 함수일 경우 람다함수를 사용하면 보다 간결하게 정의할 수 있음

'언어 > JavaScript' 카테고리의 다른 글

#6 객체(Object)  (0) 2022.02.18
#5 기본 구문  (0) 2022.02.17
#3 배열(Array)  (0) 2022.02.15
#2 문자열(String)  (0) 2022.02.14
#1 기본 문법  (0) 2022.02.14

1. 선언

// 빈 배열 선언
let empty_arr1 = new Array();
let empty_arr2 = [];


// 배열 선언과 동시에 초기화
let arr1 = new Array(1, 2, 3, 4, 5);
let arr2 = [1, 2, 3, 4, 5];


// 배열 선언시 길이지정
// 생성자의 인자로 한개의 정수값을 넘길경우 배열의 길이로 인식 
let init_length_arr = new Array(10);
console.log(init_length_arr)	// [,,,,,,,,,]
  • JavaScript의 배열은 Python의 리스트처럼 사용 가능한 자료구조(C나 Java의 배열보다 내장된 기능이 다양함)

  • 선언 방법은 생성자를 호출하는 방식(new Array()) 과 대괄호를 사용하는 방법이 있음

  • 생성자를 호출할 경우 인자로 하나의 정수만을 넘겨주면 그 값을 길이로하는 배열 생성 (초기값 undefined)

  • 선언과 동시에 초기화 가능

 

 

2. 자주 사용되는 연산

  • 삽입
    let arr = [1, 2, 3, 4, 5];
    
    // push(e) : 맨 뒤에 e 삽입
    arr.push(6);
    console.log(arr);	// [1, 2, 3, 4, 5, 6]
    
    
    // unshift(e) : 맨 앞에 e 삽입
    arr.unshift(7);
    console.log(arr);	// [7, 1, 2, 3, 4, 5, 6]
    • push 메소드를 사용하여 배열의 맨 뒤에 원소 삽입 가능

    • unshift 메소드를 사용하여 배열의 맨 앞에 원소 삽입 가능

  • 삭제
    let arr = [1, 2, 3, 4, 5];
    
    // pop() : 맨 뒤의 원소를 제거하고 제거한 원소를 반환
    console.log(arr.pop());	// 5
    console.log(arr);	// [1, 2, 3, 4]
    
    
    // shift() : 맨 앞의 원소를 제거하고 제거한 원소를 반환
    console.log(arr.shift());	// 1
    console.log(arr);		// [2, 3, 4]
    
    
    // 빈 배열에서 pop, shift 호출시 undefined를 반환
    let arr2 = [];
    console.log(arr2.pop());
    console.log(arr2.shift());
    • pop 메소드를 사용하여 배열의 맨 뒤의 원소를 제거 가능

    • shift 메소드를 사용하여 배열의 맨 앞의 원소를 제거 가능

    • 빈 배열에서 호출할 경우 undefined 반환

  • 접근
    let arr = [1, 2, 3, 4, 5];
    console.log(arr[2]);		// 3
    console.log(arr[arr.length-1]);	// 5​
    • 인덱스를 통해 배열의 n번째 요소에 접근 가능

    • 배열의 길이는 <배열>.length 로 알아낼 수 있음

  • 순회
    let arr = [1, 3, 7, 2, 16];
    arr.forEach(function(currentValue, index, array) {
    	// currentValue: 현재 요소의 값
        // index: 현재 인덱스
        // array: callback 함수 내에서 this로 사용할 값
        console.log(`${index}: ${currentValue}`);
        if (index == array.length-1) {
        	console.log('last element');
        }
    });
    
    /*
    "0: 1"
    "1: 3"
    "2: 7"
    "3: 2"
    "4: 16"
    "last element"
    */​
    • forEach 메소드에 인자로 callback 함수를 넘겨주면 배열을 순회하며 작업을 수행

    • 넘겨줄 callback의 인자에 currentValue는 반드시 들어가야하며(이름은 상관없음) index, array는 선택사항

    • forEach 메소드는 아무 값도 반환하지 않음

  • splice
    let arr = [1, 3, 5, 7, 9];
    
    // splice(start, deleteCount, item1, item2, ...)
    // start 인덱스부터 시작하여 deleteCount 만큼의 요소를 제거하고
    // item1, item2, ...를 그자리에 삽입
    
    // deleteCount를 0으로 할 경우 단순히 주어진 값을 삽입
    arr.splice(1, 0, 2, 4);
    console.log(arr);
    
    // 추가할 값을 생략할 경우 요소의 삭제만 실행
    arr.splice(2, 1);
    console.log(arr);
    
    // 추가할 값이 없고 deleteCount도 0일 경우
    // 에러는 발생하지 않고 아무 작업도 수행하지 않음
    arr.splice(2, 0);
    console.log(arr);
    • splice 메소드를 사용하여 특정 인덱스로부터 deleteCount개의 요소들을 제거 가능

    • 추가할 요소를 인자로 넘겨줄 경우 인덱스에 해당 요소들을 삽입 가능

  • 탐색
    let arr = [1, 2, 3, 2];
    
    // indexOf(e) 는 e를 처음으로 찾은 인덱스를 반환
    console.log(arr.indexOf(2));	// 1
    
    // lastIndexOf(e) 는 e를 마지막으로 찾은 인덱스를 반환
    console.log(arr.lastIndexOf(2));	// 3
    
    // 존재하지 않는 값일 경우 -1 반환
    console.log(arr.indexOf(4));	// -1
    • indexOf, lastIndexOf 를 사용하여 특정 원소가 몇 번째 인덱스에 있는지 탐색 가능

  • 복사
    let nested_arr = [[1, 2, 3], [2, 3, 4]];
    
    // 얕은 복사
    // 원본 배열의 요소를 그대로 가져오기떄문에 원본과 복사본의 수정이 서로에게 영향을 미침
    let copy1 = nested_arr.slice();
    let copy2 = [...nested_arr];
    let copy3 = Array.from(nested_arr);
    
    /* 
    [
    [1, 2, 3], 
    [2, 3, 4]]
    */
    console.log(nested_arr);
    console.log(copy1);
    console.log(copy2);
    console.log(copy3);
    
    nested_arr[0][1] = 5;
    
    /* 
    [
    [1, 5, 3], 
    [2, 3, 4]]
    */
    console.log(nested_arr);
    console.log(copy1);
    console.log(copy2);
    console.log(copy3);
    
    
    // 깊은 복사
    // JSON으로 직렬화한 뒤 다시 파싱하는 것으로 완전히 독립적인 복사본 생성
    // 한쪽의 수정이 서로에게 영향을 미치지 않음
    let deepcopy = JSON.parse(JSON.stringify(nested_arr));
    
    /* 
    [
    [1, 5, 3], 
    [2, 3, 4]]
    [
    [1, 5, 3], 
    [2, 3, 4]]
    */
    console.log(nested_arr);
    console.log(deepcopy);
    
    nested_arr[0][1] = 2;
    
    /* 
    [
    [1, 2, 3], 
    [2, 3, 4]]
    [
    [1, 5, 3], 
    [2, 3, 4]]
    */
    console.log(nested_arr);
    console.log(deepcopy);
    • slice 메소드에 아무 인자도 넘겨주지않는 것으로 얕은 복사가 가능  => <배열>.slice()

    • spread 연산자를 사용하여 얕은 복사가 가능 => [...<배열>]

    • Array.from 메소드를 사용하여 얕은 복사가 가능 => Array.from(<배열>)

    • JSON을 사용하여 깊은 복사가 가능 => JSON.parse(JSON.stringify(<배열>))

  • join
    let arr = [1, 2, 3, 4, 5];
    console.log(arr.join(''));	// "12345"
    console.log(arr.join('*'));	// "1*2*3*4*5"
    • join 메소드를 사용하여 배열의 요소를 하나의 문자열로 만들 수 있음

    • join의 인자로 구분자를 줄 경우 요소 사이에 구분자를 넣은 문자열을 만들 수 있음

  • reverse
    let arr = [1, 2, 3, 4, 5];
    arr.reverse();
    console.log(arr);	// [5, 4, 3, 2, 1]​
    • reverse 메소드를 사용하여 배열을 뒤집을 수 있음

  • sort
    let arr = [2, 4, 1, 5, 3];
    arr.sort();
    console.log(arr);	// [1, 2, 3, 4, 5]
    • sort 메소드를 사용하여 배열의 요소를 정렬할 수 있음

    • 인자로 비교함수를 넘길 수 있음
      • 비교함수는 compareFunction(a, b) => <return> 의 형태로 구성
      • a가 b보다 작을 경우 음수를, 클 경우 양수를, 같을 경우 0을 반환해야한다.

  • concat
    let arr = [1, 2, 3];
    let arr2 = [4, 5, 6];
    let num = 7
    
    arr = arr.concat(arr2);
    console.log(arr);	// [1, 2, 3, 4, 5, 6]
    
    arr = arr.concat(num);
    console.log(arr);	// [1, 2, 3, 4, 5, 6, 7]
    • concat 메소드를 사용하여 배열에 원소 혹은 배열을 이어붙일 수 있음

    • Python과 달리 +연산을 수행할 경우는 단순히 문자열로 변환한 뒤 이어붙인 결과를 반환함

  • map
    let arr = [1, 2, 3, 4, 5];
    
    // 인자로 받은 수를 제곱한 결과를 반환하는 함수
    function func(o) {
        return o ** 2;
    }
    
    // map 함수를 사용하여 arr의 각 요소에 함수 func를 수행한 결과를 반환받음
    let res = arr.map(func);
    
    // res 출력
    console.log(JSON.stringify(res));	// "[1,4,9,16,25]"
    • map을 사용하여 배열의 각 요소에 특정 함수를 수행한 결과를 배열의 형태로 얻을 수 있음

  • reduce
    let arr = [1, 2, 3, 4, 5];
    
    // reduce 메소드를 사용하여 배열의 모든 숫자를 합한 결과를 구함
    let res = arr.reduce((acc, cur, idx) => acc + cur, 0);
    
    // 결과 출력
    console.log(res);	// 15
    
    
    // reduce 메소드를 사용하여 배열의 숫자중 홀수만을 담은 배열을 구함
    res = arr.reduce((acc, cur, idx) => {
        if(cur % 2) {
        	acc.push(cur);
        }
        return acc;
    }, []);
    
    // 결과 출력
    console.log(JSON.stringify(res));	// "[1,3,5]"
    • reduce 메소드를 사용하여 각 요소에 특정 작업을 수행한 뒤 그 결과를 누적값(acc)에 반영하여
      모든 요소에 대해 작업을 마친 후 누적값을 반환받을 수 있음

    • 간단하게는 배열의 요소를 모두 더하는 작업부터 조건에 따른 필터링이나 최댓값, 최솟값 혹은 특정 값의
      인덱스 탐색, map 메소드의 구현 등 다양하게 활용 가능한 강력한 기능

 

 

 

'언어 > JavaScript' 카테고리의 다른 글

#5 기본 구문  (0) 2022.02.17
#4 함수(Function)  (0) 2022.02.17
#2 문자열(String)  (0) 2022.02.14
#1 기본 문법  (0) 2022.02.14
#0 자바 스크립트  (0) 2022.02.14

+ Recent posts