JavaScript 함수
1-1 클로저(Closure)
1-2 생성자 함수
Map, Set
this
3-1 bind
3-2 call
3-3 apply
JSON
let outer = function (){
let a = 1;
function inner (){
let b = 2;
let c = 3;
a = a + b + c;
console.log(a);
}
return inner
}
let newOuter = outer();
newOuter()
🕵️♀️클로저(Closure)란?
위 소스코드를 예제로 클로저를 다음과 같이 정의할 수 있다.
첫 번째, 폐쇠된 공간 안에서 데이터에 접근하기 위한 테크닉이다.
➡ outer 함수는 마지막 return inner로 역할을 다 하고 폐쇠된다.(메모리에서 사라진다.)
➡ 하지만, inner 함수에서 a 변수를 사용하고 있어 a 변수는 없어지지 않는다.(메모리에 존재한다.)
두 번째, 내부 함수의 외부 함수 접근 테크닉이다.
➡ inner 함수a = a+b+c
코드를 보면 변수 a는 inner 함수 밖 outer 함수에 정의되어 있다. 하지만 inner 함수는 자신에게 a 변수가 없는 것을 알고 밖에 있는 inner 함수의 a 변수를 참조하였다.
❓ 클로저 왜 사용할까?
함수 내에 코드는 휘발되고 필요한 부분만 참조하기 때문에 메모리 효율이 좋다. 또 위 소스코드에 변수 a를 함수 밖에서 참조할 수 없기 때문에 변수 은닉을 위해 사용합니다.
const x = 100; function a() { const x = 1; b(); } function b() { console.log(x); } a(); // 100 b(); // 100
✍ 위 소스코드에서 함수 a안에서 b를 호출했다. 결과적으로, 함수 a의 x 지역변수를 참조하지 않고 전역변수인 x를 참조한다.
클로저를 사용하기 위해서는 함수 내부에서 선언해야 한다. 호출된 위치는 상관 없다. 즉, b 함수가 전역으로 선언되어 있어 상위 스코프인 window(전역) 변수 x를 가지고 온다.
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("ayden");
console.log(user.name); // ayden
console.log(user.isAdmin); // false
🕵️♀️생성자 함수란?
유사한 객체를 여러 개 만들어야 할 때 'new' 연산자와 생성자 함수를 사용하면 유사한 객체 여러 개를 쉽게 만들 수 있다. 생성자 함수는 유사한 객체를 만들 때 토대가 되는 함수라고 생각하면 된다.
일반 함수와 기술적인 차이는 없고, 함수 이름의 첫 글자는 대문자로 시작하는 것과 함수명 앞에 'new' 연산자를 붙여 실행하는 차이가 있다.
function Z(){ console.log("1"); } let a = new Z(); let b = new Z(); console.log(a===b); // false
✍ Z 함수를 생성자로 만들어진 a, b 인스턴스는 서로 다르다. 생성자는 같으나, 인스턴스끼리는 메모리 주소 값이 다르다.
let user = new Map();
user.set('name', 'ayden');
console.log(user.get('name')); // ayden
console.log(user.has('name')); // true
console.log(user.size); // 1
console.log(user.keys()); // {"name"}
console.log(user.values()); // {"ayden"}
console.log(user.entries()); // {"name" => "ayden"}
🕵️♀️Map이란?
Map 객체는 key-value 쌍을 가지는 객체 자료형의 한 종류이다.
set
은 key와 value 생성.
get
은 생성된 key를 가지고 value 확인.
has
는 생성된 key가 map에 존재하는지 true or false로 반환.
size
는 map에 있는 key 개수 확인.
keys
는 map에 있는 key들을 반환.
values
는 map에 있는 value들을 반환.
entries
는 map에 있는 key와 value 쌍을 반환.
✍ Object와 Map
둘 다 key와 value를 가지는 자료형이다.
- Object의 key는 문자열 타입으로만 지정해야하지만, Map의 key는 모든 값을 가질 수 있다.
- Object는 크기를 사용자가 직접 수동으로 알아내야 하지만, Map은 size를 통해 크기를 쉽게 얻을 수 있다.
- Map은 key 추가, 삭제가 빈번하거나 데이터 크기가 클 때 사용한다.
let a = new Set('abc'); // {'a', 'b', 'c'}
let b = new Set('cde'); // {'c', 'd', 'e'}
a.add('h'); // {'a', 'b', 'c', 'h'}
// 교집합
let cro = [...a].filter(value => b.has(value)) // ['c']
// 합집합
let union = new Set([...a].concat(...b)) // ['a', 'b', 'c', 'h', 'd', 'e']
// 차집합
let dif = new Set([...a].filter(x => !b.has(x))); // ['a', 'b', 'h']
let c = nwe Set('aaaabbbbcccdddddeee') // {'a', 'b', 'c', 'd', 'e'}
🕵️♀️Set이란?
Set은 모든 타입의 값을 저장하는 객체자료형의 한 종류이다.
이때 객체 안의 값은 중복을 허용하지 않는다.
✍ 배열 담긴 값들도 중복을 제거한다.
let a = {
point: 100,
func: function () {
console.log(this);
}
}
a.func(); // {"point":100, "func": F} a 객체
let user = {
name: "ayden",
age: 30,
greet() {
console.log(this.name);
}
};
user.greet(); // ayden
this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 예약어이다. 즉, this는 자신을 호출한 객체, 자신이 생성할 객체이다. 이러한 특성으로 함수를 다른 객체에서 재사용이 가능하다.
✍this는 함수가 만들어질 때가 아닌 '실행'될 때 그 값이 결정된다.
화살표 함수에서의 this는 상위 스코프의 객체를 가르킨다.
function sayName(){
console.log(this.name);
}
var bruce = {
name: 'bruce',
sayName : sayName
}
var peter = {
name : 'peter',
sayName : sayName.bind(bruce)
}
peter.sayName(); // bruce
bruce.sayName(); // bruce
bind()
는 this가 고정된 새로운 함수를 반환한다. 즉, this에 할당되는 객체가 고정된 새로운 함수를 생성한다.
위 소스코드에서peter.sayName()
와bruce.sayName()
는 모두 bruce 를 출력한다.
bruce.sayName()
은this.name
이기 때문에 this == bruce 객체로 작용되어 bruce가 출력된다.
peter.sayName()
은sayName.bind(bruce)
로 bruce 객체가 sayName 함수에 바인드되었다. 따라서, peter 객체에 sayName 함수 this는 peter가 아니라 bruce 객체이다.
✍ this만 사용하면 상황에 따라 this가 변경되게 된다. 하지만 bind를 사용하면 this는 내가 정한 object로 고정된다.
function menu(item){
console.log("오늘 저녁은 " + item + this.name)
}
let myDiner = {
name: "김치찌개"
}
let yourDiner = {
name: "된장찌개"
}
menu.call(myDiner, "칼칼한 ") // 오늘 저녁은 칼칼한 김치찌개
call()
은 this의 값을 바꿀수 있고 함수를 실행할 때 사용할 인수도 전달할 수 있다.menu.call()
이 아닌,menu()
로 실행했다면this.name
의 결과는window.name
과 같다.
function menu(item1, item2){
[item1, item2].forEach(el=>{
console.log("오늘 저녁은 " + el + this.name)
})
}
let myDiner = {
name: "김치찌개"
}
let yourDiner = {
name: "된장찌개"
}
menu.apply(myDiner, ["칼칼한 ", "밍밍한 "])
// 오늘 저녁은 칼칼한 김치찌개
// 오늘 저녁은 밍밍한 김치찌개
apply()
는 함수를 실행할 때 인수를 배열로 묶어 한 번에 전달한다.
apply
와call
은 인수를 배열로 전달하는 것 빼고는 동일한 역할을 수행한다.
🕵️♀️JSON이란?
배열 안에 객체가 담겨 있는 파일의 형태로 필요한 데이터가 담겨있는 파일 포맷이다. 다른 형태의 데이터 파일 형식으로는 .CSV 와 .XML 이 있다.
- JSON.parse(): JSON문자열을 자바스크립트 객체로 변환.
- JSON.stringify() : 자바스크립트 객체를 JSON문자열로 변환.