Closures


Closures는 자바스크립트가 제공하는 막강한 추상 개념이다. 하지만 동시에 혼란스럽기도 하다. 직역하면, 폐포(닫힌 주머니)를 의미한다.



1
2
3
4
5
function makeAdder(a) {
    return function(b) {
        return a+b;    
    }
}
cs


x = makeAdder(5);

x(6)


-> 11



makeAdder 함수는 한 매개변수를 통해 호출되고, 주어진 매개변수를 더하는 새 익명함수를 생성한다.


또 다른 외부 함수 혹은 호출자가 외부 함수의 변수에 액세스한 다는 점에서 내장함수가 수행하는 일과 비슷하다고 볼 수 있다.


한가지 다른점은 외부 함수가 리턴된다는 점인데, 일반적으로 생각할 때 변수는 사라진다고 볼 수 있으나 여전히 존재하고 있다.


또한, 자바스크립트의 함수가 실행될 때는 언제나, 스코프 객체가 생성되어 해당 함수내에 생성된 지역변수를 저장하고 있다.


함수 매개변수로서 넘어온 어떤 값이라도 초기값으로 저장하고 있다. 이것은 전역변수 및 전역 객체와 비슷하지만, 2가지 차이점이 있다.


1) 함수가 실행될 때마다 새로운 스코프 객체가 생성된다.

2) 전역 객체와 달리 스코프 객체는 자바스크립트 코드에서 직접 접근 불가능하다.


따라서 makeAdder 함수가 호출되면, 스코프 객체는 makeAdder 함수에 매개변수로 넘겨진 하나의 속성 값 a를 갖는 상태로 생성된다.


일반적으로 자바스크립트의 가비지 컬렉터가 makeAdder에 의해 생성된 범위 객체를 제거해야하지만, 리턴된 함수가 여전히 스코프 객체를 참조한다.


결과적으로 스코프 객체는 makeAdder에 의해 리턴된 함수가 더는 참조되지 않을 때까지 가비지컬렉터는 삭제하지 않는다.


또한 Closures는 상태를 저장하도록 허용한다. 그렇기 때문에 객체 내부에서 자주 사용될 수 있는 것이다.



즉 Closures는 함수와 함수에 의해 생성되는 범위 객체를 함께 지칭하는 용어이다.








메모리 누출


자바스크립트는 객체가 생성됨에 따라 메모리를 할당하고, 더 참조하는 다른 객체가 없으면 메모리에서 제거하는 등 가비지컬렉트를 하는 언어이다.  


이에 따라, Closures의 부작용은 IE에서 심각하지는 않지만 메모리 누출이 쉽게 된다는 것이다. 


브라우저 호스트는 HTML 페이지의 DOM 객체로 표현된 많은 수의 객체를 다루어야 한다. 


객체들을 어떻게 할당하고 거둬들이는 지는 브라우저의 책임이다. IE는 자신만의 고유한, 자바스크립트와는 다른 가비지 컬렉션 방식을 사용한다. 


IE에서 메모리 누출은 자바스크립트 객체와 고유 객체간의 참조하는 중 자기 자신을 참조(circular reference : 순환 참조)하게 되는 일이 발생할 경우라면 언제든지 발생하게 된다.



1
2
3
4
5
6
7
function leakMemory(){
 
    var el = document.getElementById('el');
    var o = {'el' : el };
    el.o = o;
 
}
cs




위의 코드는 순한 참조로서 메모리 누출을 일으킨다. IE는 완전히 다시 시작하기 전까지 el과 O에 의해 사용되는 메모리를 반환하지 못한다.


일반적으로 메모리 누출이 이렇게 명확한 경우는 드물다. 누출을 일으키는 데이터 구조는 수차례에 거친 참조 구조를 가지고 있어 순환참조를 하고 있는지 명확하지 않기 때문이다.


Closures는 위와 같은 경우가 아니더라도 간단하게 메모리 누출이 일어날 수 있다.



1
2
3
4
5
6
7
function addHandler(){
 
    var el = document.getElementById('el');
    el.onclick = function(){
        this.style.backgroundColor = 'red';
    }
}
cs



위의 코드는 클릭했을 때 배경색이 바뀌는 엘리먼트를 설정한다. 그리고 메모리 누출 또한 일어난다.


el을 참조하면 의도와 달리 익명함수 때문에, 생성된 Closures 내에 객체가 붙잡혀 있기 때문이다.


이는 자바스크립트 객체(내부 함수)와 원시 객체(el) 간의 순환 참조를 만든다.



다음과 같은 방법을 통해 이 문제를 피할 수 있다.



1
2
3
4
5
6
7
function addHandler(){
 
    var el = document.getElementById('el');
    el.onclick = function(){
        this.style.backgroundColor = 'red';
    }
el = null;
}

cs





혹은 다음과 같은 방법으로 메모리 누출을 피할 수 있다.



1
2
3
4
5
6
7
8
9
10
function addHandler(){
    var clickHandler = function(){
        this.style.backgroundColor = 'red';
    }
 
    (function(){
    var el = document.getElementById('el');
    el.onclick = clickHandler;
    })();
}
cs


클로져에 의해 발생된 순환 참조를 끈기 위해 또 다른 클로져를 추가 했다.

내부함수는 실행되고 바로 사라지므로 clickHandler와 함께 생성된 Closure로 부터 내용을 숨긴다.





'programming > JavaScript' 카테고리의 다른 글

사용자 정의 객체, 프로토타입, call, apply  (0) 2018.05.27
배열, 함수  (0) 2018.05.26
객체 (Object)  (0) 2018.05.26
데이터 타입, 변수, 연산자  (0) 2018.05.26

사용자 정의 객체


(1) 기존 방법


1
2
3
4
5
6
7
8
9
10
function makePerson(first, last){
    return {
        first : first,
        last : last    
    }
}
 
function personFullName(person){
    return person.first + ' ' + person.last;
}
cs



> master = makePerson("susan" , "wilson");

> persnFullName (master);


: sunsan wilson


-> 작동은 하지만 어설픈 방법이다. 전역 공간에 관련 함수가 많이 생성되기 때문. 가장 중요한 것은 객체에 함수를 붙여 놓는 것이다.




(2) 객체에 함수 추가


1
2
3
4
5
6
7
8
9
10
function Person(first, last) {
 
    return {
        first : first,
        last : last,
        fullName : function(){
            return this.first + ' ' + this.last;    
        }
    }
}
cs


> master = Person("susan" , "wilson");

> master.fullName()


: sunsan wilson



-> 여기서 this 는 함수 안쪽에 사용되어 현재 객체를 참조한다. 실제 의미하는 바는, 함수를 지정하는 것


> fullName() 


: undefined


-> 그냥 fullName 메소드를 호출하면, this는 전역에 속해 있기 때문에 undefined를 할당한다.




(3) 전역 함수 추가


1
2
3
4
5
6
7
8
9
10
11
12
13
14
function personFullName(){
    return this.first + ' ' + this.last;
}
 
 
function Person(first, last) { 
    return {
        this.first : first,
        this.last : last,
        fullName : function(){
            return this.first + ' ' + this.last;    
        }
    }
}
cs


> master = new Person("susan" , "wilson");


: new라는 키워드가 새로 추가 되었다. new는 this와 연관이 깊다. 새로운 빈 객체를 만든 다음 지정된 함수를 불러 새로운 객체를 this에 설정한다.

 'new'에 의해 불려지도록 디자인 된 함수를 construct 함수라 일컫는다. 



-> 점차 코드가 개선되고 있지만, 안에 있는 fullName에 정의된 함수를 전역에 있는 함수와 공유하는 것이 좀 더 좋은 방법일 것이다.




(4) 전역 함수와 공유


1
2
3
4
5
6
7
8
9
10
11
12
13
function personFullName(){
    return this.first + ' ' + this.last;
}
 
 
function Person(first, last) { 
    return {
        this.first : first,
        this.last : last,
        fullName : personFullName;
        }
    }
}
cs



-> 프로토타입을 추가하여 조금 더 개선이 가능하다. 프로토타입은 인스턴스된 모든 객체에서 공유할 수 있는 객체이다. 

    이것은 찾아보기 체인 (prototype chain 이라 일컫는)의 한 부분을 이룬다. 

    즉, person 객체에 설정되지 않은 속성에 접근을 시도할 때마다 javascript는 prototype에 대신 존재하는 속성이 있는지 없는지 찾아본다.




(5) 프로토타입 설정 


1
2
3
4
5
6
7
8
9
10
11
12
13
Person.Prototype.fullName = function(){
    return this.first + ' ' + this.last;
}
 
 
function Person(first, last) { 
    return {
        this.first : first,
        this.last : last,
        fullName : personFullName;
        }
    }
}
cs



프로토타입은 Javascript의 가장 강력한 도구 중에 하나이다. 프로토 타입을 통해 언제든지 객체의 속성 및 메소드를 추가 할 수 있다는 뜻이된다.





(6) 프로토타입을 통해 기존 객체에 없던 메소드 추가


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Person.Prototype.firstName = function(){
    return this.first;
}
 
Person.Prototype.fullName = function(){
    return this.first + ' ' + this.last;
}
 
 
function Person(first, last) { 
    return {
        this.first : first,
        this.last : last,
        fullName : personFullName;
        }
    }
}
cs



firstName 이라는 property는 Person 객체에 없지만, 프로토타입을 통해 설정할 수 있다.


정의한 객체 이외에 기존 객체에도 prototype을 정의 할 수 있다.





(6) 프로토타입을 통해 Javascript 내부에 정의된 객체에 메소드 추가


1
2
3
4
5
6
7
8
9
String.prototype.checkNum = function(){    
    var str = "";
    
    if(!isNaN(parseInt(str))){
        return true;
    }else{
        return false;
    }
}
cs






(6) Call , Apply 함수


1
2
3
4
function add(x,y){
    var total = x + y;
    return total;    
}
cs


> add.call(null, 2,3,4) ;

 : 5     

> add.apply(null,[2,3,4]);

 : 5


apply를 통해 배열을 인자 값으로 넘길 수 있다. apply와 call의 첫 번째 인자값에 해당하는 null은 역할은?

 : this, 즉 자기 자신을 지칭한다.






(6) Call, Apply의 첫번 째 인자 값의 활용


1
2
3
4
5
6
7
8
9
var writer = {
  message: 'HI',
  write: function() {
    alert(this.message);
  }
};
var writer2 = {
  message: 'HELLO'
};
cs


writer 객체에는 write라는 property가 있고, 함수를 대입했다.


writer.write();                    // HI

writer.write.call(writer2);     //HELLO

'programming > JavaScript' 카테고리의 다른 글

클로져 (Closures), 메모리 누출  (0) 2018.06.09
배열, 함수  (0) 2018.05.26
객체 (Object)  (0) 2018.05.26
데이터 타입, 변수, 연산자  (0) 2018.05.26

배열


배열은 실제로 객체의 특별한 타입이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var a = new Array();
a[0= "dog";
a[1= "cat";
a[2= "tiger";
 
a. length
 
 
 
 
var a = ["dog""cat""tiger"];
a[100] = "fox";
a.length
 
cs


>3

> 101


- 2번 째 같은 경우 3번 째부터 100번 째까지는 undefined로 할당 된다.





함수


: javascipt의 핵심 컴포넌트이다.

: javascript의 함수는 강력하다. 객체 일수도 있으며, 함수일 수도 있다.



1
2
3
4
function add(x,y){
    var total = x + y;
    return total;    
}
cs


-> return 이 없다면, undefined를 얻을 수 있을 것이다.



> add()

: NaN        // undefined에 대해 덧셈을 수행할 수 없다.


> add(2,3,4)

 : 5          // 마지막 값 4는 무시된다.






익명 함수



1
2
3
4
5
6
7
8
var avg = function() {
    var sum = 0;
 
    for(var i=0; j=arguments.length; i<j; i++ {
        sum+ = arguments[i];
    }
        return sum / arguments.length;
}
cs


'programming > JavaScript' 카테고리의 다른 글

클로져 (Closures), 메모리 누출  (0) 2018.06.09
사용자 정의 객체, 프로토타입, call, apply  (0) 2018.05.27
객체 (Object)  (0) 2018.05.26
데이터 타입, 변수, 연산자  (0) 2018.05.26

객체


Javascript에서 객체는 간단히 키(key)-값(value) 쌍의 모임이다. 다른언어와 비교하면 다음과 같다.


- Python의 Dictionaries

- C와 C++의 Hash Table

- Java의 HashMap

- PHP의 Associative arrays




Javascript의 모든 것(코어타입을 제외한)은 객체로 취급되고, 기본적으로 검색하는데 매우 빠르기 때문에 유용하게 활용가능.


키(key)는 객체 포함 모든 값이 들어갈 수 있는 반면, 값(value)에는 문자열이 들어가야 한다.






빈 객체를 생성 하는 방법


(1) var obj = new Object(); 

(2) var obj = {};    


-> 두가지는 의미적으로 동치이다.






객체에 접근 하는 방법


(1) obj.name = "YYh"; 

    var name = obj.name;


(2) obj["name"] = "YYs";

     var name2 = obj["name"];


-> 마찬가지로 의미적으로 동치이다. 

2번 째 방법은 속성의 이름이 Runtime(실행시간)에 계산될 수 있는 문자열로 주어진다. 또한 예약어의 사용이 가능하다.



obj.for = "loop" ;         //  구문 오류, for문의 예약어 때문에

obj["for"] = "loop" ;     // 가능





객체에 엄밀 구문으로 초기화 하는 방법


1
2
3
4
5
6
7
8
9
var letter = {
    name : "tom",
    "for" : "jerry",
     details: {
         from : "seoul",
          to : "busan"
     }
    day : 24 
};
cs



- 속성에 연속적인 접근이 가능


 > letter.details.from 

 > letter["details"]["from"] 



























'programming > JavaScript' 카테고리의 다른 글

클로져 (Closures), 메모리 누출  (0) 2018.06.09
사용자 정의 객체, 프로토타입, call, apply  (0) 2018.05.27
배열, 함수  (0) 2018.05.26
데이터 타입, 변수, 연산자  (0) 2018.05.26


수 - Number


: 설계 명세서에 의하면 Javascript의 수는 "이중정밀도 64비트 형식  IEEE 754" 값으로 정의된다.

 Javascript에는 C 나 Java의 정수 타입이 없기 때문에 조심해야한다.


0.1 + 0.2 = 0.300000000000000000000004


- 내장 객체 Math를 통해 연산 가능

- 내장 parseInt() 함수를 사용하여 문자열을 정수로 변환 가능


ex) parseInt("100",10) = 100

     parseInt(100)  = 64   -> default는 8진수로 인식함

     

     parseInt("hello") = NaN 


    1 / 0  -> infinity     양의 값으로 무한대

   -1 / 0  -> -infinity   음의 값으로 무한대




문자열 - String


: Javascript의 문자열은 문자하나가 연결되어 만들어 진것. 즉 16비트로 표현된 유니코드 문자들이 길게 나열된 값


1) 길이 : "str".length

2) 추출 : "str".charAt(index)


.. 소문자변환(toLowerCase), 대문자 변환(toUpperCase) 등등..





정의되지 않음 - Undefined


: 어떤 값도 주어지지 않은(할당되지 않은) 변수 , Null과 구분




Null


: 값이 없음을 의미



NaN


: 수가 아님 ( Not - a - Number)





부울  -  Boolean


: true, false를 구분


- 특징이 있다면, false, 0, "" 빈문자, 수가 아님을 뜻하는 NaN 그리고 null, undefined 모두 false를 반환




변수


: 자바스크립트에서는 변수를 모두 var로 선언, 값을 할당하지 않으면 undefined




연산자 - Operator


: 자바스크립트에서는 변수를 모두 var로 선언, 값을 할당하지 않으면 undefined


 "3" + 4 + 5  

> 345


 3 + 4 + "5"

> 75



 1 == true 

>true


-> 타입이 강제 변환하지 않도록 하려면 삼중등호 연산자 사용해야함.


1 === true

> false








위 내용과 더불어 추가적으로 작성될 내용은 다음 페이지 참조 :  https://developer.mozilla.org/ko/docs/A_re-introduction_to_JavaScript






'programming > JavaScript' 카테고리의 다른 글

클로져 (Closures), 메모리 누출  (0) 2018.06.09
사용자 정의 객체, 프로토타입, call, apply  (0) 2018.05.27
배열, 함수  (0) 2018.05.26
객체 (Object)  (0) 2018.05.26

+ Recent posts