라디오 버튼을 이용하여 DIV를 각각 활성화 시켜서 사용하는 함수를 간단히 작성하면 아래와 같다.


- HTML

<input type="radio" name="tp_cd" value="1" checked="checked"> 1번

<input type="radio" name="tp_cd" value="2" > 2번


<div id="POP1"><p>POP1의 영역이 보임</p></div>

<div id="POP2" style="display: none;"><p>POP2의 영역이 보임</p></div>


- jquery

$('input[type=radio][name=tp_cd]').on('click', function() {

var chkValue = $('input[type=radio][name=tp_cd]:checked').val();


if (chkValue == '1') {

$('#POP1').css('display', 'block');

$('#POP2').css('display', 'none');

return false;

} else if (chkValue == '2') {

$('#POP1').css('display', 'none');

$('#POP2').css('display', 'block');

return false;

}

});


위와 같은 방법으로 작성하면 된다.

jquery는 css에 display: none; 일 경우 화면에서 보여지지 않고, display: block; 일 경우 화면에 보여지는 것을 이용한 것이다.

POP2의 영역이 처음부터 노출되는 것을 막기 위해서는 HTML에서 스타일을 주면 된다.


함수 안에 return false;를 입력하게 되면 2번을 선택하더라도 기존에 체크되어있던 라디오버튼 1번에 계속 체크가 되어있다. (DIV는 POP2가 보이게된다.)

이를 해결하기 위해서는 간단하게 return false; 를 지우면 된다.

게시판을 만들다보면 게시글 제목이 너무 길어 생략이 필요한 경우가 있다.

이 경우 CSS로 간단하게 해결할 수 있다.


table {

table-layout: fixed;

}


td {

text-overflow: ellipsis;

white-space: nowrap;

overflow: hidden;

}


위의 내용은 table과 td에 모두 적용이 되지만 class로 지정하여 사용하면 원하는 부분에만 사용이 가능하다.



MySQL을 외부 IP에서 접속할 수 있도록 하기 위해서는 설정이 필요하다.

아래에 각각 모든 IP에서 접속 / 특정 IP에서 접속 / 원래상태로 복구하는 방법에 대한 정리를 하도록 하겠다.


1. 모든 IP에서 접속

use mysql;

INSERT INTO mysql.user(host, user, password) VALUES('%', 'root', password('패스워드'));

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';

FLUSH PRIVILEGES;

기본적으로 위의 내용을 차례대로 입력할 경우 root라는 계정으로 접속할 경우 모든 외부 IP에서 접속이 가능하다.

하지만 MySQL의 버전에 높아지면서 위의 내용을 입력할 경우 보안 관련 오류가 발생할 수 있다.

이 경우 오류 메세지는 두 가지가 발생할 수 있는데 각각 아래의 두 가지의 방법으로 해결이 가능하다.


- ERROR 1364(HY000): Field 'ssl_cipheer' doesn't have a default value 

use mysql;

INSERT INTO mysql.user(host, user, password, ssl_cipher, x509_issuer, x509_subject) VALUES('%', 'root', password('패스워드'), '', '', '');

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';

FLUSH PRIVILEGES;


- ERROR 1364(HY000): Field 'authentication_string' doesn't have a default value 

use mysql;

INSERT INTO mysql.user(host, user, authentication_string, ssl_cipher, x509_issuer, x509_subject) VALUES('%', 'root', password('패스워드'), '', '', '');

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';

FLUSH PRIVILEGES;

참고로 authentication_string로 password를 변경한 경우 VALUES에서 password('패스워드')에 변경이 일어나지 않는다.




2. 특정 IP에서 접속

  이 경우에는 VALUES에서 HOST값을 변경하면 된다. 아래의 예제는 111.222.xxx.xxx의 IP에 접속이 가능하며 한 IP만 접속이 가능하게 하려면 해당 IP를 정확히 적어주면 된다.

use mysql;

INSERT INTO mysql.user(host, user, password) VALUES('111.222.%', 'root', password('패스워드'));

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';

FLUSH PRIVILEGES;




2. 원래 상태로 복구

  외부에서 접속하지 못하도록 하기 위해서는 입력한 내용을 아래와 같이 삭제하면 된다.

use mysql;

DELETE FROM mysql.user WHERE HOST = '%' AND User = 'root';

FLUSH PRIVILEGES;



jsp에서 form을 이용하여 화면간의 이동을 하면서 변수를 넘길 때, 유용하게 사용하는 형식은 대부분

int num = Integer.parseInt(request.getParameter("num"));

String result = request.getParameter("result");

위와 같은 형태이다.


하지만 파일과 같은 이유 때문에 아래와 같은 형태로 사용을 하게 된다면 request를 이용하여 데이터를 받아오는 것은 불가능하다.

<form id="Frm" action="" method="post" enctype="multipart/form-data">

...

</form>

이때는, MultipartRequest multi = new MultipartRequest(request, savePath, maxSize, "UTF-8", new DefaultFileRenamePolicy()); 를 이용하여

request 대신 multi를 이용하여 받아오는데, 


상황에 따라 request를 이용해야할 경우가 발생한다. 이때 javascript에서

function fn_check() {

Frm.encoding="application/x-www-form-urlencoded";

Frm.action="./action.jsp";

Frm.submit();

}

위와 같은 형태로 form의 encoding을 변경하여 사용할 수 있다.




쓸 때마다 기억이 제대로 나지 않아서 찾아보는 내용이다.

개인적으로 자주 쓸 일이 없기도 하고, 기억력이 좋지 않기도 하고...


PrintWriter out=response.getWriter();


response.setContentType("text/html; charset=utf-8");

out.println("<script language='javascript'>");

out.println("alert('쓰고 싶은 내용을 쓰자');");

out.println("</script>");

out.flush();


다음에 또 이 내용을 찾는다고 시간을 날리지 않길 바라며.


jsp에 form 태그에 action에 URL을 주고 javascript에서 submit() 처리를 하는데, 화면이 이동하지 않아서 이유를 찾는다고 시간을 보냈다.

게시판의 제목을 클릭하면 a태그를 이용하여 화면을 이동하는 것이었는데, onclick에 함수를 실행시킨 것이 잘못이었다.


기존에 사용하고 있던 a태그의 형태는 아래와 같았다.

<a href="?" onclick="fn_action()">글 제목이 들어갈 부분</a>

위의 형태는 js의 함수에 들어가는 것은 확인이 되었지만 frm.submit()이 실행되지 않고, 현재 페이지를 계속 새로고침 하는 형태로 보여줬다.


그래서 아래와 같이 수정을 하자 원하는 대로 submit() 동작이 되었다.

<a href="javascript:fn_action()">글 제목이 들어갈 부분</a>




기존에 컴퓨터에 있던 이클립스로 Angular를 설치하려고 하니 계속 버전에 맞지 않는 문제로 설치가 되지 않았다.

그래서 아예 새로운 이클립스 버전을 깔고 Angular를 설치해서 프로젝트를 생성했다.


새로 설치한 이클립스 버전으로 사실 Oxygen 은 이번에 처음 알게되었다.

위키에서 확인해본 결과 2017년 6월 28일이 Oxygen 버전의 배포일이라고 되었다.

배포한지 채 한달도 지나지 않은 버전.

(가장 최근 버전을 깔면 버전 오류가 나지 않겠지!!!!라는 생각으로 깔았다......)


[Help > Eclipse Marketplaces...] 로 들어가서 angularJS를 검색하여 Angular IDE 2017 CI 7과 nodejs를 검색하여 Nodeclipse 1.0.2를 다운받았다.


이 후, 바로 Angular프로젝트를 생성할 수 있다.

마우스 우측 클릭을 해서 [ New > Project...] 를 선택한다.


팝업 창에서 Angular 폴더에 Angular Project가 있는 것을 확인할 수 있다.

기존에는 Dynamic Web Project를 생성해서 프로젝트를 선택하여 Config로 Angular로 프로젝트를 변환 시켜서 사용하는 것 같았다.


원하는 프로젝트 명을 작성하고.


위의 설정까지 하면 Server에 기본으로 Angular CLI가 생기는데, 프로젝트를 선택해서 실행시키면 아래와 같이 프로젝트가 열리게된다.





기본적으로 angularJS에 대한 내용을 알아보기 위해서는

https://angular.io

위의 URL로 이동하여 예시를 따라하거나 예제 파일을 활용할 수 있다.


먼저 위의 홈페이지로 이동하여 GETTING STARTED 화면을 보면 간단하게 프로젝트를 생성하고 확인할 수 있도록 되어있다.


우선 가장 먼저 해야할 것은

https://nodejs.org/en/download/

해당 사이트로 이동하여 node.js를 다운받아 설치한다.

해당 사이트의 화면으로 맞는 버전을 찾기 위해 위에 DOWNLOADS에 들어갔다.


필요한 버전을 찾아 다운로드를 했다.


다운로드 된 아이콘을 확인하고 설치를 시작.


Next 클릭.


설치중......


설치가 완료된 것을 확인할 수 있다.


이제 cmd(명령 프롬프트) 창을 열어 node 버전을 확인하고 실행을 시킬 수 있다.

cmd 창은 위와 같이 검색을 해서 간단하게 열 수 있다.


위와 같이 node --version을 입력 하면, 정상 설치가 완료되었을 경우 설치한 node의 버전을 확인할 수 있다.


다음에는 npm install -g @angular/cli를 입력하여 Angular CLI를 설치한다.


angular 프로젝트를 생성하기 위해서는 위의 명령어를 작성하면 된다.

(my-app은 프로젝트 명이다)


위와 같이 생성한 프로젝트 안으로 들어가서 프로젝트를 실행시키면 아래와 같은 화면이 열리는 것을 확인할 수 있다.

프로젝트가 실행되는데 어느정도의 시간이 소요된다.


가장 기본적으로 따라해볼 수 있는 내용인 것 같다.


그리고 명령 프롬프트에

ng build 를 입력하면 해당 프로젝트를 배포할 수 있는 형태로 빌드해준다.

또한, 기존에는 프로젝트를 생성해도 해당 경로에서 프로젝트가 보이지 않는데, 빌드를 하고 나면 해당 경로에서 프로젝트를 확인할 수 있다.


1. 변수 Varialble

변수는 주로 const와 let을 이용하여 선언한다.

변수 선언의 기본 형태는 아래와 같다.

// 변수에 값을 넣으면서 초기화

const myStr : String = "Hello World!";

let myNum : Number = 2017;

// 변수만 초기화

let myNum : Number;

myNum = 2017;

// 변수 타입 생략

const myStr = "Hello World!";

let myNum = 2017;

변수만 초기화하는 경우 let만 선언이 가능하며, const는 사용이 불가능하다.

한 번 정해진 변수 타입은 변경이 불가능하며, 변수를 초기화할 때 변수의 타입을 적어주지 않더라도 초기화할 값으로 컴파일러가 변수의 타입을 결정할 수 있으므로 명시적인 생략이 가능하다.


const array1 : Number[] = [2017, 6, 29];

const array2 : [Number, String] = [2017, "Thursday"];


const myArr : (Number|String)[] = [2017, "Thursday"];

myArr[0] = "2017";

타입을 설정할 때, 파이프( | )를 이용하면 여러타입 중 하나를 선택할 수 있는데, 이를 유니온 타입이라고 한다.



2. 함수 Function

기본적인 함수 형태는 같으나 차이가 있다. TypeScript는 함수에도 타입 선언이 가능하며, 타입 지정 대상은 함수로 전달되는 매개 변수와 최종 리턴 값이 될 수 있다.


function myFunc1(a : number, b : number) : number {

return a+b;

}

consle.log(myFunc1(1,2));


function myFunc2(a : number, b : number) {

return a+b;

}

consle.log(myFunc2(1,2));

위의 예제에서 둘의 차이점은 리턴 값의 타입을 선언하여 보여주는 것이며, 두 함수의 결과 값은 모두 같다.


var myFunc3 = (num : number) : number => {

return (num * num);

}


var myFunc4 = (num : number) => {

return (num * num);

}

위의 예제는 Arrow 함수를 이용하여 함수를 표현항 방식이다.


var myFunc5 = (num : number) => (num * num);

또한 위와 같이 축약형태로도 사용이 가능하다.



3. 오브젝트 objects

오브젝트는 key와 value를 쌍으로 가지는 인스턴스이다. value는 스칼라(scalar), 함수, 다른 오브젝트 등을 값으로 가질 수 있다.

var objName = {

key1 : 2017,

key2 : "value",

key3 : function() {......},

key4 : ["content1", "content2"]

};

오브젝트는 위와 같은 형태로 구현할 수 있다.

그리고 오브젝트 내에 함수를 선언하여 오브젝트의 함수로 사용이 가능하다. 아래는 오브젝트 내에 함수를 선언하여 사용하는 예제이다.

var person = {

firstName : "마루나"

lastName : "J"

sayHello : function(){}

};

person.sayHello = function() {

console.log("Hello!" + person.firstName);

);

person.sayHelo();

위와 같은 형태로 사용이 가능하다. 그리고 함수의 매개변수에 오브젝트를 넣을 수 있다.

매개 변수에 사용하는 형태는 obj 혹은 obj : {firstName : string} 처럼 사용하면 된다.



4. 인터페이스 Interfaces

클래스의 구현부가 제외된 형태의 것으로 인터페이스로 선언한 객체가 인터페이스 내에 선언한 프로퍼티나 메소드를 가지는 것을 의미한다.

실질적인 구현은 인터페이스를 사용하는 클래스에서 한다.

interface Shape {

getArea() : number;

}

class Rect implements Shape {

width : number;

height : number;

constructor(width, height) {

this.width = width;

this.height = height;

}

getArea() {

return (width * height);

}

}

위와 같은 형태가 인터페이스를 사용하는 가장 기본 형태이다. implements는 Shape 인터페이스를 사용한다고 선언하는 것이므로 Rect 클래스 안에서 인터페이스를 사용해야한다.


아래는 변수 선언 방법에 대한 내용이다.

// 기본 변수 선언

value1 : string;

// 선택적으로 변수를 사용할 수 있도록 선언

value2 ?: number;

// 읽기만 가능한 변수 선언으로 변수 수정이 불가

readonly value3 : string;

위의 readonly는 프로퍼티에서 사용이 되며, 변수에는 const로 상수 선언이 가능하다.


interface square {

color?: string;

width?: number;

}

function createSquare(config : Square) : {color : string; area : number} {......}


// 에러 발생

let mySquare = createSquare({colour : "red", width : 100});

// 성공

let temp = {colour : "red", width : 100};

let mySquare = createSquare(temp);

위에서 실패한  예제는 color 변수대신 colour 변수가 들어가있다. 이 경우 명백히 잘못된 인자가 들어간 것이므로 에러가 발생한다. 하지만 아래의 경우 temp에도 color 변수가 colour로 입력되어있는 것을 확인할 수 있다. 아래의 경우에는 colour이 temp의 변수이므로 다른 곳에서 해당 변수를 사용할 수 있다고 판단하여 에러가 발생하지 않는 것이다.


interface interFunc {

(source : string, subString : string) : boolean;

}

let mySearch : interFunc;

mySearch = function(source : string, subString : string) {

let result = source.search(subString);

if (result == -1) {

return false;

} else {

return true;

}

}

인터페이스의 함수는 파라미터와 리턴 값을 지정할 수 있다. 함수 인자 이름은 변경이 가능하며, 괄호안에 값을 넣는다. return값은 ' : '을 이용하여 선언한다.



5. 클래스 Classes

이전 게시글에서 나온 ECMAScript2016(ES6)의 클래스 설명과 차이점을 비교하면서 확인하는게 더 유용할 것 같다.

class Rect {

width : number;

height : number;

static count : number;


constructor(width : number, height : number) {

this.width = width;

this.height = height;

Rect.count++;

}

}

new Rect(10, 10);

new Rect(20, 20);

Rect.count;            // 2

위의 예제가 기본 클래스의 형태이며, ES6와는 달리 클래스 생성자에서 사용하는 변수는 클래스 내부 프로퍼티로 선언을 하여야한다. 선언하지 않을 경우 생성자에서 오류가 발생한다.

또한, ES6의 경우 static 메서드는 사용이 가능하지만 static 프로퍼티를 사용하지 못했다. 하지만 TypeScript의 경우 static 프로퍼티 사용이 가능하다. 그리고 접근 제한자(private, public, protected)가 사용이 가능하며, readonly도 사용이 가능하다. readonly는 어느 접근 제한자에도 제한없이 사용이 가능하다.

- readonly 사용 방법 : 접근제한자 readonly 변수;


상속을 위한 추상클래스(추상메소드를 가진 클래스)는 구현부가 없는 메소드를 가진 클래스이다. 객체 인스턴스는 생성이 불가능하며, 상속용으로만 사용이 가능하다.

+) 인터페이스는 모든 메소드가 추상 메소드인 반면 추상클래스는 실제 구현이 있는 메소드도 포함하여 사용 할 수 있다.



ECMAScript2015의 기본 개념에 대해 대략적으로 정리를 한 부분이다.


ECMAScript2015에서는 아래의 내용이 화면 전체 혹은 함수 내에 작성되어있는 것을 볼 수 있다.

'use strict';

이것은 '엄격모드'라고도 하며, ES6 버전에서 새롭게 추가된 기능이다. 프로그램 또는 함수를 사용할 때, 문법을 더 정확히 사용할 수 있도록 도와주는 역할로 기존에 가능했던 사용방법에서 오류가 발생할 수 있다.

- 필수 사용은 아니다.

- 모호하거나 틀린 문법에서 오류를 발생시킨다. (ex. 같은 이름의 변수 선언 등)

- IE의 경우 버전 10 이전에서는 사용이 불가하다.



1. Arrow(=>, 화살표 함수)

- ES6에서 처음 도입된 개념

- 짧은 함수 및 바인딩하지 않은 this가 arrow의 도입에 영향을 끼쳤다. (this 사용의 번거로움 해소를 위해)

- 함수 표현에 비해 구문이 짧다.

- 항상 익명으로 사용이 된다.

- 메소드가 아닌 곳에 적합하므로 생성자로 사용할 수 없다.


아래의 경우 arrow 함수 사용 형태에 대한 설명이다.

1) arrow 사용의 기본 형태

(param1, param2, ..., paramN) => {statement}

(param1, param2, ..., paramN) => expression        // {return expression}과 동일하다


2) 매개변수가 하나일 경우 괄호는 선택사항이다.

(singleParam) => {statement}

singleParam => {statement}


3) 매개변수가 없을 경우 괄호는 필수사항이다.

() => {statement}


4) 객체 리터럴 식을 반환하는 본문(body)은 괄호속에 넣어서 표현한다.

params => ({foo:bar})


5) 나머지 매개변수 및 기본 매개변수가 지원된다.

(param1, param2, ...rest) => {statement}

(param1 = defaultValue1, param2, ..., paramN = defaultValueN) => {statement}


6) 매개변수 목록 내 비구조화도 지원된다.

var f = ([a, b] = [1, 2], {x : c} = {x : a + b} => a + b + c);

f();                // 결과값


아래는 이해에 도움이 되도록 JS에서 기존 사용했던 방식과 arrow 함수를 사용한 방식이다.

// JS

function(a) { return a > 0; }


// ES6

a => a > 0


기존 콜백함수나 이벤트리스너를 arrow 함수를 이용해 새로운 방식으로 사용할 수 있다.

(콜백함수를 등록하는 시점에 this를 콜백함수에 access를 하는 경우가 발생하는데, 클로저를 이용하여 this를 속박하는 등의 방식 대신 arrow 함수로 더 효율적으로 사용할 수 있다.)


var exFunc = {

var cnt : 0,

ex1 : function(selector) {

var node = document.querySelector(selector);

node.addEventListener('click', function(evt) {

this.cnt++;

}.bind(this));

}

};

exFunc.ex1('body');

위의 내용을 아래처럼 바꿔서 사용할 수 있다.

var exFunc = {

var cnt : 0,

ex1 : function(selector) {

var node = document.querySelector(selector);

node.addEventListener('click', (evt) => {

this.cnt++;

});

}

};

exFunc.ex1('body');



아래는 바인딩되지 않는 this에 대한 예제로 arrow 함수 사용 이전에는 모든 새로운 함수는 자신의 this값을 정의해서 사용해야하는 것을 보여준다.

function addFunc() {

this.num= 0;

setInterval(function add() {

this.num++;

}, 1000);

}

var a = new addFunc();

위의 예제에는 add()함수는 this를 전역 객체로 정의하여 사용한다. 따라서 addFunc() 생성자의 this와는 다른 this이다.

아래의 예제는 비전역 변수에 할당하여 위의 문제를 해결을 하는 것이다.

function addFunc() {

var temp = this;

temp.num= 0;

setInterval(function add() {

temp.num++;

}, 1000);

}

var a = new addFunc();

위의 문제를 ES6부터는 arrow 함수를 이용하여 처리할 수 있다.

arrow 함수는 자신만의 this를 생성하지 않고, 감싸고 있는 컨텍스트의 this를 가져오므로 의도한대로의 기능을 가진다.

function addFunc() {

this.num

setInterval(() => {

this.num++;

}, 1000);

}

var a = new addFunc();

다시 말해 위의 arrow 함수를 이용한 뒤의 this는 addFunc()의 this와 같은 this이다.



2. Promise 객체

- 콜백이 중첩되어 사용되는 경우(하나의 작업을 콜백으로 처리한 뒤, 순차적으로 다음 작업을 진행하고자 하는 경우)에 사용할 수 있다.

- Promise 패턴을 사용하면 비동기 작업을 순차적으로 진행하거나, 병렬로 진행하는 등의 작업의 효율이 높아진다.

- 예외처리 구조가 잘되어 있으므로 오류처리에 대해 더 가시적인 처리가 가능하다.

- chrome 32 버전부터 native promise가 지원 가능하다.


아래는 Promise 패턴의 기본적인 예제이다.

var promiseFunc(param) {

return new Promise(function(resolve, reject) {

window.setTimeout(function() {

if (param) {

resolve("해결!");

} else {

reject(Error("실패!"));

}

}, 1000);

});

};

// 실행

promiseFunc(true)

.then(function(text) {

console.log(text);

}, function(error) {

console.error(error);

};

함수 선언은 var promiseFunc = function(param){...}; 의 형식으로 선언하여도 무관하다.

Promise 객체를 return으로 감싸는 이유는 Promise 객체 생성을 위한 것이다. 그리고 parameter를 익명함수로 가지고 있으며, resolve와 reject를 parameter로 가진다.


위의 과정을 볼 때, new Promise로 Promise가 생성되는 직후부터 resolve나 reject가 호출되기 전까지의 순간을 pending상태라고 한다.

이후, 비동기 작업을 마친 뒤, 결과물을 약속대로 전달할 수 있다면 첫번째 parameter로 주입되는 resolve 함수를 호출하고, 실패하면 두번째 parameter로 주입되는 reject함수를 호출한다.


아래는 Promise 객체의 네가지 상태를 정리한 것이다.

1. pending

: 아직 Promise를 수행중인 단계 (fullfilled 혹은 rejected 이전)

2. fullfilled

: Promise가 지켜진 상태

3. rejected

: Promise가 지켜지지 못한 상태

4. settled

: Promise 성공 여부와 무관하게 결론이 난 상태


예제에서 함수를 실행하는 부분을 보면 Promise 객체는 정상적으로 비동기화가 완료될 경우 then이라는 API가 존재하여 이를 이용한 결과를 실행한다. 위의 예제에서는 콘솔로그를 이용하여 '해결!'이라는 문구를 보여준다.

then API는 첫번째 parameter에는 성공시 호출할 함수를, 두번째 parameter에는 실패시 호출할 함수를 선언하고 Promise의 상태에 따라 수행한다.

작업 중 중간에 에러를 잡기 위해서는 catch API를 사용할 수 있다. catch API의 형태는 .catch(function(){......}) 와 같다.


* 여러개의 Promise 완료를 확인 해야하는 경우

var promise1 = new Promise(function(resolve, reject) {......});

var promise2 = new Promise(function(resolve, reject) {......});


Promise.all([promise1, promise2]).then(function(values) {

console.log("promise1과 promise2가 모두 완료됨.", values);

});

위와 같이 사용하면 promise1과 promise2를 처리하는데 시간차가 나더라도 두 promise가 모두 완료되어야 .all이 실행되어 확인이 가능하다.



3. 블록스코프

ES6부터 사용이 가능한 기능으로 기존에 사용하던 변수 var 외의 let 변수를 사용할 수 있다.

let 변수는 var와 다르게 호이스팅(hoisting)을 하지 않는다.

* 호이스팅(hoisting)

: 선언이 뒤에서 이루어진 경우, 선언된 변수나 함수가 Scope의 최상위에 위치하는 것을 의미하는 것으로 이로 인해 뒤에서 선언한 변수나 함수를 그 이전에 사용할 수 있도록 해준다.

따라서 변수가 선언된 이후부터 변수가 유효하고, 한 블록 내에서도 변수 선언 이전에는 에러처리가 된다.

같은 스코프에서 같은 이름의 변수를 다시 선언할 경우 에러처리가 된다. 하지만 변수 선언에서 문제가 되는 것이 아니라 실제로 해당 구문을 실행하면서 에러처리가 이루어지는 것이므로 같은 이름의 변수를 선언만 하고 사용하지 않을 경우 에러처리가 이루어지지 않는다.



4. 클래스 문법

class 키워드가 ES6에 추가되었지만 클래스기반 객체지향 개념이 추가된 것은 아니며, 프로토타입의 개념이다.

//클래스 선언

class Shape {

// 생성자

constructor(width, height) {

this.width = width;

this.height = height;

}

// 멤버메서드

getArea() {

return 0;

}

// static 메서드

static getType() {

return 'Shape';

}

}

위의 예제에서 class를 사용하는 방법을 확인할 수 있다.

클래스 선언을 할 때 위의 형태 대신 var Shape = class {......}의 형태로 선언할 수 있다. 이는 클래스도 함수이므로 함수표현식(function expression)으로 정의가 가능한 것이며, 클래스표현식(class expression)이라고도 한다.

+) getType()과 같이 static 메서드는 정의할 수 있으나 static 멤버를 정의할 수는 없다.


new Person();

class Person {......}

클래스 선언에서 유의할 점 중 하나는 클래스 선언에는 호이스팅(hoisting)이 적용되지 않는다는 것이다. 그러므로 위처럼 class 선언이 뒤에 나올 경우 Uncaught SyntaxError가 발생한다. 그리고 같은 이름의 클래스를 중복 선언할 경우 문법 에러가 발생한다.


class Rect extends Shape {

constructor(width, height) {

super(width, height);

}

getArea() {

return (this.width * this.height);

}

getType() {

return super.getType() + ' : Rect()';

}

}

또한 클래스를 이용하여 위와 같이 extends를 이용해 상속을 받을 수 있다.

생성자의 경우 super로 부모 참조가 가능하며, getArea()와 같이 부모의 메서드명과 같은 메서드가 있다면 부모의 메서드를 덮어쓸 수 있다. 그리고 getType()에서 확인 할 수 있듯이 멤머 메서드 내에서도 부모 인스턴스를 참조하여 사용할 수 있다.

+ Recent posts