Developer's Development
3.4.3 [화면 구현] JavaScript: Core 본문
JavaScript 개요
JavaScript는 웹 페이지의 보조적인 기능을 수행하기 위해 브라우저에서 동작하는 경량 프로그래밍 언어로서 1996년 넷스케이프 커뮤니케이션즈에서 처음 개발되었다.
ECMAScript 5(ES5)는 HTML5와 함께 출현한 표준 사양이며,
2015년에 공개된 ECMAScirpt 6(ES6)는 let/const 키워드, 화살표 함수, 클래스 등과 같이 범용 프로그램이 언어로서 갖춰야 할 기능들을 대거 도입하는 큰 변화가 있었다.
- JavaScript의 성장
Ajax (1999년)
jQuery (2006년)
V8 자바스크립트 엔진 (2008년)
Node.js (2009년)
SPA 프레임워크
- JavaScript의 특징
웹 브라우저에서 동작하는 유일한 프로그래밍 언어이다.
개발자가 별도의 컴파일 작업을 수행하지 않는 인터프리터 언어이다.
❗인터프리터 언어
= 코드가 실행되는 단계인 런타임에 문 단위로 한 줄씩 중간 코드인 바이트 코드로 변환한 후 실행하는 언어
클래스 기반 객체지향 언어보다 효율적이면서 강력한 프로토타입 기반의 객체지향 언어이다.
개발 환경 구축
- Node.js 다운로드
Node.js — Run JavaScript Everywhere
Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.
nodejs.org
- cmd
node -v, npm -v로 버전을 출력하여 정상적으로 설치되었는지 확인
- vscode
test.js 파일 생성
console.log('hello javascript')
실행시킬 땐 Ctrl + ` (terminal)에서 node test.js로 실행
Extension > 'Code Runner' install
→ Ctrl + Alt + N으로 파일 실행 가능
variable (변수)
- data type (데이터 타입)
number (숫자 타입), string (문자열 타입 '', "", ``), boolean (논리 타입), undefined & null, symbol & object
- dynamically typed language (동적 타입 언어)
1. 정적 타입(static/strong type) 언어
2. 동적 타입(dynamic/weak type) 언어
- implicit-coercion (암묵적 타입 변환)
convert to string (문자열 타입으로 변환)
convert to number (숫자 타입으로 변환)
convert to boolean (논리 타입으로 변환)
- explicit-coercion (명시적 타입 변환)
convert to string (문자열 타입으로 변환): toString()
convert to number (숫자 타입으로 변환): parseInt(), parseFloat()
convert to boolean (논리 타입으로 변환): !!
// JS 한 줄 주석
/*
JS 여러줄 주석
*/
/* 문자열 타입 */
var string;
string = 'JavaScript "큰 따옴표" 자체로 출력';
string = "JavaScript '작은 따옴표' 자체로 출력";
// string = `JavaScript`;
console.log(string);
// var str = '안녕하세요.
// 맹구입니다.';
var str = '안녕하세요. \n맹구입니다.';
console.log(str);
/* 템플릿 리터럴 */
/*
ES6부터 도입된 벡틱(``)을 사용한 표현식으로
멀티라인 문자열, 표현식 삽입 등
편리한 문자열 처리 기능을 제공하는 문자열 표기법
*/
var multiline = `안녕하세요.
진짜 맹구입니다.`;
console.log(multiline);
var teacher = '맹구';
var student = 17;
// 맹구 선생님과 함께 하는 17기의 SKN 일대기!
console.log(teacher + " 선생님과 함께 하는 " + student + "기의 SKN 일대기!");
console.log(`${teacher} 선생님과 함께 하는 ${student}기의 SKN 일대기!`);

/* undefined */
var item;
console.log(item); // undefined
/* null */
var hello = 'hello';
hello = null;
console.log(hello); // null
operator (연산자)
- comparison operator (비교 연산자)
/* 비교 연산자 */
/*
- 동등 비교(==, !=): 값이 같은지 비교 (암묵적 형변환 비교)
- 일치 비교(===, !==): 타입과 값이 모두 같은지 비교
*/
console.log("===== 숫자 1과 문자 '1', true 비교 =====");
console.log(`1 == '1' : ${1 == '1'}`); // T
console.log(`1 == true : ${1 == true}`); // T
console.log(`1 === '1' : ${1 === '1'}`); // F
console.log(`1 === true : ${1 === true}`); // F
console.log("===== 숫자 0과 빈 문자열 '', 문자 '0', false 비교 =====");
console.log(`0 == '0' : ${0 == '0'}`); // T
console.log(`0 == '' : ${0 == ''}`); // T
console.log(`0 == false : ${0 == false}`); // T
console.log(`0 === '0' : ${0 === '0'}`); // F
console.log(`0 === '' : ${0 === ''}`); // F
console.log(`0 === false : ${0 === false}`); // F
console.log("===== NaN과 NaN 비교 =====")
// NaN은 자신과 일치하지 않는 유일한 값
console.log(`NaN == NaN : ${NaN == NaN}`); // F
console.log(`NaN === NaN : ${NaN === NaN}`); // F
console.log(`Number.isNaN(NaN) : ${Number.isNaN(NaN)}`); // T
- logical operator (논리 연산자)
👉🏻 short circuit evaluation (단축 평가)
표현식을 평가하는 도중 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다.
/*
논리 연산자
- AND : &&
- OR : ||
- NOT : !
*/
// OR, AND 연산자 표현식의 결과는 boolean이 아닐 수도 있음
// 'apple'이 이미 Truthy한 값이므로 true로 평가되고,
// 논리 연산의 결과를 결정한 피연산자 'apple'을 그대로 반환
console.log(false || 'apple'); // apple
console.log('apple' || false); // apple
console.log('apple' || 'banana'); // apple
console.log(false && 'apple'); // false
console.log('apple' && false); // false
console.log('apple' && 'banana'); // banana
// 단축 평가를 사용해 if문 대체 가능
var num = 1;
if (num % 2 == 0) {
console.log('짝수');
} else {
console.log('홀수');
}
num % 2 == 0 && console.log('짝수');
num % 2 == 0 || console.log('홀수');
// 객체가 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고
// 프로퍼티를 참조할 때 단축 평가를 유용하게 활용 가능
var obj = null;
// console.log(obj.value);
obj && console.log(obj.value);
- ES11 operator
👉🏻 optional chaining operator (옵셔널 체이닝 연산자)
/*
?.
- ES11(EcmaScript2020)에서 도입된 연산자
- 좌항의 피연산자가 null 또는 undefined인 경우 undefined 반환
- 그렇지 않으면 우항의 프로퍼티 참조 이어감
*/
var obj = null;
// var val = obj.value; // TypeError
// var val = obj && obj.value; // 단축 평가로 해결
var val = obj?.value;
console.log(val); // undefined
// 논리연산자 &&를 이용한 단축 평가에서는
// 빈 문자열 같은 Falsy한 값을 false 취급해서 문제 발생 => 옵셔널 체이닝이 해결
var str = '';
var len = str.length; // 단축 평가 이용: len == ''
len = str?.length; // 옵셔널 체이닝 이용: len == 0
console.log(len); // 0
👉🏻 nullish coalescing operator (null 병합 연산자)
/*
??
- ES11(ECMAScript2020)에서 도입된 연산자
- 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자 변환
- 그렇지 않으면 좌항의 피연산자 반환
- 변수 기본값 설정 시 유용
*/
var test = null ?? 'default';
console.log(test); // default
// 단축 평가 ||를 사용해 기본값을 설정하는 방식은
// 아래와 같은 빈 문자열을 false로 취급해 기본 값이 할당되는 문제 발생
// => nullish coalescing 방식이 해결
var str = null;
var value = str || 'default';
value = str ?? 'default';
console.log(value); // default
object literal (리터럴 객체)
- object (객체)
// 객체 리터럴을 통한 객체 생성 (중괄호 내 0개 이상의 프로퍼티 정의)
var teacher = {
// 프로퍼티: 객체의 상태를 나타내는 값 (data)
name: "맹구",
age: 900,
// 메서드: 프로퍼티(상태 데이터)를 참조하고 조작할 수 있는 동작
getInfo: function() {
return `${this.name}은(는) ${this.age}세의 선생님입니다.`
}
}
console.log(typeof teacher); // object
console.log(teacher); // { name: '맹구', age: 900, getInfo: [Function: getInfo] }
var student = {};
console.log(typeof student); // object
console.log(student); // {}
- property (속성)
// 객체 == 프로퍼티의 집합
// 프로퍼티 == 키(key): 값(value)
var idol = {
group: 'BTS',
'@ s o n g @': 'Fire', // 특수문자도 key값으로 사용 가능 (단, ''로 감싸야 함)
'': '', // 빈 문자열도 key값으로 사용 가능
0: 1, // 숫자 key는 내부적으로 문자열로 변환됨
var: 'var', // 예약어도 key로 사용 가능
group: '방탄소년단' // 이미 존재하는 key를 중복 선언하면 나중에 선언한 프로퍼티로 덮어씀
}
var key = 'count';
idol[key] = 7;
console.log(typeof idol); // object
console.log(idol);
// 마침표 표기법
console.log(idol.group);
// 대괄호 표기법 (프로퍼티 키는 반드시 따옴표로 감싼 문자열 사용)
console.log(idol['0']); // 1
console.log(idol['group']); // '방탄소년단'
/* 프로퍼티 값 단축 구문 (ES6)*/
var productName = 'iPhone17';
var price = 1000000;
var product = {
productName: productName,
price: price
};
console.log(product);
// 프로퍼티 값으로 변수를 사용하는 경우
// 변수 이름과 프로퍼티 key가 동일한 이름일 때 프로퍼티 key 생략 가능
var new_product = {
productName, price
};
console.log(new_product); // { productName: 'iPhone17', price: 1000000 }
/* 계산된 프로퍼티 key (ES5) */
// 계산된 프로퍼티 key로 프로퍼티를 동적 생성 가능 (대괄호 표기법 사용)
var prefix = 'B';
var index = 1;
var boardObj = {};
boardObj[prefix + '-' + index++] = '게시글 1';
boardObj[prefix + '-' + index++] = '게시글 2';
boardObj[prefix + '-' + index++] = '게시글 3';
console.log(boardObj); // { 'B-1': '게시글 1', 'B-2': '게시글 2', 'B-3': '게시글 3' }
// ES6
// 객체 리터럴 내부에서도 계산된 프로퍼티 key로 key 동적 생성 가능
var new_boardObj = {
[`${prefix}-${index++}`] : '게시글 4',
[`${prefix}-${index++}`] : '게시글 5',
[`${prefix}-${index++}`] : '게시글 6',
}
console.log(new_boardObj);
- method
// 메소드를 정의하려면 프로퍼티 값으로 함수를 할당 (ES5)
var puppy = {
name: '뽀삐',
eat: function(food) {
console.log(`${this.name}은(는) ${food}를 맛있게 먹어요~!`);
}
};
puppy.eat('소고기'); // 뽀삐은(는) 소고기를 맛있게 먹어요~!
/* 프로퍼티 값 단축 구문 (ES6)*/
var squirrel = {
name: '람쥐썬더',
action(skill) {
console.log(`${this.name}이(가) ${skill}을 보여줍니다!`);
}
};
squirrel.action('현란한 강의'); // 람쥐썬더이(가) 현란한 강의을 보여줍니다!
- property change, add, remove (프로퍼티 값 변경, 추가, 삭제)
/*
- 존재하지 않는 프로퍼티에 접근해서 값을 대입 > 추가
- 존재하는 프로퍼티에 접근해서 값을 대입 > 수정
- delete 키워드를 이용해 프로퍼티에 접근 > 삭제
(이때 존재하지 않는 프로퍼티를 넣어도 에러 없이 무시됨)
*/
var kitty = {
name: '나비'
};
// 추가
kitty['zipsa'] = '맹구';
kitty.like = '츄르';
console.log(kitty); // { name: '나비', zipsa: '맹구', like: '츄르' }
// 수정
kitty.name = '보리';
kitty['like'] = '맹구';
console.log(kitty); // { name: '보리', zipsa: '맹구', like: '맹구' }
// 삭제
delete kitty.like;
delete kitty['zipsa'];
delete kitty.age;
console.log(kitty); // { name: '보리' }
- 연산자 (in)
var actor = {
name: '차은우',
age: 30,
gender: 'M',
company: undefined
}
console.log(actor.name === undefined); // false
console.log(actor.drama === undefined); // true
console.log(actor.company === undefined); // true
// 프로퍼티 존재 여부 확인 가능
console.log('name' in actor); // true
console.log('drama' in actor); // false
console.log('company' in actor); // true
// for-in 반복문
// 객체의 key를 순회하며 받음
for (var key in actor) {
console.log(key);
console.log(actor[key]);
}
function (함수)
- 함수 선언 (function declaration)
function hello(name) {
return `${name}님 안녕하세요 :)`;
}
// JS엔진은 생성된 함수를 호출하기 위해
// 함수 이름과 동일한 식별자를 암묵적으로 생성하고 거기에 함수 객체를 할당함
/*
var hello = function hello(name) {
return `${name}님 안녕하세요 :)`;
};
*/
/* 함수 표현식 (function expression) */
/*
- var 변수 = 함수 (단, 함수명 생략 가능)
- 변수명에 해당하는 식별자로 함수 호출해야 함
- 함수명을 생략하지 않아도 문제는 없지만 함수 호출은 식별자(변수)로만 가능함
*/
var hi = function new_hello(name) {
return `${name}야 안녕!!!`;
};
hi = function new_hello(name) {
return `${name}야 안녕!!!`;
};
console.log(hello('맹구')); // 맹구님 안녕하세요 :)
console.log(hi('맹구')); // 맹구야 안녕!!!
// console.log(new_hello('맹구')); // ReferenceError
- 함수 호이스팅 (function hoisting)
/*
함수 선언문은 이전 JS 엔진에 의해 먼저 실행된다.
따라서 함수 선언문 이전에 해당 함수를 참조하거나 호출할 수 있다.
이를 JS 고유의 특징, 함수 호이스팅이라고 한다.
단, 변수 할당문의 값은 런타임에 평가되므로
함수 표현식으로 정의한 함수는 반드시 함수 표현식 이후에 참조 또는 호출해야 한다.
*/
console.log(returnHello); // [Function: returnHello] :함수 참조
console.log(returnHello('맹구')); // 맹구 HELLO ~! :함수 호출
console.log(returnHi); // undefined
console.log(returnHi('maenggu')); // TypeError: returnHi is not a function
function returnHello(name) {
return `${name} HELLO ~!`;
}
var returnHi = function(name) {
return `Yo! ${name} HI!!!`;
}
- 매개변수(Parameter)와 인자(Arguments)
// function lunch(menu) {
function lunch(...menu) { // 가변인자
console.log('lunch가 몰래 갖고 있는 args:', arguments);
// arguments: 함수 내부적으로 가지고 있는 인자값을 다 저장한 객체
console.log('lunch가 받은 menu:', menu);
return `오늘 점심은 ${menu}를 먹었어. 아주 맛있더라고~`;
}
console.log(lunch('김치찌개'));
console.log(lunch()); // 인자가 부족해서 할당되지 않으면 undefined
// console.log(menu); // 파라미터 값은 함수 내부에서만 사용 가능
console.log(lunch('양꼬치', '양갈비', '소갈비', '채끝살')); // 파라미터보다 많은 인자는 무시됨
function dance(danceName) {
// 인자 검증
// 1. 인자를 1개만 받아야 해
// 2. 1개의 인자는 문자열이어야 해
// 3. 빈 문자열이면 안돼
if (arguments.length > 1 || typeof danceName !== 'string' || danceName.length === 0) {
throw new TypeError('잘못된 인자 딱 걸렸음!!!');
}
return `${danceName} 춤추기 시작💃🏻🕺🏻🤸🏻♀️`;
}
result = dance('꼭짓점댄스');
console.log(result);

- arrow function (화살표 함수)
/* 화살표 함수 (arrow function) */
var message;
message = function() {
return "Hello World👋🏻"
};
console.log("function", message());
// 화살표 함수 기본 형식
message = () => {
return "Hello World👋🏻"
};
console.log("arrow function", message());
// 함수 수행 내용이 return 뿐이라면
// return 키워드 생략 가능 + 함수블럭(중괄호) 생략 가능
// 단, 파라미터가 없더라도 화살표 앞 ()는 생략 불가
message = () => "Hello World👋🏻"
console.log("arrow function without {}", message());
message = (str1, str2) => str1 + "Hello World👋🏻" + str2;
console.log("arrow function with params", message("파라미터 ", " 전달 완료!"))
// 하지만 파라미터가 단 1개인 경우에는 화살표 앞 ()도 생략 가능
message = str1 => str1 + "Hello World👋🏻";
console.log("arrow function with param", message("파라미터 "));
// 반환값이 object인 경우에는 return 키워드와 코드블럭{}을 생략하려면 ()로 감싸줘야 함
var createUser = (name, hobby) => ({name, hobby});
console.log(createUser('맹구', 100));
// 화살표 함수는 코드 수행 내용이 한 줄인 함수에 유용하며
// 고차 함수의 인자(콜백 함수)로 많이 활용됨
console.log(
[1, 2, 3, 4, 5].map(function(val) {return val * 10})
);
console.log(
[1, 2, 3, 4, 5].map(val => val * 10)
);

- 화살표 함수의 특징
// 1. 화살표 함수는 this를 가지지 않는다.
var theater = {
store: '영등포점',
titles: ['어쩔수가없다', '극장판 체인소 맨', '극장판 귀멸의 칼날', '얼굴', 'F1 더 무비'],
showMovieList() {
this.titles.forEach(
title => console.log(this.store + ":" + title)
// function(title) {
// console.log(this.store + ":" + title);
// }
);
}
};
theater.showMovieList();
// 2. 화살표 함수는 new와 함께 호출할 수 없다.
// 3. 화살표 함수는 super를 가지지 않는다.
// 4. 화살표 함수는 arguments를 지원하지 않는다.
(function() {
// var arrowFunc = function() {
// console.log(arguments);
// }
var arrowFunc = () => console.log(arguments);
arrowFunc(3, 4);
}(1, 2));

- 순수 함수 & 비순수 함수
/*
- 순수 함수: 외부 상태에 의존하지도 않고 외부 상태를 변경하지도 않는 함수
- 비순수 함수: 외부 상태에 의존하거나 외부 상태를 변경하는 함수
*/
var cnt = 0;
// 순수 함수
function increase(n) {
return ++n;
}
increase(cnt);
console.log(cnt); // 0
cnt = increase(cnt);
console.log(cnt); // 1
// 비순수 함수
function decrease() {
return --cnt;
}
decrease();
console.log(cnt); // 0
cnt = decrease(); // 재할당이 불필요 (함수 호출만 해도 같은 결과)
console.log(cnt); // -1
- 일급 객체
/*
1. 무명의 리터럴로 생성할 수 있다.
2. 변수나 자료구조(객체, 배열 등)에 저장할 수 있다.
3. 함수의 매개변수로 전달할 수 있다.
4. 함수의 반환 값으로 사용할 수 있다.
*/
function repeat(func, count) {
for(var i = 0; i < count; i++) {
console.log(func());
}
return function() {
console.log(`${count}번 반복 완료! 명심하셨으리라 생각합니다 ^_^!`)
}
}
var cheerup = function() {
return `JavaScript 열심히 공부해야 되겠죠 ^^?`;
};
var returnFunc = repeat(cheerup, 10);
returnFunc();
scope
- 함수 레벨 스코프
/*
var 키워드로 선언된 변수는 오로지 함수의 코드 블록만을
지역 스코프로 인정하는 함수 레벨 스코프를 가진다.
*/
var i = 0;
for(var i = 0; i < 10; i++) {
console.log(`${i}번째 실행중~~~`);
}
console.log(i); // 10
- var
// 1. 변수 중복 선언 허용
var msg = "열심히 공부해 봅시다!";
console.log(msg);
var msg = "곧 최종 프로젝트니까요!";
console.log(msg);
// 초기화문이 없는 변수 선언문은 중복 선언하면 무시됨
var msg;
console.log(msg); // 곧 최종 프로젝트니까요!
// 2. 함수 레벨 스코프 (함수 코드 블록만 지역 스코프 인정)
// 3. 변수 호이스팅
console.log(test); // undefined
test = "테스트 출력";
console.log(test); // 테스트 출력
var test;
- let
// 1. 변수 중복 선언 금지
// let, const 키워드로 선언된 변수는 동일 스코프 내 중복 선언 불가
// 단, let 키워드를 사용하면 재할당은 가능
let msg = 'JavaScript 공부는 참 즐거워요 ^_^*';
console.log(msg);
// let msg = '어라 빨간 줄이 뜨죠...?';
msg = '열심히 공부할 맛이 납니다!';
console.log(msg);
// 2. 블럭 레벨 스코프
let i = 0;
for(let i = 0; i < 10; i++) {
console.log(`${i}번째 실행중~~~`);
}
console.log(i); // 0
// 3. 변수 호이스팅
// let 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 동작
// 선언은 되었지만 초기화가 되지 않아 참조 시 오류가 발생하는 것
console.log(test);
// let test; // ReferenceError: Cannot access 'test' before initialization
- const
/*
- const 키워드는 상수(constant) 선언을 위해 사용
- let 키워드와 마찬가지로 블럭 레벨 스코프를 가짐
- let 키워드와 마찬가지로 변수 호이스팅이 발생하지 않는 것처럼 동작
(* 상수 == 재할당이 금지된 변수)
*/
// 1. 선언과 동시에 초기화해야 함
const TEST = 1;
// 2. const 키워드로 선언한 변수는 재할당 금지
// TEST = 100; // TypeError: Assignment to constant variable.
console.log(TEST); // 1
// const 키워드로 선언한 변수에 '객체'를 할당한 경우
// property 값은 변경 가능 (단, 마찬가지로 재할당은 불가)
const STUDENT = {
name: "SKN 17기",
count: 28
}
STUDENT.name = "최종 프로젝트 때 최고의 결과를 보여줄 17기 ^^";
console.log(STUDENT);
STUDENT['studyTime'] = 960;
console.log(STUDENT); // { name: '최종 프로젝트 때 최고의 결과를 보여줄 17기 ^^', count: 28, studyTime: 960 }
// STUDENT = {}; // TypeError: Assignment to constant variable.
Object constructor
- Object 생성자 함수
const teacher = new Object();
teacher.name = '맹구';
teacher.height = 199;
console.log(teacher); // { name: '맹구', height: 199 }
- 생성자 함수 vs 일반 함수
function Student(name, hobby) {
this.name = name;
this.hobby = hobby;
this.getInfo = function() {
return `${this.name}의 취미는 ${this.hobby}입니다.`;
};
}
// new 연산자와 함께 호출해야 함
// - new 연산자와 함꼐 호출해야 생성자 함수로써 동작
// - 그렇지 않으면 일반 함수로 동작
const student = Student('맹구', '야구보기');
console.log(student);
console.log(hobby);
const newStudent = new Student('짱구', '놀기');
console.log(newStudent);
console.log(hobby);
// new.target (ES6)
// - new 연산자와 함께 생성자 함수로써 호출 시, 함수 자기 자신
// - new 연산자 없이 일반 함수로써 호출 시, undefined
function Dog(name, skill) {
console.log(new.target);
if(!new.target) {
return new Dog(name, skill);
}
this.name = name;
this.skill = skill;
}
const dog = Dog('뽀삐', '손!');
console.log(dog);
const newDog = new Dog('삐뽀', '빵!');
console.log(newDog);
// 내적 생성자 함수는 new 연산자 없이 사용해도 빈 객체를 반환하는 방식으로
// 잘 동작하게 만들어짐
const obj = Object();
console.log(obj);
strict mode
- 엄격 모드 (strict mode)
/*
전역 선두 또는 함수의 선두에 'use strict';를 작성해 사용
(즉시 실행 함수 스크립트 단위로 적용하는 것이 바람직함)
*/
// 'use strict';
function test() {
'use strict';
x = 10;
}
test();
console.log(x); // ReferenceError: x is not defined
- strict mode 활용
// 1. 암묵적 전역 방지
(function(){
// 'use strict';
x = 1;
}());
console.log(x);
// 2. 매개변수 이름 중복 방지
(function(){
// 'use strict';
function test(x, x) {
return x + x;
}
console.log(test(1, 2));
}());
// 3. 변수, 함수, 매개변수의 삭제 방지 (delete 키워드 사용 에러)
(function(){
// 'use strict';
var y = 1;
delete y;
console.log(y);
}());
// 4. with문 사용 방지
(function(){
// 'use strict';
with({ z : 1 }) {
console.log(z);
}
}());
// 5. 일반 함수에서의 this 사용 제한
// - 일반 함수로서 호출한 함수의 this == 전역 객체
// - strict mode에서 일반 함수로서 호출한 함수의 this == undefined
(function(){
'use strict';
function testThis() {
console.log(this);
}
testThis(); // undefined
new testThis(); // testThis {}
}());
// 6. arguments 객체
// strict mode에서는 매개변수에 전달된 인수를 재할당해 변경해도
// arguments 객체에는 반영되지 않음
(function(arg){
'use strict';
arg = 1;
console.log(arg); // 1
console.log(arguments); // [Arguments] { '0': 777 }
}(777));
array
- 배열
// 1. 배열 리터럴
const arr = ['다람쥐', '토끼', '호랑이'];
console.log(arr);
// 2. 배열 생성자 함수
const arr2 = new Array();
console.log(arr2); // []
const arr2_1 = new Array(10); // 10칸짜리 배열 (length 프로퍼티 지정)
const arr2_2 = new Array(10, 20, 30); // 인자를 요소로 가지는 배열
const arr2_3 = new Array('javascript'); // 안저룰 요소로 가지는 배열
console.log(arr2_1); // [ <10 empty items> ]
console.log(arr2_2);
console.log(arr2_3);
// 3. Array.of() 메서드
const arr3_1 = Array.of(10);
const arr3_2 = Array.of(10, 20, 30);
const arr3_3 = Array.of('javascript');
console.log(arr3_1); // [ 10 ]
console.log(arr3_2);
console.log(arr3_3);
// 배열 == object
console.log(typeof arr);
/*
[ 프로퍼티 플래그 ]
객체 프로퍼티는 값(value)과 함께 플래그(flag)라는 특별한 속성 세 가지를 가짐
- writable: 수정 가능 여부 (true: 값 수정 가능 / false: 읽기만 가능)
- enumerable: 반복문을 사용해 나열 가능한지 여부
- configurable: 프로퍼티 삭제 및 플래그 수정 가능 여부
*/
console.log(Object.getOwnPropertyDescriptors(arr));
- array property: length
const arr = [1, 2, 3, 4, 5];
console.log(arr.length); // 5
arr.push(6);
console.log(arr.length); // 6
arr.pop();
console.log(arr.length); // 5
// length를 기존 길이보다 작게 조정하면 배열 요소도 조정됨
console.log(arr); // [ 1, 2, 3, 4, 5 ]
arr.length = 3;
console.log(arr); // [ 1, 2, 3 ]
// length를 기존 길이보다 늘리면 빈 공간이 추가됨
arr.length = 7;
console.log(arr); // [ 1, 2, 3, <4 empty items> ]
// JS는 배열 요소 일부가 비어있는 배열을 문법적으로 인정함
// 문법적으로 인정 == length로 요소 개수를 셀 때도 카운트
// 단, 요소가 존재하는 것은 아니므로 property에는 없음
const arr2 = [1, , , , 100];;
console.log(arr2); // [ 1, <3 empty items>, 100 ]
console.log(arr2.length); // 5
console.log(Object.getOwnPropertyDescriptors(arr2));
- JS 배열의 메서드
// indexOf, lastIndexOf, includes
const yongdonList = ['할머니', '할아버지', '큰삼촌', '할아버지', '작은숙모', '외삼촌', '할아버지'];
console.log('===== indexOf =====');
console.log(yongdonList.indexOf('할아버지')); // 1
console.log(yongdonList.indexOf('할아버지', 2)); // 3
console.log(yongdonList.lastIndexOf('할아버지')); // 6
console.log(yongdonList.includes('할머니')); // true
// push, pop
console.log('===== push & pop =====');
console.log(yongdonList.push('엄마'), yongdonList);
console.log(yongdonList.push('아빠'), yongdonList);
console.log(yongdonList.pop(), yongdonList);
console.log(yongdonList.pop(), yongdonList);
console.log(yongdonList.pop(), yongdonList);
console.log(yongdonList.pop(), yongdonList);
console.log(yongdonList.pop(), yongdonList); // 작은숙모 [ '할머니', '할아버지', '큰삼촌', '할아버지' ]
// shift, unshift
const chikenList = ['후라이드치킨', '양념치킨', '간장치킨'];
console.log('===== shift & unshift');
console.log('원래 치킨:', chikenList);
chikenList.unshift('파닭');
chikenList.unshift('마늘치킨');
chikenList.unshift('스노윙치킨', '불닭');
console.log('unshift 후:', chikenList); // unshift 후: [ '스노윙치킨', '불닭', '마늘치킨', '파닭', '후라이드치킨', '양념치킨', '간장치킨' ]
console.log(chikenList.shift(), chikenList);
console.log(chikenList.shift(), chikenList);
console.log(chikenList.shift(), chikenList);
console.log(chikenList.shift(), chikenList);
console.log(chikenList.shift(), chikenList); // 후라이드치킨 [ '양념치킨', '간장치킨' ]
// concat
// arr1.concat(arr2, ...);
// slice, splice
const frontEnd = ['HTML', 'CSS', 'JavaScript', 'ES6'];
console.log('===== slice & splice =====');
console.log(frontEnd.slice(1, 3)); // [ 'CSS', 'JavaScript' ]
console.log(frontEnd); // [ 'HTML', 'CSS', 'JavaScript', 'ES6' ]
console.log(frontEnd.splice(3, 1, '자바스크립트')); // [ 'ES6' ]
console.log(frontEnd); // [ 'HTML', 'CSS', 'JavaScript', '자바스크립트' ]
// join
// 배열을 구분자로 결합하여 문자열로 반환
console.log(frontEnd.join('---')); // HTML---CSS---JavaScript---자바스크립트
// reverse
// 배열의 순서를 뒤집음
console.log(frontEnd.reverse()); // [ '자바스크립트', 'JavaScript', 'CSS', 'HTML' ]
- iterable & array-like
/*
iterable: Symbol.iterator 메서드가 구현된 객체
array-like(유사배열): 인덱스와 length 프로퍼티가 있어 배열처럼 보이는 객체
- 이터러블이면서 유사배열일 수 있고
- 이터러블 객체라고 해서 유사배열 객체는 아니며
- 유사배열 객체라고 해서 이터러블 객체인 것도 아니다.
*/
// 유사배열 객체
let arrayLike = {
0: '배열인듯',
1: '배열아닌',
2: '배열같은',
3: '유사배열',
length: 4
};
// console.log(arrayLike.pop());
// 이터러블 객체 (Symbol.iterator 구현)
let range = {
from: 1,
to: 5
};
range[Symbol.iterator] = function() {
return {
current: this.from,
last: this.to,
next() {
if(this.current <= this.last) {
return {done: false, value: this.current++};
} else {
return {done: true};
}
}
};
};
console.log(range);
for(let item of range) {
console.log(item);
}
// console.log(range.pop());
/*
이터러블이나 유사배열을 Array.from()의 인자로 넘겨주면
새로운 배열을 만들고 객체의 모든 요소를 새롭게 만든 배열에 복사한다.
*/
let arrLikeArr = Array.from(arrayLike);
console.log(arrLikeArr.pop());
let iterArr = Array.from(range);
console.log(iterArr.pop());
// 배열로 생성하기 전 적용할 함수 매핑 가능
iterArr = Array.from(range, num => num * num);
console.log(iterArr);
'AI 활용 애플리케이션 개발 > 화면 구현' 카테고리의 다른 글
| 3.4.5 [화면 구현] JavaScript: DOM (1) | 2025.10.14 |
|---|---|
| 3.4.4 [화면 구현] JavaScript: ES6 (0) | 2025.10.03 |