0. 라이프사이클

모든 리액트 컴포넌트에는 라이프사이클이 존재합니다. 말 그대로 생명주기입니다. 컴포넌트가 마운트 되기 전 후, 업데이트가 되는 시기, 또 언마운트된 시기 등 10가지의 메서드로 라이프사이클이 정의됩니다. 


1. 마운트 단계

:페이지에 컴포넌트가 나타남

1) constructor : 컴포넌트 클래스 생성자

2) getDerivedStateFromProps : State를 Prop와 동기화하는 단계에 불리는 메서드

3) render : 렌더링 단계에 불리는 메서드

4) componentDidMount : 마운트 후 불리는 메서드


2. 업데이트 단계

컴포넌트 정보를 업데이트 함(리렌더링)

5) getDerivedStateFromProps : State를 Prop와 동기화하는 단계에 불리는 메서드(마운트 단계 뿐 아니라 업데이트 단계에서도 호출됩니다)

6) shouldComponentUpdate : 컴포넌트 리렌더링 여부를 결정하는 메서드, false 리턴시 업데이트 하지 않습니다.

* 최적화를 위해서 중요한 메서드입니다. 리렌더링을 최소화 하기 위해서 잘 활용해야 합니다.

7) render : 리렌더링 단계에 불리는 메서드

8) getSnapshotBeforeUpdate: 컴포넌트 변화를 Virtual Dom에서 Dom으로 반영 직전 불리는 메서드

9) componentDidUpdate: 컴포넌트의 업데이트 후 불리는 메서드

업데이트는 props, state가 변경될 때, 부모 컴포넌트가 리렌더링될 때, forceUpdate가 호출 될 때 이렇게 4가지 경우에 호출됩니다.


3. 언마운트 단계

:페이지에서 컴포넌트가 사라짐

10) componentWillUnmount : 컴포넌트가 사라지기 직전에 불리는 메서드



'Web Front > React.js' 카테고리의 다른 글

[React] create-react-app으로 React App 만들기  (0) 2018.08.06

1. create-react-app 설치

먼저 글로벌에 create-react-app을 설치합니다.

yarn global add create-react-app


2. 프로젝트 생성

create-react-app project-name


놀랍게도 이렇게하면 React 프로젝트가 생성됩니다. 갓페이스북!! 참고로 create-react-app은 페이스북에서 제공해주는 것이랍니다.

위 명령어로 제가 한번 생성해보겠습니다.


react-todolist라는 프로젝트를 생성했습니다. 참고로 프로젝트 이름에 대문자는 사용할 수 없습니다.

생성한 프로젝트는 아래와 같은 폴더 구조를 갖습니다. 딱 필수로 필요한 것들만을 포함하고 있습니다.


Dependency를 보면 react, react-dom, react-scripts가 포함되어 있습니다.



3. 실행

yarn start


yarn start 명령어를 입력하니 아래와 같이 React 프로젝트가 실행되었습니다!


yarn 명령어는 아래와 같이 있습니다. 설치가 완료되면 저렇게 목록을 보여줍니다. 

그런데 마지막 happy hacking!?? 이건 뭘까요 ㅋㅋㅋ Happy hacking 키보드 사고싶다..


끝!!

'Web Front > React.js' 카테고리의 다른 글

[React] Component LifeCycle API정리  (0) 2018.08.07

0. 뷰 CLI

싱글 파일 컴포넌트 체계를 사용하기 위해서는 .vue 파일을 웹 브라우저가 인식할 수 있는 형태의 파일로 변환해 주는 W ebpack, Browserify와 같은 도구가 필요합니다.

Webpack은 웹 앱의 자원들을 자바스크립트 모듈로 변한해 하나로 묶어 웹 성능을 향상시켜 주고,  빌드 자동화 기능까지 포함한 강력한  자바스크립트 모듈 번들러이다. 비슷한 모듈 번들러로 Browserify가 있다.


그러나 Webpack을 이용해 직접 프로젝트를 구성하기에는 상당히 배워야할 것이 많습니다. 그래서 뷰 프레임워크에서는 개발자들이 편하게 프로젝트를 구성할 수 있도록 CLI(Command Line Interface)도구를 제공합니다. 이를 뷰 CLI라고 합니다.



1. 뷰 CLI 설치

bpack을 이용해 직접 프로젝트를 구성하기에는 상당히 배워야할 것이 많습니다. 그래서 뷰 프레임워크에서는 개발자들이 편하게 프로젝트를 구성할 수 있도록 CLI(Command Line Interface)도구를 제공합니다.

아래와 같이 명령어를 입력하여 간단하게 설치할 수 있습니다.



설치가 완료되면 아래와 같이 vue 명령어를 첬을 때 명령어로 인식되는 것을 볼 수 있습니다.



2. 뷰 CLI 명령어

뷰 CLI 명령어 중 가장 중요한 명령어는 vue init 입니다. vue init은 초기 프로젝트 구성을 도와줍니다. 그리고 아래와 같은 프로젝트 템플릿 구성이 있습니다.


  vue init webpack  : 고급 웹팩 기능을 활용한 프로젝트 구성 방식. 테스팅, 문법 검사 지원


  vue init webpack-simple : 웹팩 최소 기능을 활용한 프로젝트 구성 방식. 빠른 화면 프로토타이핑용


  vue init browserify  : 고급 브라우저리파이 기능을 활용한 프로젝트 구성 방식. 테스팅, 문법 검사등을 지원


  vue init browserify-simple : 브라우저파이 최소 기능을 활용한 프로젝트 구성 방식. 빠른 화면 프로토타이핑용


  vue init simple  : 최소 뷰 기능만 들어간 HTML 파일 1개 생성


  vue init pwa  : 웹팩 기반의 프로그레시브 웹 앱(PWA, Progressive Web App) 기능을 지원하는 뷰 프로젝트


이들 템플릿은 지원하는 기능이 다르지만 크게보면 전체적으로는 비슷합니다.

1. 웹팩이나 브라우저리파이 같은 모듈 번들러를 프로젝트 자체에 포함하여 바로 사용할 수 있다.

2. .vue 파일을 HTML, CSS, js파일로 변환해 주기 위한 뷰 로더(Vue Loader)를 포함하고 있다.

결론적으로 .vue 파일 방식으로 어플리케이션을 개발하려면 뷰 로더와 이를 지원하는 웹팩, 브라우저리파이 같은 모듈 번들러가 필요하다.


템플릿 중 웹팩이나 다른 기능에 신경 쓰지 않고 뷰 프레임워크 자체에 집중할 수 있는 템플릿은 webpack-simple 입니다. webpack 템플릿은 다양한 기능을 포함하고 있어서 파악하는데 시간이 소요됩니다.


3. 뷰 CLI로 프로젝트 생성하기


1. vue init 명령어로 프로젝트 생성하기


2. npm install을 입력하여 뷰 애플리케이션을 구동하기 위한 관련 라이브러리 다운로드하기.


아래는 설치까지 완료된 후 프로젝트의 폴더 구조입니다. 이 중 package.json 파일은 프로젝트 정보를 담고 있는 설정 파일임과 동시에 npm명령어 및 뷰로 애플리케이션을 제작하는 데 필요한 라이브러리 정보들을 포함하고 있습니다.


npm install을 입력하면 package.json의 라이브러리 목록이 모두 node_modules 폴더 밑에 설치가 됩니다.




3. npm run dev로 실행하기!


실행을 하면 마침내 아래와 같이 8080포트로 index.html이 열리게 됩니다!!







'Web Front > Vue.js' 카테고리의 다른 글

[Vue.js] 뷰 디렉티브(vue Directive)  (0) 2018.06.13

뷰 디렉티브(vue Directeve)

HTML 태그 안에 v- 접두사를 가지는 모든 속성이다.

디렉티브는 화면의 요소를 더 쉽게 조작할 수 있게 도와준다. 뷰의 데이터 값이 변경되었을 때 화면의 요소들이 리액티브하게 반응하여 변경된 데이터 값에 따라 갱신된다.


v-bind 는 아이디, 클래스, 스타일 등의 HTML속성 값에 뷰 데이터 값을 연결할 때 사용한다.

<p v-bind:class="test">v-bind 테스트</p>


v-if 는 지정한 뷰 데이터값의 참, 거짓 여부에 따라 해당 HTML 태그를 화면에 표시하거나 표시하지 않는다.


v-for  은 지정한 뷰 데이터의 개수만큼 해당 HTML 태그를 반복 출력한다.


v-show  v-if와 유사하게 데이터의 진위 여부에 따라 해당 HTML 태그를 화면에 표시하거나 표시하지 않는다. 다만 v-if는 해당 태그를 완전히 삭제하지만 v-show는 css효과만 display:none; 으로 준다.


v-on  은 화면 요소의 이벤트를 감지하여 처리할 때 사용한다. 예를 들어 v-on:click은 해당 태그의 클릭 이벤트를 감지하여 특정 메서드를 실행할 수 있다.


v-model  은 Form에서 주로 사용되는 속성으로 폼에 입력한 값을 뷰 인스턴스의 데이터와 즉시 동기화한다. 화면에 입력된 값을 저장하여 서버에 보내거나 watch와 같은 고급 속성을 이용하여 추가 로직을 수행할 수 있다. * <input>, <select>, <textarea> 태그에만 사용할 수 있다.



'Web Front > Vue.js' 카테고리의 다른 글

[Vue.js] 뷰 CLI 를 통한 프로젝트 생성  (0) 2018.06.14


인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.



함수형 프로그래밍은 프로그래밍의 여러 가지 패러다임 중 하나이다. 함수의 조합으로 작업을 수행하는 프로그래밍 방식이다. 중요한 것은 이 작업이 이루어 지는 동안 작업에 필요한 데이터와 상태는 변하지 않는다는 점이다. 변할 수 있는 건 오직 함수 뿐이다. 


자바스크립트에서의 함수형 프로그래밍은 다음과 같은 자바스크립트의 특징 때문에 가능하다.

- 일급 객체로서의 함수

- 클로저



1.Memoization Pattern


//Memoization이란 계산 결과를 저장해 놓아 이후 다시 계산할 필요 없이 사용할 수 있게 한다는 컴퓨팅 용어이다.
//말 그대로 함수의 키값에 결과를 저장해두고 이후 계산없이 사용할 수 있다.
//왠지 아래 함수보다는 input, func 값으로 key값을 만들어서 하면 이후 똑같은 호출 시 계산없이해서 좋을 거 같다.
//jQuery에서는 data()라는 메서드로 이 메모이제이션 패턴을 사용하였다.

function Calculate(key, input, func){
    Calculate.data = Calculate.data || {};
    if(!Calculate.data[key]){
        var result;
        result = func(input);
        Calculate.data[key] = result;
    }
    return Calculate.data[key];
}

var result;

result = Calculate(1,5,function(input){
    return input * input;
});
console.log(result);

result = Calculate(2, 5, function(input){
    return input * input /4;
});
console.log(result);

console.log(Calculate(1));
console.log(Calculate(2));



1) Memoization을 적용한 Factorial


//클로저를 활용한 앞서 실행한 factorial 값을 저장하는 factorial 함수
var factorial = function(){
    var cache = {'0':1};
    //연산을 수행하는 과정에서 캐시에 저장된 값이 있으면 곧바로 그 값을 반환한다.
    var factorial = function(n){
        var result = 0;
        if(typeof(cache[n]) === 'number'){
            result = cache[n];
        } else {
            result = cache[n] = n * factorial(n-1);
        }
        return result
    };

    return factorial;
}();

console.log(factorial(10));
console.log(factorial(12));



2) Memoization을 적용한 Fibonaci


//메모이제이션 기법을 적용한 피보나치 수열

var fibo = function(){
    var cache = {'0' : 0, '1': 1};

    var fibo = function(n){
        if(typeof(cache[n]) === 'number'){
            result = cache[n];
        } else {
            result = cache[n] = fibo(n-1) + fibo(n-2);
        }
        return result;
    }
    return fibo;
}();

console.log(fibo(10));


2.함수 적용

apply(), bind(), call() 함수는 함수형 프로그래밍에서 중요한 함수들이다.




3.Currying


커링이란 특정 함수에서 정의된 인자의 일부를 넣어 고정시키고, 나머지를 인자로 받는 새로운 함수를 만드는 것을 의미한다.

function calculate(a, b, c){
    return a*b+c;
}

function curry(func){
    var args = Array.prototype.slice.call(arguments, 1);

    return function(){
        return func.apply(null, args.concat(Array.prototype.slice.call(arguments)));
    }
}

var new_func1 = curry(calculate, 1);
console.log(new_func1(2,3)); //5 

var new_func2 = curry(calculate, 1, 2);
console.log(new_func2(3));//5

커링이란 특정 함수에서 정의된 인자의 일부를 넣어 고정시키고, 나머지를 인자로 받는 새로운 함수를 만드는 것을 의미한다.


bind() 함수가 커링과 매우 유사하다.


//bind() 함수는 고정시키고자 하는 인자를 함수 호출시 전달하고, 반환받은 함수를 호출하면서 나머지 가변 인자를 넣어줄 수 있다.

Function.prototype.bind = function(thisArg){
    var fn = this;
    slice = Array.prototype.slice;
    args = slice.call(arguments, 1);
    return function(){
        return fn.apply(thisArg, args.concat(slice.call(arguments)));
    };
}


4.wrapper


특정 함수를 자신의 함수로 덮어쓰는 것을 말한다. 물론 여기서 사용자는 원래 함수 기능을 잃어버리지 않은 상태로 자신의 로직을 수행할 수 있어야 한다.

기존 제공하는 함수에 기능을 추가하고 싶거나, 버그를 피하고자 할 때 많이 사용된다.


function wrap(object, method, wrapper){ var fn = object[method]; return object[method] = function(){ //original에서의 this와 익명함수 wrapper에서의 this가 다르므로 동일하게 만든다. return wrapper.apply(this, [fn.bind(this)].concat(Array.prototype.slice.call(arguments))); }; }

//original 함수가 있고, 이는 인자로 넘어온 값을 value에 할당하고 출력하는 기능을 한다. Function.prototype.original = function(value){ this.value = value; console.log("value : " + this.value); } //이를 사용자가 덮어쓰기 위해 wrap 함수를 호출하였다. 세 번째 인자로 넘긴 자신의 익명 함수를 original에 덮어쓰는 것이다. //여기서 사용자는 자신의 익명 함수의 첫 번째 인자로 원래 함수의 참조를 받을 수 있다. 이로 인해 원래 로직을 수행 할 수 있다. var mywrap = wrap(Function.prototype, "original", function(orig_func, value){ orig_func(value); console.log("wrapper value : " + this.value); }); var obj = new mywrap("song");



인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.



1.클래스, 생성자, 메서드


일반적으로 C++, Java와 같은 언어에서는 class라는 키워드를 제공하여 프로그래머가 클래스를 만들 수 있다.

그리고 클래스와 같은 이름의 메서드로 생성자를 구현한다. 그러나 자바스크립트에는 이러한 개념이 없다.(ES5에서는)

자바스크립트에서는 함수객체로 클래스, 생성자, 메서드도 구현 가능하다.



var Person = function(arg){
    this.name = arg;
};

Person.prototype.getName = function(){
    return this.name;
}

Person.prototype.setName = function(name){
    this.name = name;
}

var me = new Person("song");
console.log(me.getName());



2.상속


자바스크립트는 클래스를 기반으로 하는 전통적인 상속을 지원하지는 않는다.(ES5기준) 하지만 자바스크립트 특성 중 객체 프로토타입 체인을 이용하여 상속을 구현할 수 있다.


1) 클래스 개념 없이 객체의 프로토타입으로 상속 구현하기.

아래 예제는 더글라스 크락포드가 자바스크립트 객체를 상속하는 방법으로 소개한 코드이다.

var create_object = function(o){ function F() {} F.prototype = o; return new F(); };


생성된 F객체는 object o에 프로토타입 링크가 연결되어 있고, 

또, 이 object o는 Object prototype에 프로토타입 링크가 연결되어 있다.


그리고 프로토타입으로 상속을 구현하기에 중심이되는 또 다른 메서드가 있다. 

바로 extend() 메서드이다. 자바스크립트에서는 범용적으로 extend() 메서드로 자신이 원하는 객체 혹은 함수를 추가시킨다.

다음 코드는 jQuery 1.0의 extend 함수이다.


function extend(obj, prop){
    if(!prop){prop = obj; obj = this;}
    for(var i in prop) obj[i] = prop[i];
    return obj;
}


위와 같은 extend() 함수의 약점은 얕은 복사를 하고 있다는 것이다. 프로퍼티 중 객체가 있는 경우 깊은 복사를 하는 것이 일반적이다.



create_object(), extend() 메서드를 이용하여 상속을 하는 예제를 구현해 보자.

//클래스 개념 없이 프로토타입 특성으로만 상속 구현하기

//더글라스 크락포드가 자바스크립트 객체를 상속하는 방법으로 소개한 코드.
var create_object = function(o){
    function F() {}
    F.prototype = o;
    return new F();
};
//  _proto_          _proto_
//F ------> object o -------> Object.prototype

var person = {
    name : "song",
    getName : function(){
        return this.name;
    },
    setName : function(arg){
        this.name = arg;
    }
};

var student = create_object(person);
student.setName("ssong");
console.log(student.getName());

//위와 같이 부모 객체의 메서드를 그대로 상속받아서 사용할 수 있고, 자신의 메서드를 재정의 혹은 추가로 구현할 수 있다.
//이때, 자바스크립트에서는 범용적으로 extend()라는 이름의 함수로 자산이 원하는 객체 혹은 메서드를 추가한다.

function extend(obj, prop){
    if(!prop){prop = obj; obj = this;}
    for(var i in prop) obj[i] = prop[i];
    return obj;
}

var studentAdded = {
    setAge : function(age){
        this.age = age;
    },
    getAge : function(){
        return this.age;
    }
};

extend(student, studentAdded);
student.setAge(25);
console.log(student.getAge());


//한 단계 더 상속을 구현해보도록 하겠다.
//student를 상속받은 HiSchoolStudent를 구현하겠다.

var hiSchoolStudent = create_object(student);

var hiSchoolStudentAdded = {
    grade : 3,
    setGrade : function(grade){
        this.grade = grade;
    },
    getGrade : function(){
        return this.grade;
    }
};

extend(hiSchoolStudent, hiSchoolStudentAdded);
console.log(hiSchoolStudent.getName());
console.log(hiSchoolStudent.getAge());
console.log(hiSchoolStudent.getGrade());


2) 클래스역할을 하는 함수로 상속하기.


아래 예제는 일반적인 상속 예제이다. 


핵심이 되는 부분은 Student.prototype에 부모가 될 Person의 인스턴스를 넣어주고, 생성자를 다시 지정해주는 것이다.

이렇게 함으로써, Student의 객체는 Person 객체의 함수와 메서드를 사용할 수 있게 프로토타입 링크가 형성된다.


주의할 점은 자동으로 부모 객체의 생성자가 호출되지는 않으므로 자식 생성자에서 부모 생성자를 호출해주어야 한다.

Person.call(this, name); 부분이 부모 생성자를 호출해 주는 부분이다. 

부모 생성자에 생성될 객체를 this로 넘긴다. 


//클래스역할을 하는 함수로 상속하기 var Person = function(name){ this.name = name; }; Person.prototype.setName = function(name){ this.name = name; }; Person.prototype.getName = function(){ return this.name; }; var Student = function(name, _calss){ //부모클래스 생성자 호출 Person.call(this, name); this.class = _calss; }; Student.prototype = new Person(); Student.prototype.constructor = Student; Student.prototype.getClass = function(){ return this.class; }; Student.prototype.setClass = function(_calss){ this.class = _calss; }; var song = new Student("song", 3); console.log(song.getName()); console.log(song.getClass()); console.log(song instanceof Person); // true console.log(song instanceof Student); // true


3.캡슐화


자바스크립트의 강력한 특성 중 하나인 클로저를 활용하여 캡슐화를 할 수 있다.


1) 기본 예제

아래 예제는 public 메서드가 클로저 역할을하고, private 멤버인 name에 접근한다.

자바스크립트에서 할 수 있는 기본적인 정보은닉 방법이다.

*모듈 패턴


주의할 점은 private 멤버가 객체나 배열인 경우 사용자가 get~~()함수를 통해 받은 값을 손쉽게 수정할 수 있다. 때문에 깊은 복사를 통해서 새로은 객체나 배열을 리턴해주어야 한다.


var Person = function(arg){
    var name = arg ? arg: "song";
    return {
        getName: function(){
            return name;
        },
        setName: function(arg){
            name = arg;
        }
    };
}

var song = Person(); // or var song = new Person();
console.log(song.getName());


위 예제는 객체를 리턴하는데, 이 객체는 Person 함수 객체의 프로토타입에는 접근할 수 없다.

때문에 Person을 부모로 하는 프로토타입을 이용한 상속을 구현하기에는 용이하지 않다. 때문에 이를 보완하기 위해 함수를 반환한다.


2) 캡슐화를 적용한 상속가능 함수.


var Person = function(arg){
    var name = arg ? arg: "song";

    var Person = function(){}
    Person.prototype = {
        getName: function(){
            return name;
        },
        setName: function(arg){
            name = arg;
        }
    };
    
    return Person;
}();

var song = new Person();
console.log(song.getName());


위도 -> y point


위도를 특정 크기의 이미지에 사상하는 소스입니다.

function convertLatitudeToY(lat, imageHeight) {
  let y = (maxLat - lat) / (maxLat - minLat) * imageHeight;
  return y;
}


경도 -> x point


경도를 특정 크기의 이미지에 사상하는 소스입니다.

function convertLongitudeToX(lon, imageWidth) {
  let x = (lon - minLon) / (maxLon - minLon) * imageWidth;
  return x;
}



인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.



클로저


이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 함수를 클로저라고 합니다.

클로저로 참조되는 외부 변수를 자유 변수(Free variable)라고 합니다. closure라는 이름은 함수가 자유 변수에 대해 닫혀 있다는 의미입니다.


//closure 예제
function outerFunc(){
    var x = 1;

    return function(){
        x = x * 2;
        console.log(x);
    };
};

var inner = outerFunc();
// outerFunc 실행 컨텍스트 종료

inner();


위와 같은 코드가 클로저를 구현하는 전형적인 패턴입니다. 외부 함수가 호출되고 이 외부 함수에서 반환된 함수가 클로저입니다.


클로저에서 실행 컨텍스트가 종료된 외부 함수의 변수를 접근할 수 있는 것은,

스코프 체인에서 참조하고 있는 것이 외부 함수의 변수 객체이기 때문입니다. outerFunc의 실행 컨텍스트는 사라젔지만 변수 객체는 여전히 남아있고, inner의 스코프체인으로 참조되고 있습니다.



클로저의 활용


클로저는 스코프체인에서 뒤쪽에 있는 객체에 자주 접근하므로, 성능 저하의 원인이 되기도 합니다. 그러나, 그렇다고 클로저를 쓰지 않는 것은 자바스크립트의 강력한 기능 중 하나를 무시하는 것이므로 잘 사용하는 것이 중요합니다.


1) 특정 함수에 사용자가 정의한 객체의 메서드 연결하기


정해진 형식의 함수를 콜백해주는 라이브러리가 있을 경우, 그 형식과는 다른 형식의 사용자 정의 함수를 호출할 때 유용하게 사용할 수 있습니다.


var Person = function(name){
    this.name = name;
    this.func = null;
};

Person.prototype.introduce = function(){
    this.func ? this.func(this.name): null;
};

Person.prototype.setIntroduce =function(func){
    this.func = func;
}

Person이라는 객체는 introduce라는 함수가 구현되어 있습니다.

introduce는 사용자가 등록한 함수를 호출해줍니다.


var userFunc = function(name){ console.log(name); }; var song = new Person("Song"); song.setIntroduce(userFunc); song.introduce(); //"Song"

사용자가 userFunc라는 함수를 구현하고, Person객체를 만들어서 등록하였습니다.

introduce()를 호출하면 "Song"이 출력됩니다.

간단한 콜백함수의 예입니다.


그런데 사용자가 등록할 수 있는 콜백함수는 name인자 하나를 받도록 형식이 정해저 있습니다.

만약 age를 인자로 추가로 받도록 하려면 어떻게해야 할까요?


클로저를 활용해서 할 수 있습니다.


var createIntroduce = function(obj, methodName, age){ return (function(name){ return obj[methodName](name, age); }); } var newObj = function(obj, age){ obj.setIntroduce(createIntroduce(this, "introduce", age)); return obj; } newObj.prototype.introduce = function(name, age){ console.log(name + ", " + age); }; var song2 = new newObj(song, 29); song2.introduce(); // "Song, 29" 출력


newObj는 Person 객체를 좀 더 자유롭게 사용하기위해 정의한 함수입니다.

위와 같이 클로저의 특성을 이용해서 age도 인자로 받을 수 있도록 할 수 있습니다.


2) 함수의 캡슐화


다음과 같이 전역 변수에 접근을 하는 함수 예제가 있습니다.

이러한 방식의 단점은 전역 변수가 외부에 노출되어 있어서, 다른 함수에서 이 값을 변경할 수도 있고 실수로 같은 이름의 변수를 만들어서 버그가 생길 수도있습니다.

var year = 2018; var month = 5; var day = 12; var sayDate = function(){ console.log(year + "년 " + month + "월 " + day + "일"); }; sayDate();


클로저를 활용해서 전역변수를 추가적인 스코프에 넣고 사용하면 이런 문제를 해결할 수 있습니다. 

sayDate에 익명의 함수를 즉시 실행시켜 반환되는 함수를 할당합니다. 

반환되는 이 함수는 클로저가 되고, 이 클로저는 자유 변수 year, month, day를 참조할 수 있다.


var sayDate = function(){
    var year = 2018;
    var month = 5;
    var day = 12;
    return (function(year, month, day){
        console.log(year + "년 " + month + "월 " + day + "일");
    });
}();

sayDate(); // "2018년 5월 12일"


클로저의 활용시 주의사항


클로저는 강력한 기능이지만 주의해서 사용해야 합니다. 



1) 클로저의 프로퍼티 값이 쓰기 가능하므로 그 값이 여러 번 호출로 항상 변할 수 있다.


2) 하나의 클로저가 여러 함수의 스코프 체인에 들어가 있는 경우도 있다.


3) 루프 안에서 클로저를 활용할 때는 주의하자.




인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.



스코프 체인


자바스크립트에서 굉장히 중요한 개념입니다. 

스코프 체인, 즉 유효범위인데 c++과는 다른 유효범위를 가지고 있기 때문에 주의해야합니다.


오직 함수만이 유효 범위의 한 단위가 되고 [[scope]] 프로퍼티로 각 함수 객체 내에서 연결 리스트 형식으로 관리됩니다.

이를 스코프 체인이라 합니다.


각각 함수는 [[scope]]프로퍼티로 자신이 실행된 실행 컨텍스트의 스코프 체인을 참조합니다. 함수가 실행되는 순간 실행 컨텍스트가 만들어지고 이 실행 컨텍스트는 실행된 함수의(실행된 함수가 속한 실행 컨텍스트의 scope) [[scope]] 프로퍼티를 기반으로 새로운 스코프 체인을 만듭니다.


스코프 체인

1. 현재 실행되는 함수 객체의 [[scope]] 프로퍼티를 복사한다.

2. 새롭게 생성된 변수 객체(활성 객체)를 맨앞에 추가한다.


-> 스코프 체인 = 현재 실행 컨텍스트의 변수 객체 + 상위 컨텍스트의 스코프 체인



var name = 'song';

function printName() {
    var age = 29;

    function printAge(){
        console.log(age);
    };

    console.log(name);
}; 


위와 같은 예제의 스코프 체인을 그려 보면 다음과 같습니다.




이렇게 만들어진 스코프 체인으로 식별자 인식이 이루어집니다. 식별자 인식은 첫 번째 변수 객체부터 시작하여 해당하는 프로퍼티가 있는 지 탐색하고, 발견하지 못하면 다음 객체로 이동하며 탐색을 진행합니다.



인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.



실행 컨텍스트


ECMAScript에서는 실행 컨텍스트를 "실행 가능한 코드를 형상화하고 구분하는 추상적인 개념"이라고 기술합니다.

이 컨텍스트 안에 실행에 필요한 여러 가지 정보를 담고 있습니다. 


실행 컨텍스트가 생성되는 경우는 세 가지가 있습니다.

1) 전역 코드

2) eval() 함수로 실행되는 코드

3) 함수 안의 코드를 실행할 경우


대부분 함수로 실행 컨텍스트를 만듭니다.

ECMAScript에서는 또 실행 컨텍스트 생성을 다음처럼 설명합니다.

"현재 실행되는 컨텍스트에서 이 컨텍스트와 관련 없는 실행 코드가 실행되면, 새로운 컨텍스트가 생성되어 스택에 들어가고 제어권이 그 컨텍스트로 이동한다."


전역 실행 컨텍스트는 일반적인 실행 컨텍스트와 다릅니다. arguments 객체가 없으며 전역 객체 하나만을 포함하는 스코프 체인이 있습니다.


약간 차이점이 있지만 C++에서 콜스택과 비슷한 개념이라고 보시면 쉬울 것 같습니다.


실행 컨텍스트가 생성되면 자바스크립트 엔진을 활성 객체를 생성합니다. 이 객체에 앞으로 사용하게 될 매개변수나 사용자가 정의한 변수 및 객체를 저장하고, 새로 만들어진 컨텍스트로 접근 가능하게 되어 있습니다.


활성 객체


실행 컨텍스트가 생성되면 자바스크립트에서는 해당 컨텍스트에서 실행에 필요한 여러가지 정보를 담을 객체를 생성합니다. 그게 바로 활성 객체입니다. 사용자가 접근할 수 있는 영역은 아니고 자바스크립트 엔진이 사용하는 영역입니다.


활성 객체가 지닌 정보

1) argumens 객체

인자로 들어온 arguments 객체를 arguments 프로퍼티로 접근합니다.


2) 스코프 정보// 스코프 체인 scope 프로퍼티

현재 컨텍스트의 유효 범위를 나타내는 스코프 정보를 생성합니다.


3) 변수

변수나 내부함수는 활성 객체가 생성되는 시점에 생성은 되지만 초기화는 해당 표현식이 실행될 때 이루어집니다.


4) this