//array 예시
var memb = ['me', 'you', 'she'];
console.log(memb[1]); // you
//object 예시
var roles = {
'programmer':'me',
'designer':'you',
'manager':'she'
}
console.log(roles.designer); // you
객체를 하나씩 꺼내서 반복문으로 처리하는 방법
var memb = ['me', 'you', 'she'];
var i = 0;
while( i <memb.length){
console.log(memb[i]);
i = i + 1;
}
다음과 같이 변수 i를 이용하여 index 값을 늘려가며 배열의 요소에 접근하였다.
하지만 object는 숫자를 식별자로 사용하지 않는다고 하였다.
var roles = {
'programmer':'me',
'designer':'you',
'manager':'she'
}
for(var name in roles) {
console.log(name);
}
다음과 같이
roles라는 object에 담겨있는 모든 식별자가 매 반복마다 차례대로 name에 담긴다.
따라서 코드의 output은
programmer
designer
manager
가 된다.
그렇다면 식별자가 아닌, 각 식별자에 해당하는 값을 출력하려면?
obect에서 식별자의 이름을 통해 값에 접근하는 식은 다음과 같다
roles[programmer]
이렇게 대괄호 내부에 식별자를 작성하여 값을 가져올 수 있기 때문에
위의 반복문은 다음과 같이 바꿔서 값을 출력하는 코드로 변경할 수 있다.
var roles = {
'programmer':'me',
'designer':'you',
'manager':'she'
}
for(var name in roles) {
console.log(roles[name]);
}
output :
me
you
she
js에서는 함수가 statement일 뿐만 아니라 값이 된다.
값이 된다는 것은 변수에 담길 수 있다는 뜻이다.
기존의 조건문, 반복문 등과 같은 다른 statement는 값이 될 수 없기 때문에 변수에 담아서 출력하면 에러가 발생한다.
var i = if(true){console.log(1);}
console.log(i);
그러나 함수의 경우엔 변수에 담아서 출력하면 오류가 발생하지 않는다.
var f = function() {
console.log(1);
}
console.log(f);
output :
[Function: f]
그리고 보이는 바와 같이 함수 자체를 정의하는 과정에서는 이름을 붙이지 않아 익명함수로 구현하였지만, 함수를 값으로서 변수에 입력하는 순간부터 변수명이 함수의 이름 역할을 한다
f(); //1
함수는 값이기 때문에 변수에 담길 수 있는 것과 마찬가지로,
배열과 객체에도 사용될 수 있다.
var a = [f];
a[0](); //1
var o = {
func:f
}
o.func(); //1
배열에 함수가 담기는 경우는 드물지만, 객체에서는 익명함수에 이름을 식별자로서 붙여줄 수 있기 때문에 함수가 담기는 경우가 많다.
하나의 객체에는 관련된 여러 데이터를 묶어서 보관할 수 있다.
(예시)
v1과 v2 변수가 연관된 데이터라고 할 때 o라는 하나의 객체로 묶어준다
var o = {
v1:'v1',
v2:'v2'
v1, v2 변수와 관련된 f1, f2함수가 있다고 하자.
function f1() {
console.log(o.v1);
}
function f2() {
console.log(o.v2);
}
이 두가지 함수도 v1, v2 변수들과 함께 연관된 값으로서 취급될 수 있기 때문에, 하나의 obejct 내에 묶여 들어갈 수 있다.
var o = {
v1:'v1',
v2:'v2',
f1:function() {
console.log(o.v1);
},
f2:function() {
console.log(o.v2);
}
}
이렇게 변수와 함수를 모두 가지는 객체가 생성될 수 있다.
하지만 위의 코드에는 결함이 있는데,
객체 o 내부의 요소인 함수가 o.v1
, o.v2
처럼 o
라는 객체명을 사용하여 자신이 속한 객체를 불러오고 있다.
이때 객체 o의 이름이 변경된다면, 함수가 접근하고 있는 o
가 자동으로 바뀌지 않으면서 문제가 발생한다.
따라서 자신이 속한 객체의 이름을 사용해야할 땐, 이름 대신 다른 키워드를 사용하기로 한다.
this
var o = {
v1:'v1',
v2:'v2',
f1:function() {
console.log(this.v1);
},
f2:function() {
console.log(this.v2);
}
}
객체 지향을 그동안 작성했던 코드에 적용시켜보자
사용했던 함수 중
function templateHTML(title, list, body, control){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`;
}
function templateList(filelist){
var list = '<ul>';
var i = 0;
while(i < filelist.length){
list = list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i = i + 1;
}
list = list+'</ul>';
return list;
}
위의 두 함수는 모두 template을 만들기 위한 함수라는 공통점이 있다.
이렇게 같은 부류의 함수를 Object로 묶어주는 것이 바로 객체 지향 방식이라고 할 수 있다.
template
이라는 Object 내의 HTML
, list
라는 요소 함수var template = {
HTML:function(title, list, body, control){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`;
},list:function(filelist){
var list = '<ul>';
var i = 0;
while(i < filelist.length){
list = list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i = i + 1;
}
list = list+'</ul>';
return list;
}
}
templateList(filelist);
-> template.list(filelist);
templateHTML(...);
-> template.HTML(...);
//변경전
/*
var list = templateList(filelist);
var template = templateHTML(title, list,
`<h2>${title}</h2>${description}`,
`<a href="/create">create</a>`
);
response.writeHead(200);
response.end(template);
*/
//변경후
var list = template.list(filelist);
var html = template.HTML(title, list,
`<h2>${title}</h2>${description}`,
`<a href="/create">create</a>`
);
response.writeHead(200);
response.end(html);
💡 이렇게 동작방법은 동일하게 유지하면서 코드를 효율적으로 수정하는 것을 Refactoring이라고 한다. 굉장히 중요한 과정!