From da78a9e329e272dedb2400b79a3bdeebff387d47 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:17 -0500 Subject: initial commit --- files/ko/web/javascript/guide/closures/index.html | 454 ++++++++++ .../control_flow_and_error_handling/index.html | 433 ++++++++++ .../guide/expressions_and_operators/index.html | 926 +++++++++++++++++++++ files/ko/web/javascript/guide/index.html | 138 +++ .../guide/indexed_collections/index.html | 456 ++++++++++ .../inheritance_and_the_prototype_chain/index.html | 531 ++++++++++++ .../guide/iterators_and_generators/index.html | 193 +++++ .../javascript/guide/keyed_collections/index.html | 149 ++++ .../guide/loops_and_iteration/index.html | 332 ++++++++ files/ko/web/javascript/guide/modules/index.html | 414 +++++++++ .../javascript/guide/numbers_and_dates/index.html | 384 +++++++++ .../core_javascript_1.5_guide/about/index.html | 109 +++ .../index.html | 26 + .../core_javascript_1.5_guide/constants/index.html | 28 + .../creating_a_regular_expression/index.html | 35 + .../defining_getters_and_setters/index.html | 84 ++ .../defining_methods/index.html | 43 + .../index.html | 11 + .../deleting_properties/index.html | 20 + .../creating_new_objects/index.html | 6 + .../indexing_object_properties/index.html | 9 + .../using_a_constructor_function/index.html | 58 ++ .../using_this_for_object_references/index.html | 25 + .../expressions/index.html | 16 + .../javascript_overview/index.html | 44 + .../core_javascript_1.5_guide/literals/index.html | 174 ++++ .../objects_and_properties/index.html | 39 + .../operators/arithmetic_operators/index.html | 44 + .../operators/assignment_operators/index.html | 62 ++ .../operators/bitwise_operators/index.html | 101 +++ .../core_javascript_1.5_guide/operators/index.html | 108 +++ .../operators/logical_operators/index.html | 68 ++ .../operators/special_operators/index.html | 228 +++++ .../operators/string_operators/index.html | 11 + .../array_object/index.html | 133 +++ .../predefined_core_objects/index.html | 20 + .../core_javascript_1.5_guide/unicode/index.html | 109 +++ .../core_javascript_1.5_guide/values/index.html | 39 + .../core_javascript_1.5_guide/variables/index.html | 64 ++ .../javascript/guide/text_formatting/index.html | 275 ++++++ .../web/javascript/guide/using_promises/index.html | 361 ++++++++ .../values,_variables,_and_literals/index.html | 708 ++++++++++++++++ .../guide/working_with_objects/index.html | 500 +++++++++++ .../index.html" | 714 ++++++++++++++++ .../index.html" | 258 ++++++ .../guide/\354\206\214\352\260\234/index.html" | 153 ++++ .../assertions/index.html" | 244 ++++++ .../groups_and_ranges/index.html" | 91 ++ .../index.html" | 666 +++++++++++++++ .../guide/\355\225\250\354\210\230/index.html" | 658 +++++++++++++++ 50 files changed, 10752 insertions(+) create mode 100644 files/ko/web/javascript/guide/closures/index.html create mode 100644 files/ko/web/javascript/guide/control_flow_and_error_handling/index.html create mode 100644 files/ko/web/javascript/guide/expressions_and_operators/index.html create mode 100644 files/ko/web/javascript/guide/index.html create mode 100644 files/ko/web/javascript/guide/indexed_collections/index.html create mode 100644 files/ko/web/javascript/guide/inheritance_and_the_prototype_chain/index.html create mode 100644 files/ko/web/javascript/guide/iterators_and_generators/index.html create mode 100644 files/ko/web/javascript/guide/keyed_collections/index.html create mode 100644 files/ko/web/javascript/guide/loops_and_iteration/index.html create mode 100644 files/ko/web/javascript/guide/modules/index.html create mode 100644 files/ko/web/javascript/guide/numbers_and_dates/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/about/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/class-based_vs._prototype-based_languages/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/constants/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_a_regular_expression/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_getters_and_setters/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_methods/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_properties_for_an_object_type/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/deleting_properties/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/indexing_object_properties/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/using_a_constructor_function/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/using_this_for_object_references/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/expressions/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/javascript_overview/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/literals/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/objects_and_properties/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/arithmetic_operators/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/assignment_operators/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/bitwise_operators/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/logical_operators/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/special_operators/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/string_operators/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/predefined_core_objects/array_object/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/predefined_core_objects/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/unicode/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/values/index.html create mode 100644 files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/variables/index.html create mode 100644 files/ko/web/javascript/guide/text_formatting/index.html create mode 100644 files/ko/web/javascript/guide/using_promises/index.html create mode 100644 files/ko/web/javascript/guide/values,_variables,_and_literals/index.html create mode 100644 files/ko/web/javascript/guide/working_with_objects/index.html create mode 100644 "files/ko/web/javascript/guide/\352\260\235\354\262\264_\353\252\250\353\215\270\354\235\230_\354\204\270\353\266\200\354\202\254\355\225\255/index.html" create mode 100644 "files/ko/web/javascript/guide/\353\251\224\355\203\200_\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/index.html" create mode 100644 "files/ko/web/javascript/guide/\354\206\214\352\260\234/index.html" create mode 100644 "files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/assertions/index.html" create mode 100644 "files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/groups_and_ranges/index.html" create mode 100644 "files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/index.html" create mode 100644 "files/ko/web/javascript/guide/\355\225\250\354\210\230/index.html" (limited to 'files/ko/web/javascript/guide') diff --git a/files/ko/web/javascript/guide/closures/index.html b/files/ko/web/javascript/guide/closures/index.html new file mode 100644 index 0000000000..b56d843b2b --- /dev/null +++ b/files/ko/web/javascript/guide/closures/index.html @@ -0,0 +1,454 @@ +--- +title: 클로저 +slug: Web/JavaScript/Guide/Closures +tags: + - Closure + - ES5 + - Intermediate + - JavaScript + - Reference +translation_of: Web/JavaScript/Closures +--- +
{{jsSidebar("Intermediate")}}
+ +

클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다.

+ +

어휘적 범위 지정(Lexical scoping)

+ +

다음을 보자:

+ +
function init() {
+  var name = "Mozilla"; // name은 init에 의해 생성된 지역 변수이다.
+  function displayName() { // displayName() 은 내부 함수이며, 클로저다.
+    alert(name); // 부모 함수에서 선언된 변수를 사용한다.
+  }
+  displayName();
+}
+init();
+ +

init()은 지역 변수 name과 함수 displayName()을 생성한다. displayName()init() 안에 정의된 내부 함수이며 init() 함수 본문에서만 사용할 수 있다. 여기서 주의할 점은 displayName() 내부엔 자신만의 지역 변수가 없다는 점이다. 그런데 함수 내부에서 외부 함수의 변수에 접근할 수 있기 때문에 displayName() 역시 부모 함수 init()에서 선언된 변수 name에 접근할 수 있다. 만약 displayName()가 자신만의 name변수를 가지고 있었다면, name대신 this.name을 사용했을 것이다.

+ +

{{JSFiddleEmbed("https://jsfiddle.net/78dg25ax/", "js,result", 250)}}

+ +

위 코드를 실행하면 displayName() 함수 내의 alert()문이 부모 함수에서 정의한 변수 name의 값을 성공적으로 출력한다. 이 예시를 통해 함수가 중첩된 상황에서 파서가 어떻게 변수를 처리하는지 알 수 있다. 이는 어휘적 범위 지정(lexical scoping)의 한 예이다. 여기서 "lexical"이란, 어휘적 범위 지정(lexical scoping) 과정에서 변수가 어디에서 사용 가능한지 알기 위해 그 변수가 소스코드 내 어디에서 선언되었는지 고려한다는 것을 의미한다. 단어 "lexical"은 이런 사실을 나타낸다. 중첩된 함수는 외부 범위(scope)에서 선언한 변수에도 접근할 수 있다.

+ +

클로저(Closure)

+ +

이제 다음 예제를 보자:

+ +
function makeFunc() {
+  var name = "Mozilla";
+  function displayName() {
+    alert(name);
+  }
+  return displayName;
+}
+
+var myFunc = makeFunc();
+//myFunc변수에 displayName을 리턴함
+//유효범위의 어휘적 환경을 유지
+myFunc();
+//리턴된 displayName 함수를 실행(name 변수에 접근)
+ +

이 코드는 바로 전의 예제와 완전히 동일한 결과가 실행된다. 하지만 흥미로운 차이는 displayName()함수가 실행되기 전에 외부함수인 makeFunc()로부터 리턴되어 myFunc 변수에 저장된다는 것이다.

+ +

한 눈에 봐서는 이 코드가 여전히 작동하는 것이 직관적으로 보이지 않을 수 있다. 몇몇 프로그래밍 언어에서, 함수 안의 지역 변수들은 그 함수가 처리되는 동안에만 존재한다. makeFunc() 실행이 끝나면(displayName함수가 리턴되고 나면) name 변수에 더 이상 접근할 수 없게 될 것으로 예상하는 것이 일반적이다.

+ +

하지만 위의 예시와 자바스크립트의 경우는 다르다. 그 이유는 자바스크립트는 함수를 리턴하고, 리턴하는 함수가 클로저를 형성하기 때문이다. 클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다. 첫 번째 예시의 경우, myFuncmakeFunc이 실행될 때 생성된 displayName 함수의 인스턴스에 대한 참조다. displayName의 인스턴스는 변수 name 이 있는 어휘적 환경에 대한 참조를 유지한다. 이런 이유로 myFunc가 호출될 때 변수 name은 사용할 수 있는 상태로 남게 되고 "Mozilla" 가 alert 에 전달된다.

+ +

다음은 조금 더 흥미로운 예제인 makeAdder 함수이다:

+ +
function makeAdder(x) {
+  var y = 1;
+  return function(z) {
+    y = 100;
+    return x + y + z;
+  };
+}
+
+var add5 = makeAdder(5);
+var add10 = makeAdder(10);
+//클로저에 x와 y의 환경이 저장됨
+
+console.log(add5(2));  // 107 (x:5 + y:100 + z:2)
+console.log(add10(2)); // 112 (x:10 + y:100 + z:2)
+//함수 실행 시 클로저에 저장된 x, y값에 접근하여 값을 계산
+
+
+ +

이 예제에서 단일 인자 x를 받아서 새 함수를 반환하는 함수 makeAdder(x)를 정의했다. 반환되는 함수는 단일 인자 z를 받아서 x와 y와 z의 합을 반환한다.

+ +

본질적으로 makeAdder는 함수를 만들어내는 공장이다. 이는 makeAdder함수가 특정한 값을 인자로 가질 수 있는 함수들을 리턴한다는 것을 의미한다. 위의 예제에서 add5, add10 두 개의 새로운 함수들을 만들기 위해 makeAdder함수 공장을 사용했다. 하나는 매개변수 x에 5를 더하고 다른 하나는 매개변수 x에 10을 더한다.

+ +

add5add10은 둘 다 클로저이다. 이들은 같은 함수 본문 정의를 공유하지만 서로 다른 맥락(어휘)적 환경을 저장한다. 함수 실행 시 add5의 맥락적 환경에서 클로저 내부의 x는 5 이지만 add10의 맥락적 환경에서 x는 10이다. 또한 리턴되는 함수에서 초기값이 1로 할당된 y에 접근하여 y값을 100으로 변경한 것을 볼 수 있다. (물론 x값도 동일하게 변경 가능하다.) 이는 클로저가 리턴된 후에도 외부함수의 변수들에 접근 가능하다는 것을 보여주는 포인트이며 클로저에 단순히 값 형태로 전달되는 것이 아니라는 것을 의미한다.

+ +

실용적인 클로저

+ +

클로저는 어떤 데이터(어휘적 환경)와 그 데이터를 조작하는 함수를 연관시켜주기 때문에 유용하다. 이것은 객체가 어떤 데이터와(그 객체의 속성) 하나 혹은 그 이상의 메소드들을 연관시킨다는 점에서 객체지향 프로그래밍과 분명히 같은 맥락에 있다.

+ +

결론적으로 오직 하나의 메소드를 가지고 있는 객체를 일반적으로 사용하는 모든 곳에 클로저를 사용할 수 있다.

+ +

이렇게 할 수 있는 상황은 특히 웹에서 일반적이다. 프론트 엔드 자바스크립트에서 우리가 쓰는 많은 코드가 이벤트 기반이다. 우리는 몇 가지 동작을 정의한 다음 사용자에 의한 이벤트에(클릭 혹은 키 누르기 같은) 연결한다. 우리의 코드는 일반적으로 콜백으로 첨부된다: 이벤트에 응답하여 실행되는 단일 함수다.

+ +

예를 들면 페이지의 글자 크기를 조정하는 몇 개의 버튼을 추가한다고 가정하자. 이 작업을 수행하는 한 가지 방법은 body 요소의 font-size를 픽셀 단위로 지정하고 상대적인 em 단위를 사용하여 페이지의 다른 요소들의 (예: 헤더) 크기를 설정하는 것이다.

+ +
body {
+  font-family: Helvetica, Arial, sans-serif;
+  font-size: 12px;
+}
+
+h1 {
+  font-size: 1.5em;
+}
+
+h2 {
+  font-size: 1.2em;
+}
+
+ +

우리의 대화식 글자 크기 버튼들은 body 요소의 font-size 속성을 변경할 수 있고 이런 조정은 상대적 단위들 덕분에 페이지의 다른 요소에 의해 선택된다.

+ +

여기 자바스크립트 코드가 있다.

+ +
function makeSizer(size) {
+  return function() {
+    document.body.style.fontSize = size + 'px';
+  };
+}
+
+var size12 = makeSizer(12);
+var size14 = makeSizer(14);
+var size16 = makeSizer(16);
+
+ +

size12, size14, size16은 body 요소의 글자 크기를 각각 12, 14, 16 픽셀로 바꾸는 함수이다. 이 함수들을 아래처럼 버튼들에(이 경우에는 링크) 연결할 수 있다.

+ +
document.getElementById('size-12').onclick = size12;
+document.getElementById('size-14').onclick = size14;
+document.getElementById('size-16').onclick = size16;
+
+ +
<a href="#" id="size-12">12</a>
+<a href="#" id="size-14">14</a>
+<a href="#" id="size-16">16</a>
+
+ +

{{JSFiddleEmbed("https://jsfiddle.net/vnkuZ/","","200")}}

+ +

클로저를 이용해서 프라이빗 메소드 (private method) 흉내내기

+ +

자바와 같은 몇몇 언어들은 메소드를 프라이빗으로 선언할 수 있는 기능을 제공한다. 이는 같은 클래스 내부의 다른 메소드에서만 그 메소드들을 호출할 수 있다는 의미이다.

+ +

자바스크립트는 태생적으로는 이런 방법을 제공하지 않지만 클로저를 이용하여 프라이빗 메소드를 흉내내는 것이 가능하다. 프라이빗 메소드는 코드에 제한적인 접근만을 허용한다는 점 뿐만 아니라 전역 네임 스페이스를 관리하는 강력한 방법을 제공하여 불필요한 메소드가 공용 인터페이스를 혼란스럽게 만들지 않도록 한다.

+ +

아래 코드는 프라이빗 함수와 변수에 접근하는 퍼블릭 함수를 정의하기 위해 클로저를 사용하는 방법을 보여준다. 이렇게 클로저를 사용하는 것을 모듈 패턴이라 한다.

+ +
var counter = (function() {
+  var privateCounter = 0;
+  function changeBy(val) {
+    privateCounter += val;
+  }
+  return {
+    increment: function() {
+      changeBy(1);
+    },
+    decrement: function() {
+      changeBy(-1);
+    },
+    value: function() {
+      return privateCounter;
+    }
+  };
+})();
+
+console.log(counter.value()); // logs 0
+counter.increment();
+counter.increment();
+console.log(counter.value()); // logs 2
+counter.decrement();
+console.log(counter.value()); // logs 1
+
+ +

이전 예제에서 각 클로저들이 고유한 문법적 환경을 가졌지만 여기서 우리는 counter.increment, counter.decrement, counter.value 세 함수에 의해 공유되는 하나의 어휘적 환경을 만든다.

+ +

공유되는 어휘적 환경은 실행되는 익명 함수 안에서 만들어진다. 이 익명 함수는 정의되는 즉시 실행된다. 이 어휘적 환경은 두 개의 프라이빗 아이템을 포함한다. 하나는 privateCounter라는 변수이고 나머지 하나는 changeBy라는 함수이다. 둘 다 익명 함수 외부에서 접근될 수 없다. 대신에 익명 래퍼에서 반환된 세 개의 퍼블릭 함수를 통해서만 접근되어야만 한다.

+ +

위의 세 가지 퍼블릭 함수는 같은 환경을 공유하는 클로저다. 자바스크립트의 어휘적 유효 범위 덕분에 세 함수 각각 privateCounter 변수와 changeBy 함수에 접근할 수 있다.

+ +

카운터를 생성하는 익명 함수를 정의하고 그 함수를 즉시 호출하고 결과를 counter 변수에 할당하는 것을 알아차렸을 것이다. 이 함수를 별도의 변수 makeCounter 저장하고 이 변수를 이용해 여러 개의 카운터를 만들 수 있다.

+ +
var makeCounter = function() {
+  var privateCounter = 0;
+  function changeBy(val) {
+    privateCounter += val;
+  }
+  return {
+    increment: function() {
+      changeBy(1);
+    },
+    decrement: function() {
+      changeBy(-1);
+    },
+    value: function() {
+      return privateCounter;
+    }
+  }
+};
+
+var counter1 = makeCounter();
+var counter2 = makeCounter();
+alert(counter1.value()); /* 0 */
+counter1.increment();
+counter1.increment();
+alert(counter1.value()); /* 2 */
+counter1.decrement();
+alert(counter1.value()); /* 1 */
+alert(counter2.value()); /* 0 */
+
+ +

두 개의 카운터가 어떻게 다른 카운터와 독립성을 유지하는지 주목해보자. 각 클로저는 그들 고유의 클로저를 통한 privateCounter 변수의 다른 버전을 참조한다. 각 카운터가 호출될 때마다; 하나의 클로저에서 변수 값을 변경해도 다른 클로저의 값에는 영향을 주지 않는다.

+ +

이런 방식으로 클로저를 사용하여 객체지향 프로그래밍의 정보 은닉과 캡슐화 같은 이점들을 얻을 수 있다.

+ +

클로저 스코프 체인

+ +

모든 클로저에는 세가지 스코프(범위)가 있다:-

+ + + +

따라서, 우리는 클로저에 대해 세가지 범위 모두 접근할 수 있지만, 중첩된 내부 함수가 있는 경우 종종 실수를 저지른다. 아래 예제를 확인해보자:

+ +
// 전역 범위 (global scope)
+var e = 10;
+function sum(a){
+  return function(b){
+    return function(c){
+      // 외부 함수 범위 (outer functions scope)
+      return function(d){
+        // 지역 범위 (local scope)
+        return a + b + c + d + e;
+      }
+    }
+  }
+}
+
+console.log(sum(1)(2)(3)(4)); // log 20
+
+// 익명 함수 없이 작성할 수도 있다.
+
+// 전역 범위 (global scope)
+var e = 10;
+function sum(a){
+  return function sum2(b){
+    return function sum3(c){
+      // 외부 함수 범위 (outer functions scope)
+      return function sum4(d){
+        // 지역 범위 (local scope)
+        return a + b + c + d + e;
+      }
+    }
+  }
+}
+
+var s = sum(1);
+var s1 = s(2);
+var s2 = s1(3);
+var s3 = s2(4);
+console.log(s3) //log 20
+ +

위의 예제를 보면 일련의 중첩된 함수들을 확인할 수 있다. 이 함수들은 전부 외부 함수의 스코프에 접근할 수 있다. 그런데 문제는 즉각적인 외부 함수의 스코프만을 추측한다는 것이다. 이 문맥에서는 모든 클로저가 선언된 외부 함수의 스코프에 접근한다라고 말할 수 있다.

+ +

루프에서 클로저 생성하기: 일반적인 실수

+ +

ECMAScript 2015의 let 키워드 소개 전에는 클로저와 관련된 일반적인 문제는 루프 안에서 클로저가 생성되었을 때 발생한다.다음 예제를 보자.

+ +
<p id="help">Helpful notes will appear here</p>
+<p>E-mail: <input type="text" id="email" name="email"></p>
+<p>Name: <input type="text" id="name" name="name"></p>
+<p>Age: <input type="text" id="age" name="age"></p>
+
+ +
function showHelp(help) {
+  document.getElementById('help').innerHTML = help;
+}
+
+function setupHelp() {
+  var helpText = [
+      {'id': 'email', 'help': 'Your e-mail address'},
+      {'id': 'name', 'help': 'Your full name'},
+      {'id': 'age', 'help': 'Your age (you must be over 16)'}
+    ];
+
+  for (var i = 0; i < helpText.length; i++) {
+    var item = helpText[i];
+    document.getElementById(item.id).onfocus = function() {
+      showHelp(item.help);
+    }
+  }
+}
+
+setupHelp();
+
+ +

{{JSFiddleEmbed("https://jsfiddle.net/v7gjv/", "", 200)}}

+ +

helpText 배열은 세 개의 도움말 힌트를 정의한다. 각 도움말은 문서의 입력 필드의 ID와 연관된다. 루프를 돌면서 각 입력 필드 ID에 해당하는 엘리먼트의 onfocus 이벤트에 관련된 도움말을 보여주는 메소드에 연결한다.

+ +

이 코드를 사용하면 제대로 동작하지 않는 것을 알게 된다. 어떤 필드에 포커스를 주더라도 나이에 관한 도움말이 표시된다.

+ +

onfocus 이벤트에 연결된 함수가 클로저이기 때문이다. 이 클로저는 함수 정의와 setupHelp 함수 범위에서 캡처된 환경으로 구성된다. 루프에서 세 개의 클로저가 만들어졌지만 각 클로저는 값이 변하는 변수가 (item.help) 있는 같은 단일 환경을 공유한다. onfocus 콜백이 실행될 때 콜백의 환경에서 item 변수는 (세개의 클로저가 공유한다) helpText 리스트의 마지막 요소를 가리키고 있을 것이다.

+ +

이 경우 한 가지 해결책은 더 많은 클로저를 사용하는 것이다: 특히 앞에서 설명한 함수 팩토리를 사용하는 것이다.

+ +
function showHelp(help) {
+  document.getElementById('help').innerHTML = help;
+}
+
+function makeHelpCallback(help) {
+  return function() {
+    showHelp(help);
+  };
+}
+
+function setupHelp() {
+  var helpText = [
+      {'id': 'email', 'help': 'Your e-mail address'},
+      {'id': 'name', 'help': 'Your full name'},
+      {'id': 'age', 'help': 'Your age (you must be over 16)'}
+    ];
+
+  for (var i = 0; i < helpText.length; i++) {
+    var item = helpText[i];
+    document.getElementById(item.id).onfocus = makeHelpCallback(item.help);
+  }
+}
+
+setupHelp();
+
+ +

{{JSFiddleEmbed("https://jsfiddle.net/v7gjv/1/", "", 300)}}

+ +

이것은 예상대로 동작한다. 모두 단일 환경을 공유하는 콜백대신, makeHelpCallback 함수는 각각의 콜백에 새로운 어휘적 환경을 생성한다. 여기서 help는 helpText 배열의 해당 문자열을 나타낸다.

+ +

익명 클로저를 사용하여 위 코드를 작성하는 또 다른 방법은 다음과 같다.

+ +
function showHelp(help) {
+  document.getElementById('help').innerHTML = help;
+}
+
+function setupHelp() {
+  var helpText = [
+      {'id': 'email', 'help': 'Your e-mail address'},
+      {'id': 'name', 'help': 'Your full name'},
+      {'id': 'age', 'help': 'Your age (you must be over 16)'}
+    ];
+
+  for (var i = 0; i < helpText.length; i++) {
+    (function() {
+       var item = helpText[i];
+       document.getElementById(item.id).onfocus = function() {
+         showHelp(item.help);
+       }
+    })(); // Immediate event listener attachment with the current value of item (preserved until iteration).
+  }
+}
+
+setupHelp();
+ +

더 많은 클로저를 사용하는 것이 싫다면 ES2015의 let 키워드를 사용할 수 있다.

+ +
function showHelp(help) {
+  document.getElementById('help').innerHTML = help;
+}
+
+function setupHelp() {
+  var helpText = [
+      {'id': 'email', 'help': 'Your e-mail address'},
+      {'id': 'name', 'help': 'Your full name'},
+      {'id': 'age', 'help': 'Your age (you must be over 16)'}
+    ];
+
+  for (var i = 0; i < helpText.length; i++) {
+    let item = helpText[i];
+    document.getElementById(item.id).onfocus = function() {
+      showHelp(item.help);
+    }
+  }
+}
+
+setupHelp();
+ +

위의 경우 var 대신 let을 사용하여 모든 클로저가 블록 범위 변수를 바인딩할 것이므로 추가적인 클로저를 사용하지 않아도 완벽하게 동작할 것이다.

+ +

성능 관련 고려 사항

+ +

특정 작업에 클로저가 필요하지 않는데 다른 함수 내에서 함수를 불필요하게 작성하는 것은 현명하지 않다. 이것은 처리 속도와 메모리 소비 측면에서 스크립트 성능에 부정적인 영향을 미칠 것이다.

+ +

예를 들어, 새로운 객체/클래스를 생성 할 때, 메소드는 일반적으로 객체 생성자에 정의되기보다는 객체의 프로토타입에 연결되어야 한다. 그 이유는 생성자가 호출 될 때마다 메서드가 다시 할당되기 때문이다 (즉, 모든 개체가 생성 될 때마다).

+ +

비실용적이지만 시범적인 다음 예를 고려하라:

+ +
function MyObject(name, message) {
+  this.name = name.toString();
+  this.message = message.toString();
+  this.getName = function() {
+    return this.name;
+  };
+
+  this.getMessage = function() {
+    return this.message;
+  };
+}
+
+ +

앞의 코드는 클로저의 이점을 이용하지 않음으로 다음과 같이 다시 쓸 수 있다.

+ +
function MyObject(name, message) {
+  this.name = name.toString();
+  this.message = message.toString();
+}
+MyObject.prototype = {
+  getName: function() {
+    return this.name;
+  },
+  getMessage: function() {
+    return this.message;
+  }
+};
+
+ +

그러나 프로토타입을 다시 정의하는 것은 권장되지 않음으로 기존 프로토타입에 추가하는 다음 예제가 더 좋다.

+ +
function MyObject(name, message) {
+  this.name = name.toString();
+  this.message = message.toString();
+}
+MyObject.prototype.getName = function() {
+  return this.name;
+};
+MyObject.prototype.getMessage = function() {
+  return this.message;
+};
+
+ +

위의 코드는 같은 결과를 가진 더 깨끗한 방법으로 작성할 수도 있다:

+ +
function MyObject(name, message) {
+    this.name = name.toString();
+    this.message = message.toString();
+}
+(function() {
+    this.getName = function() {
+        return this.name;
+    };
+    this.getMessage = function() {
+        return this.message;
+    };
+}).call(MyObject.prototype);
+
+ +

앞의 두 가지 예제에서 상속된 프로토타입은 모든 객체에서 공유될 수 있으며 메소드 정의는 모든 객체 생성시 발생할 필요가 없다. 객체 모델의 세부 사항을 참고하라.

diff --git a/files/ko/web/javascript/guide/control_flow_and_error_handling/index.html b/files/ko/web/javascript/guide/control_flow_and_error_handling/index.html new file mode 100644 index 0000000000..fa007d6997 --- /dev/null +++ b/files/ko/web/javascript/guide/control_flow_and_error_handling/index.html @@ -0,0 +1,433 @@ +--- +title: 제어 흐름과 에러 처리 +slug: Web/JavaScript/Guide/Control_flow_and_error_handling +tags: + - 가이드 + - 자바 스크립트 + - 초보자 +translation_of: Web/JavaScript/Guide/Control_flow_and_error_handling +--- +

{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}

+ +

JavaScript는 어플리케이션 상의 상호작용을 통합하는데 사용할 수 있는 일련의 문법, 특히 제어흐름 문을 지원합니다. 이 장에서는 이러한 문법의 개요를 제공합니다.

+ +

JavaScript reference는 이 장의 문법에 대한 철저하고 자세한 내용은 포함하고 있습니다. 세미콜론 (;) 은 JavaScript 코드 상에서 문장을 나누는데 사용됩니다. 

+ +

 JavaScript 표현식도 문법입니다. 표현식에 대한 자세한 내용은 Expressions and operators를 참조하세요.

+ +

Block 문

+ +

Block 문은 코드를 묶는 가장 기본적인 문법입니다. Block 문은 중괄호 ( { } )에 의해 범위가 결정됩니다.

+ +
{
+  statement_1;
+  statement_2;
+  .
+  .
+  .
+  statement_n;
+}
+
+ +

예시

+ +

Block 문은 일반적으로 제어 흐름 문(if, for, while)과 함께  사용됩니다.

+ +
while (x < 10) {
+  x++;
+}
+
+ +

여기서, { x++; }는 block 문입니다.

+ +

중요: ECMAScript2015 이전의 JavaScript는 블록 범위를 가지고 있지 않습니다. Block 내에서 선언한 변수는 블록을 넘어 변수가 위치한 함수 혹은 스크립트에 영향을 끼치게 됩니다.즉, block 문은 변수의 범위를 정의하지 않습니다. 자바스크립트의 "독립" block 은 C 혹은 Java의 그것과 완전히 다른 결과를 가집니다. 예를 들어:

+ +
var x = 1;
+{
+  var x = 2;
+}
+console.log(x); // outputs 2
+
+ +

블록 내에 var x 문이 블록 전에 var x 문과 같은 범위에 있기 때문에 2를 출력합니다. C 나 Java에서 해당 코드는 1을 출력합니다.

+ +

ECMAScript2015부터, let 그리고 const 변수 선언으로 변수의 블록 범위를 제한할 수 있습니다. 자세한 내용은 {{jsxref("Statements/let", "let")}}와 {{jsxref("Statements/const", "const")}} 참조 페이지를 참조하세요.

+ +

조건문

+ +

조건문은 특정 조건이 참인 경우에 실행하는 명령의 집합입니다. JavaScript는 두 가지 조건문을 지원합니다: if...else and switch.

+ +

if...else

+ +

특정 조건이 참인 경우 문장을 실행하기 위해 if 문을 사용합니다. 또한 선택적으로 조건이 거짓인 경우 문장을 실행하기 위해서는 else 절을 사용합니다. 다음과 같은 경우 :

+ +
if (condition) {
+  statement_1;
+} else {
+  statement_2;
+}
+ +

조건의 참과 거짓에 따라 수행문이 정해질 때 사용할 수 있습니다.. 무엇이 참과 거짓으로 평가되는 지에 대한 설명은 Boolean을 참조하세요. 조건이 참으로 평가되면, statement_1은 실행됩니다. 그렇지 않으면, statement_2가 실행됩니다. statement_1과 statement_2는 if문이 더 중첩 된 경우를 포함한 문장이 될 수도 있습니다.

+ +

다음과 같은 순서대로 나열된 여러 조건을 가지고 else if를 사용하여 문장을 복잡하게 할 수 있습니다:

+ +
if (condition_1) {
+  statement_1;
+} else if (condition_2) {
+  statement_2;
+} else if (condition_n) {
+  statement_n;
+} else {
+  statement_last;
+}
+
+ +

여러 줄의 문장을 실행하기 위해, block 문({ ... })안에 코드들을 작성합니다. 일반적으로, 특히 코드가 중첩할 때, 항상 block 문을 사용하는 것이 좋은 습관입니다:

+ +
if (condition) {
+  statement_1_runs_if_condition_is_true;
+  statement_2_runs_if_condition_is_true;
+} else {
+  statement_3_runs_if_condition_is_false;
+  statement_4_runs_if_condition_is_false;
+}
+
+ +
조건문 안에서의 변수값 할당은 사용하지 않는 것이 좋습니다. 왜냐하면 그것은 코드를 자세히 보지 않는 경우, 동등비교연산자로 오해할 수 있기 때문입니다. 예를 들어, 다음 코드는 사용하지 마세요.
+ +
+

if (x = y) {
+      /* statements here */
+ }

+
+ +

만약 조건식에 할당을 사용해야하는 경우, 일반적인 관행은 할당 주위에 추가 괄호를 넣는 것입니다. 예를 들어:

+ +
if ((x = y)) {
+  /* statements here */
+}
+
+ +

거짓으로 취급하는 값

+ +

다음과 같은 값은 거짓으로 평가됩니다:

+ + + +

조건문에 전달되었을 때 모든 개체를 포함하여 다른 모든 값은 참으로 평가합니다.

+ +

{{jsxref("Boolean")}} 개체의 참과 거짓 값으로 원시 boolean 값 true와 false를 혼동하지 마세요. 예를 들어:

+ +
var b = new Boolean(false);
+if (b) // this condition evaluates to true
+
+ +

예시

+ +

다음 예에서, 텍스트 개체의 문자 수가 3인 경우 함수 checkDatatrue를 반환합니다; 그렇지 않으면 경고를 표시하고 false를 반환합니다.

+ +
function checkData() {
+  if (document.form1.threeChar.value.length == 3) {
+    return true;
+  } else {
+    alert("Enter exactly three characters. " +
+    document.form1.threeChar.value + " is not valid.");
+    return false;
+  }
+}
+
+ +

switch

+ +

Switch문은 프로그램이 표현식을 평가하고  값을 조건과 비교합니다. 만약 값이 일치한다면,  프로그램은 각 조건의 하위 문장을 실행합니다. Switch문은 아래와 같이 사용합니다.:

+ +
switch (expression) {
+  case label_1:
+    statements_1
+    [break;]
+  case label_2:
+    statements_2
+    [break;]
+    ...
+  default:
+    statements_def
+    [break;]
+}
+
+ +

프로그램은 주어진 값과 일치하는 case 라벨을 찾습니다. 그리고나서 관련된 구문을 수행합니다. 만약 매치되는 라벨이 없다면 그 default 절을 찾습니다. 찾게되면, 관련된 구문을 수행합니다.  default 절을 못 찾게 된다면 프로그램의 switch문은 종료됩니다. 관례상, default 절은 마지막절입니다. 하지만 꼭 그럴 필요는 없습니다.

+ +

한번 일치된 문장이 수행되고 switch문을 따라서 계속 수행한다면 각각의 조건절로 연결된 선택적인 break문은 그 프로그램이 switch문을 벗어나게 합니다. 만약 break문이 생략된다면, 그 프로그램은 switch문안에서 다음 문장을 계속 수행합니다.

+ +

예시

+ +

아래 예에서, 만약 "fruittype"가 "Bananas"라면, 프로그램은 case "Bananas"와 값이 일치합니다. 그리고 관련된 문장을 실행합니다. 프로그램의 switch문은 break문을 만났을 때 종료됩니다. 그리고 switch문 다음에 나오는 문장을 실행합니다. 만약 break문이 생략되면, 조건문 "Cherries" 와 관련된 문장도 실행됩니다.

+ +
switch (fruittype) {
+  case "Oranges":
+    console.log("Oranges are $0.59 a pound.");
+    break;
+  case "Apples":
+    console.log("Apples are $0.32 a pound.");
+    break;
+  case "Bananas":
+    console.log("Bananas are $0.48 a pound.");
+    break;
+  case "Cherries":
+    console.log("Cherries are $3.00 a pound.");
+    break;
+  case "Mangoes":
+    console.log("Mangoes are $0.56 a pound.");
+    break;
+  case "Papayas":
+    console.log("Mangoes and papayas are $2.79 a pound.");
+    break;
+  default:
+   console.log("Sorry, we are out of " + fruittype + ".");
+}
+console.log("Is there anything else you'd like?");
+ +

 

+ +

예외처리문

+ +

여러분은 throw문을 사용하는 예외들을 사용 할 수 있고 try...catch문을 사용하는 예외들 또한 다룰 수 있습니다.

+ + + +

예외 유형

+ +

대부분 자바스크립트안에서 사용될 수 있습니다. 그럼에도 불구하고, 반드시 사용되는 객체들이 같은 것으로 만들어 지지는 않습니다. 이것들은 에러같은 숫자들이나 문자열들을 사용하는데 흔한 일이지만 특히 이런 목적으로 만들어진 예외 유형중 하나를 사용하는데 더 효과적입니다:

+ + + +

throw 문

+ +

예외를 사용할 때 throw 문을 사용합니다. 여러분이 예외를 사용할 때, 사용되는 값을 포함하는 표현을 명시해야합니다:

+ +
throw expression;
+
+ +

여러분은 구체적 유형의 표현이 아니라도 어떤 표현이든지 사용할 것입니다. 다음 코드는 다양한 유형중의 여러 예외들을 사용합니다:

+ +
throw "Error2";   // String type
+throw 42;         // Number type
+throw true;       // Boolean type
+throw {toString: function() { return "I'm an object!"; } };
+
+ +
Note: 여러분은  예외를 사용할때 객체를 명시할 수 있습니다. 그리고나서  catch 문안에서 객체의 특성들을 참조 할 수 있습니다. 다음 예시는 myUserException of type UserException객체를 만듭니다 그리고 throw문에서 사용합니다.
+ +
// Create an object type UserException
+function UserException (message){
+  this.message=message;
+  this.name="UserException";
+}
+
+// Make the exception convert to a pretty string when used as a string
+// (e.g. by the error console)
+UserException.prototype.toString = function () {
+  return this.name + ': "' + this.message + '"';
+}
+
+// Create an instance of the object type and throw it
+throw new UserException("Value too high");
+ +

try...catch 문법

+ +

try...catch 문법은 시도할 블록을 표시하고, 예외가 발생하였을때, 하나 이상의 반응을 명시합니다. 만약 예외가 발생하였을때, try...catch 문법은 예외를 잡아냅니다.

+ +

try...catch 문법은 하나 이상의 문장을 포함한 try 블록과, try 블록 에서 예외가 발생하였을때, 어떤 것을 할 것인지 명시된 문장을 포함한 0개 이상의 catch 블록으로 구성됩니다. try 블록이 성공하길 원하고, try 블록이 성공하지 않았다면, 제어를 catch 블록으로 넘기고 싶을 것입니다. 만약 try 블록(또는 try 블록에서 호출하는 함수) 의 문장이 예외를 발생시켰을때, 제어는 즉시 catch 블록으로 이동합니다. 만약 try 블록에서 예외가 발생하지 않았을 때, catch 블록을 건너뜁니다. finally 블록은 try 블록과 catch 블록의 시행이 끝나고 try...catch 문법 다음의 문장이 시행 되기 전에 시행됩니다.

+ +

다음의 예제는 try...catch 문법을 사용합니다. 예제는 함수에 전해진 값을 토대로 달의 이름을 검색하는 함수를 호출합니다. 만약 값이 달 숫자값(1-12) 에 일치하지 않으면,"InvalidMonthNo" 라는 값과 함께 예외가 발생하고 catch 블록의 문장들이 monthName 변수를 unknown 값으로 설정합니다.

+ +
function getMonthName (mo) {
+  mo = mo-1; // Adjust month number for array index (1=Jan, 12=Dec)
+  var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul",
+                "Aug","Sep","Oct","Nov","Dec"];
+  if (months[mo] != null) {
+    return months[mo];
+  } else {
+    throw "InvalidMonthNo"; //throw keyword is used here
+  }
+}
+
+try { // statements to try
+  monthName = getMonthName(myMonth); // function could throw exception
+}
+catch (e) {
+  monthName = "unknown";
+  logMyErrors(e); // pass exception object to error handler
+}
+
+ +

catch 블록

+ +

try 블록에서 발생할수 있는 모든 예외를 처리하기 위해 catch 블록을 사용할 수 있습니다.

+ +
catch (catchID) {
+  statements
+}
+
+ +

catch 블록은 throw문장에 의해 명시된 값을 가지고 있는 식별자(앞 구문의 catchID)를 명시합니다; 이 식별자를 발생된 예외에 대한 정보를 얻기 위하여 사용할 수 있습니다. 자바스크립트는 catch 블록에 진입했을때 식별자를 생성합니다; 식별자는 catch 블록에 있는 동안만 유지됩니다; catch 블록의 시행이 끝난 후, 식별자는 더이상 사용하실 수 없습니다.

+ +

예를 들어, 다음의 코드는 예외를 발생시킵니다. 예외가 발생하였을때, 제어는 catch 블록으로 넘어갑니다.

+ +
try {
+  throw "myException" // generates an exception
+}
+catch (e) {
+  // statements to handle any exceptions
+  logMyErrors(e) // pass exception object to error handler
+}
+
+ +

finally 블록

+ +

finally 블록은 try 블록과 catch 블록이 시행되고, try...catch 문법 다음 문장이 시행되기 전에 시행되는 문장들을 포함하고 있습니다. finally 블록은 예외가 발생하든 안하든 수행됩니다. 만약 예외가 발생하였을때, finally 블록 안의 문장들은 어떤 catch 블록도 예외를 처리하지 않더라도 시행됩니다.

+ +

finally 블록을 예외가 발생하였을때 여러분의 스크립트가 우아하게 실패하도록 만들기 위하여 사용할 수 있습니다. 예를 들어, 여러분의 스크립트가 묶어둔 자원들을 풀어줄 필요가 있습니다. 다음의 예제는 파일을 열고, 파일을 사용하는 문장(서버 측 자바스크립트는 파일에 접근하는 것을 허가합니다)을 시행합니다. 만약 파일이 열린 동안 예외가 발생했다면, finally 블록은 스크립트가 실패하기 전에 파일을 닫아줍니다.

+ +
openMyFile();
+try {
+  writeMyFile(theData); //This may throw a error
+} catch(e) {
+  handleError(e); // If we got a error we handle it
+} finally {
+  closeMyFile(); // always close the resource
+}
+
+ +

만약 finally 블록이 값을 반환하였을 경우, try 블록과 catch블록의 return 문장과 상관없이 전체 try-catch-finally 생산물의 반환값이 됩니다:

+ +
function f() {
+  try {
+    console.log(0);
+    throw "bogus";
+  } catch(e) {
+    console.log(1);
+    return true; // this return statement is suspended
+                 // until finally block has completed
+    console.log(2); // not reachable
+  } finally {
+    console.log(3);
+    return false; // overwrites the previous "return"
+    console.log(4); // not reachable
+  }
+  // "return false" is executed now
+  console.log(5); // not reachable
+}
+f(); // alerts 0, 1, 3; returns false
+
+ +

finally 블록에 의한 반환값 덮어쓰기는 예외가 발생하거나 다시 예외가 발생했을때 또한 적용됩니다.

+ +
function f() {
+  try {
+    throw "bogus";
+  } catch(e) {
+    console.log('caught inner "bogus"');
+    throw e; // this throw statement is suspended until
+             // finally block has completed
+  } finally {
+    return false; // overwrites the previous "throw"
+  }
+  // "return false" is executed now
+}
+
+try {
+  f();
+} catch(e) {
+  // this is never reached because the throw inside
+  // the catch is overwritten
+  // by the return in finally
+  console.log('caught outer "bogus"');
+}
+
+// OUTPUT
+// caught inner "bogus"
+ +

try...catch 문법 중첩하기

+ +

 

+ +

하나 이상의 try ... catch 문을 중첩 할 수 있습니다. 중첩된 안쪽 try ... catch 문에 catch 블록이 없으면 finally 블록이 있어야하고 try ... catch 문의 catch 블록에 일치하는 항목이 있는지 확인해야합니다. 자세한 내용은 try...catch 참조 페이지의 nested try-blocks을 참조하십시오.

+ +

Error 객체를 도구화 하기

+ +

오류의 종류에 따라, 더 정제된 메세지를 얻기 위하여 'name'속성과 'message'속성을 사용할수도 있습니다. 'name'속성은 오류의 일반 클래스(e.g., 'DOMException' 또는 'Error')를 제공하고, 'message' 속성이 error 객체를 문자열로 바꿀수 있는 것 보다 더 간결한 메세지를 제공합니다.

+ +

만약 이 속성들에 대하여 이득을 얻기 위해(여러분의 catch 블록이 시스템의 예외와 여러분의 예외를 구분하지 않을 때와 같은 것) 여러분만의 예외를 발생시킨다면, 여러분은 Error 생성자를 사용할 수 있습니다. 예를 들어:

+ +
function doSomethingErrorProne () {
+  if (ourCodeMakesAMistake()) {
+    throw (new Error('The message'));
+  } else {
+    doSomethingToGetAJavascriptError();
+  }
+}
+....
+try {
+  doSomethingErrorProne();
+}
+catch (e) {
+  console.log(e.name); // logs 'Error'
+  console.log(e.message); // logs 'The message' or a JavaScript error message)
+}
+ +

Promises

+ +

ECMAScript2015를 시작하면서, 자바스크립트는 지연된 흐름과 비동기식의 연산을 제어할 수 있게 하는 {{jsxref("Promise")}} 객체에 대한 지원을 얻게 되었습니다.

+ +

Promise 는 다음의 상태중 하나입니다:

+ + + +

+ +

XHR 를 통해 이미지 불러오기

+ +

이미지를 불러오기 위해 PromiseXMLHttpRequest 를 사용한 간단한 예제는 MDN GitHub promise-test repository 에 있습니다. 이 예제 가 동작하는 것을 보실 수 있습니다. 각 단계는 설명되어있고 Promise 와 XHR 구조를 친밀하게 이해할수 있게 합니다. 여기 Promise 흐름을 보여줘서 아이디어를 얻을 수 있는 설명되지 않은 버전이 있습니다:

+ +
function imgLoad(url) {
+  return new Promise(function(resolve, reject) {
+    var request = new XMLHttpRequest();
+    request.open('GET', url);
+    request.responseType = 'blob';
+    request.onload = function() {
+      if (request.status === 200) {
+        resolve(request.response);
+      } else {
+        reject(Error('Image didn\'t load successfully; error code:'
+                     + request.statusText));
+      }
+    };
+    request.onerror = function() {
+      reject(Error('There was a network error.'));
+    };
+    request.send();
+  });
+}
+ +

더 자세한 정보를 얻기 위해선, {{jsxref("Promise")}} 참고 페이지를 보세요.

+ +
{{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}
diff --git a/files/ko/web/javascript/guide/expressions_and_operators/index.html b/files/ko/web/javascript/guide/expressions_and_operators/index.html new file mode 100644 index 0000000000..f5e711304f --- /dev/null +++ b/files/ko/web/javascript/guide/expressions_and_operators/index.html @@ -0,0 +1,926 @@ +--- +title: 표현식과 연산자 +slug: Web/JavaScript/Guide/Expressions_and_Operators +tags: + - Beginner + - Expressions + - Guide + - JavaScript + - Operators + - 'l10n:priority' + - 연산자 +translation_of: Web/JavaScript/Guide/Expressions_and_Operators +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Functions", "Web/JavaScript/Guide/Numbers_and_dates")}}
+ +

이 장은 JavaScript의 표현식과 할당, 비교, 산술, 비트 계산, 논리, 문자열, 삼항 등 여러 가지 연산자를 설명합니다.

+ +

연산자와 표현식의 완전하고 구체적인 목록도 참고서에서 확인할 수 있습니다.

+ +

연산자

+ +

JavaScript는 다음과 같은 형태의 연산자가 있습니다. 이 절은 연산자에 대하여 설명하고, 연산자 우선순위에 관한 정보를 포함하고 있습니다.

+ + + +

JavaScript는 이항 연산자와 단항연산자, 조건연산자인 단 하나 존재하는 삼항 연산자를 가지고 있습니다. 이항 연산자는 하나는 좌변에 다른 하나는 우변에 두개의 피연산자가 필요합니다:

+ +
피연산자1 연산자 피연산자2
+
+ +

예를 들면 3+4 또는 x*y와 같습니다.

+ +

단항 연산자는 연산자 뒤에든 앞에든 하나의 피연산자를 필요로 합니다.:

+ +
연산자 피연산자
+
+ +

또는

+ +
피연산자 연산자
+
+ +

x++ 또는 ++x를 예시로 들 수 있습니다.

+ +

할당 연산자

+ +

할당 연산자는 오른쪽 피연산자의 값을 왼쪽 피연산자에 할당합니다. 기본적인 할당 연산자는 오른쪽의 피연산자 값을 왼쪽 피연산자 값에 할당하는 등호(=) 입니다. 즉 x = yy 값을 x에 할당합니다.

+ +

다음의 표에 나열된 연산의 약칭인 복합 할당 연산자도 존재합니다:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
복합 할당 연산자
이름복합 할당 연산자
할당x = yx = y
덧셈 할당x += yx = x + y
뺄셈 할당x -= yx = x - y
곱셈 할당x *= yx = x * y
나눗셈 할당x /= yx = x / y
나머지 연산 할당x %= yx = x % y
지수 연산 할당 {{experimental_inline}}x **= yx = x ** y
왼쪽 이동 연산 할당x <<= yx = x << y
오른쪽 이동 연산 할당x >>= yx = x >> y
부호 없는 오른쪽 이동 연산 할당x >>>= yx = x >>> y
비트 AND 할당x &= yx = x & y
비트 XOR 할당x ^= yx = x ^ y
비트 OR 할당x |= yx = x | y
+ +

구조 분해

+ +

복잡한 할당 연산에서, 구조 분해 할당 구문은 배열이나 객체의 구조를 반영하여 배열이나 객체에서 데이터를 추출할 수 있게 해주는 JavaScript 표현식입니다.

+ +
var foo = ['one', 'two', 'three'];
+
+// 구조 분해를 활용하지 않은 경우
+var one   = foo[0];
+var two   = foo[1];
+var three = foo[2];
+
+// 구조 분해를 활용한 경우
+var [one, two, three] = foo;
+ +

비교 연산자

+ +

비교 연산자는 피연산자들을 비교하고 비교에 따라 논리 값을 반환합니다. 피연산자들은 숫자, 문자열, 논리형, 객체 를 사용할 수 있습니다. 문자열은 유니코드 값을 사용하여 표준 사전순서를 기반으로 비교합니다. 만약 두 피연산자가 다른 형태일 경우, JavaScript는 대부분 비교를 위해 피연산자를 적절한 타입으로 변환합니다. 이런 행동은 보통 숫자로 피연산자를 숫자로 비교하는 형태로 나타납니다. 형태를 바꾸기의 유일한 예외는 엄격한 비교를 수행하는 ===!== 연산이 관련되는 경우입니다. 이런 연산자는 비교를 위해 피연산자의 형태를 적절히 바꾸려고 시도하지 않습니다. 다음 표는 샘플 코드를 통해 비교 연산자에 대하여 설명합니다:

+ +
var var1 = 3;
+var var2 = 4;
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
비교 연산자
연산자설명참을 반환하는 예제
동등 (==)피연산자들이 같으면 참을 반환합니다.3 == var1 +

"3" == var1

+ 3 == '3'
부등 (!=)피연산자들이 다르면 참을 반환합니다.var1 != 4
+ var2 != "3"
일치 (===)피연산자들이 같고 피연산자들의 같은 형태인 경우 참을 반환합니다. {{jsxref("Object.is")}} 와 JavaScript에서의 같음을 참고하세요.3 === var1
불일치 (!==)피연산자들이 다르거나 형태가 다른 경우 참을 반환합니다.var1 !== "3"
+ 3 !== '3'
~보다 큰 (>)좌변의 피연산자 보다 우변의 피연산자가 크면 참을 반환합니다.var2 > var1
+ "12" > 2
~보다 크거나 같음 (>=)좌변의 피연산자 보다 우변의 피연산자가 크거나 같으면 참을 반환합니다.var2 >= var1
+ var1 >= 3
~보다 작음 (<)좌변의 피연산자 보다 우변의 피연산자가 작으면 참을 반환합니다.var1 < var2
+ "2" < 12
~보다 작거나 같음 (<=)좌변의 피연산자 보다 우변의 피연산자가 작거나 같으면 참을 반환합니다. +

var1 <= var2
+ var2 <= 5

+
+ +
+

참고: (=>) 은 연산자가 아니고, 화살표 함수(Arrow functions)를 나타내는 기호입니다.

+
+ +

산술 연산자

+ +

산술 연산자는 숫자값(리터럴 또는 변수)을 피연산자로 갖고, 하나의 숫자 값을 반환합니다. 기본적인 산술 연산자는 덧셈(+), 뺄셈 (-), 곱셈 (*), 나눗셈 (/)입니다. 이 연산자들은 대부분의 다른 프로그래밍 언어들이 부동소수점 값을 연산하는것처럼 동작합니다. (0 으로 나누는 것은 {{jsxref("Infinity")}} 을 발생시키는 것을 기억하세요) 예를 들면:

+ +
1 / 2; // 0.5
+1 / 2 == 1.0 / 2.0; // this is true
+
+ +

또한, 표준 산술 연산자 (+, -, *, /) 에 대해 JavaScript는 다음의 표에 나와 있는 산술 연산자를 제공합니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
산술 연산자
연산자설명예제
나머지 연산자 (%)이항 연산자입니다. 두 피연산자를 나눈후 나머지를 반환합니다.12 % 5 는 2를 반환합니다.
증가 연산자 (++)단항 연산자입니다. 피연산자에 1을 더합니다. 만약 연산자를 피연산자 앞(++x)에 사용하면, 피연산자에 1을 더한 값을 반환합니다.; 만약 연산자를 피연산자 뒤(x++)에 사용하면, 피연산자에 1을 더하기 전 값을 반환합니다.x 가 3이면 ++xx 를 4로 만들고 4를 반환합니다. 반면 x++ 는 3을 반환하고 x 를 4로 만듭니다.
감소 연산자 (--)단항 연산자입니다. 피연산자로 부터 1을 뺍니다. 반환값은 증가 연산자와 유사합니다.x 가 3이면 --xx 를 2로 만들고2를 반환합니다. 반면 x-- 는 3을 반환하고 x 를 2로 만듭니다.
단항 부정 연산자 (-)단항 연산자 입니다. 피연산자의 반대값(부호 바뀐값)을 반환합니다. x 가 3이면 -x 는 -3을 반환합니다.
숫자화 연산자 (+)단항연산자 입니다. 피연산자가 숫자값이 아니라면 피연산자를 숫자로 변환하기를 시도합니다.+"3"3을 반환합니다.
+ +true1. 을 반환합니다.
+ +

비트 연산자

+ +

비트 연산자는 피연산자를 10진수, 16진수, 8진수처럼 취급하지 않고 32비트의 집합으로 취급합니다. 예를 들면, 10진수의 9는 2진수의 1001로 나타낼 수 있습니다. 비트 단위 연산자는 이진법으로 연산을 수행하지만, JavaScript의 표준 숫자값을 반환합니다..

+ +

다음의 표는 JavaScript의 비트단위 연산자의 요약입니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
비트 연산자
연산자사용법설명
비트단위 논리곱a & b두 피연산자의 각 자리 비트의 값이 둘다 1일 경우 해당하는 자리에 1을 반환합니다.
비트단위 논리합a | b두 피연산자의 각 자리 비트의 값이 둘다 0일 경우 해당하는 자리에 0을 반환합니다.
비트단위 배타적 논리합a ^ b두 피연산자의 각 자리 비트의 값이 같을 경우 해당하는 자리에 0을 반환합니다.
+ [두 피연산자의 각 자리 비트의 값이 다를 경우 해당하는 자리에 1을 반환합니다.]
비트단위 부정~ a피연산자의 각 자리의 비트를 뒤집습니다.
왼쪽 시프트a << b오른쪽에서 0들을 이동시키면서, a의 이진수의 각 비트를 b비트 만큼 왼쪽으로 이동시킨 값을 반환합니다.
부호 전파 오른쪽 시프트a >> b사라지는 비트를 버리면서, a의 이진수의 각 비트를 b비트만큼 이동시킨값을 반환합니다.
부호 없는 오른쪽 시프트a >>> b사라지는 비트를 버리고 왼쪽에서 0을 이동시키면서, a의 이진수의 각 비트를 b비트 만큼 이동시킨 값을 반환합니다.
+ +

비트 논리 연산자

+ +

개념상으로, 비트단위 논리 연산자는 다음과 같이 동작합니다:

+ + + +

예를 들면, 9의 이진표현은 1001이고, 15의 이진표현은 1111입니다. 따라서, 비트단위 연산자가 이 값들에 적용될때, 결과는 다음과 같습니다:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
비트 연산자 예제
표현결과이진법 설명
15 & 991111 & 1001 = 1001
15 | 9151111 | 1001 = 1111
15 ^ 961111 ^ 1001 = 0110
~15-16~00000000...00001111 = 11111111...11110000
~9-10~00000000...00001001 = 11111111...11110110
+ +

모든 32비트가 비트단위 부정연산자를 통해 뒤집히고, 가장 의미있는(가장 왼쪽의) 비트가 1인 값들이 음수(2의 보수 표기법)로 표현되는것에 주목하세요 . ~x 의 평가 값은 -x -1의 평가값과 동일합니다.

+ +

비트 시프트 연산자

+ +

비트 단위 연산자는 2개의 피연산자를 가집니다: 첫번째는 이동될 수치이고, 두번째는 첫번째 피연산자가 이동될 비트 자리수를 명시합니다. 비트 이동 연산의 방향은 연산자의 사용에 의해 조종됩니다.

+ +

이동 연산자는 피연산자를 32비트의 정수로 변환하고, 왼쪽의 피연산자와 같은 형태를 반환합니다.

+ +

이동 연산자는 다음의 표에 나열되었습니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
비트 시프트 연산자
연산자설명예제
왼쪽 시프트
+ (<<)
이 연산자는 첫번째 피연산자를 특정한 수의 비트를 왼쪽으로 이동시킵니다. 왼쪽으로 초과되어 이동되는 비트들은 버려집니다. 오른쪽으로부터 0이 이동됩니다.9<<2 yields 36, because 1001 shifted 2 bits to the left becomes 100100, which is 36.
부호 전파 오른쪽 시프트(>>)이 연산자는 첫번째 피연산자를 특정한 수의 비트를 오른쪽으로 이동시킵니다. 오른쪽으로 초과되어 이동되는 비트들은 버려집니다. 왼쪽으로부터 제일 왼쪽의 비트 값이 이동됩니다.9>>2 yields 2, because 1001 shifted 2 bits to the right becomes 10, which is 2. Likewise, -9>>2 yields -3, because the sign is preserved.
부호 없는 오른쪽 시프트(>>>)이 연산자는 첫번째 피연산자를 특정한 수의 비트를 오른쪽으로 이동시킵니다. 오른쪽으로 초과되어 이동되는 비트들은 버려집니다. 왼쪽으로부터 0이 이동됩니다 .19>>>2 yields 4, because 10011 shifted 2 bits to the right becomes 100, which is 4. For non-negative numbers, zero-fill right shift and sign-propagating right shift yield the same result.
+ +

논리 연산자

+ +

논리 연산자는 보통 부울 값과 사용됩니다; 부울 값들과 사용될때, 연산자는 부울값을 반환합니다. 그러나,&& 과 || 연산자는 실제로 명시된 피연자들 중 하나를 반환합니다. 따라서, 만약 이 연산자들이 부울 값이 아닌 값들과 함께 쓰였을때, 그들은 부울 값이 아닌 값을 반환할지도 모릅니다. 논리 연산자들은 다음의 표에서 설명됩니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
논리 연산자
연산자구문설명
논리 AND (&&)expr1 && expr2expr1true로 변환할 수 있는 경우 expr2을 반환하고, 그렇지 않으면 expr1을 반환합니다.
논리 OR (||)expr1 || expr2 +

expr1true로 변환할 수 있으면 expr1을 반환하고, 그렇지 않으면 expr2를 반환합니다.

+
논리 NOT (!)!expr단일 피연산자를 true로 변환할 수 있으면 false를 반환합니다. 그렇지 않으면 true를 반환합니다.
+ +

false로 변환될 수 있는 표현 예제들은 null, 0, NaN, 빈 문자열 (""), 또는 정의되지 않음 으로 평가될 수 있습니다.

+ +

다음의 코드는 && (논리 곱) 연산자의 예제를 보여주고 있습니다.

+ +
var a1 =  true && true;     // t && t returns true
+var a2 =  true && false;    // t && f returns false
+var a3 = false && true;     // f && t returns false
+var a4 = false && (3 == 4); // f && f returns false
+var a5 = "Cat" && "Dog";    // t && t returns Dog
+var a6 = false && "Cat";    // f && t returns false
+var a7 = "Cat" && false;    // t && f returns false
+
+ +

다음의 코드는 || (논리 합) 연산자의 예제를 보여주고 있습니다.

+ +
var o1 =  true || true;     // t || t returns true
+var o2 = false || true;     // f || t returns true
+var o3 =  true || false;    // t || f returns true
+var o4 = false || (3 == 4); // f || f returns false
+var o5 = "Cat" || "Dog";    // t || t returns Cat
+var o6 = false || "Cat";    // f || t returns Cat
+var o7 = "Cat" || false;    // t || f returns Cat
+
+ +

다음의 코드는 ! (논리 부정) 연산자의 예제를 보여주고 있습니다.

+ +
var n1 = !true;  // !t returns false
+var n2 = !false; // !f returns true
+var n3 = !"Cat"; // !t returns false
+
+ +

단락 평가

+ +

논리 연산자가 왼쪽에서 오른쪽으로 평가될때, 논리연산자는 다음의 규칙을 따라서 "단축 계산"으로 검사됩니다:

+ + + +

이 논리 규칙들은 이러한 평가가 언제나 정확하다고 보증합니다. 위에서 anything 부분은 평가되지 않았고, 어떤 부작용도 아무런 효과를 미치지 못한다는 것에 주목하세요.

+ +

문자열 연산자

+ +

문자열 값으로 사용될 수 있는 비교 연산자에 덧붙여서, 연결 연산자 (+)는 두 문자열 값을 연결하고,두 문자열이 합쳐진 새로운 문자열을 반환합니다.

+ +

예를 들어,

+ +
console.log("my " + "string"); // console logs the string "my string".
+ +

복합 할당 연산자인 += 또한 문자열을 연결하는데 사용할 수 있습니다.

+ +

예를 들어,

+ +
var mystring = "alpha";
+mystring += "bet"; // evaluates to "alphabet" and assigns this value to mystring.
+ +

조건 (삼항) 연산자

+ +

조건 연산자 는 JavaScript에서 3개의 항을 사용하는 유일한 연산자 입니다. 조건 연산자는 조건에 따라 2개의 값중 하나를 가질 수 있습니다. 문법은 다음과 같습니다:

+ +
조건 ? 값1 : 값2
+
+ +

만약 조건이 참이라면, 조건 연산자는 값1을 값으로 갖습니다. 그렇지 않은 경우 조건 연산자는 값2을 값으로 갖습니다. 표준 연산자를 사용하는 어디든 조건연산자를 사용할 수 있습니다.

+ +

에들 들어,

+ +
var status = (age >= 18) ? "adult" : "minor";
+
+ +

이 구문은 age 변수가 18보다 같거나 클때 "adult" 값을 status 변수에 할당합니다. 그렇지 않은 경우, 이 구문은 "minor"값을 status변수에 할당합니다.

+ +

쉼표 연산자

+ +

쉼표 연산자 (,)는 두 피연산자를 평가하고, 마지막 피연산자의 값을 반환합니다. 이 연산자는 주로 for 반복문 안에서 각각의 시간에 복수의 변수들을 갱신하기 위하여 사용합니다.

+ +

예를 들어, a는 각 변에 10개의 원소가 있는 2차원 배열일때, 다음의 코드는 콤마 연산자를 두 변수를 한번에 증가 시키기 위하여 사용하였습니다. 이 코드는 배열의 대각선에 위치한 원소를 출력합니다:

+ +
var x = [0,1,2,3,4,5,6,7,8,9]
+var a = [x, x, x, x, x];
+
+for (var i = 0, j = 9; i <= j; i++, j--)
+  console.log('a[' + i + '][' + j + ']= ' + a[i][j]);
+ +

단항 연산자

+ +

단항 연산자는 오직 하나의 피연산자를 가지고 연산을합니다.

+ +

delete

+ +

delete연산자는 객체, 객체의 속성 또는 배열의 특정한 위치에 있는 객체를 삭제합니다. 문법은 다음과 같습니다:

+ +
delete objectName;
+delete objectName.property;
+delete objectName[index];
+delete property; // legal only within a with statement
+
+ +

objectName은 객체의 이름이고, property는 객체에 존재하는 속성이고,index는 배열의 위치를 나타내는 정수입니다.

+ +

네번째 형태의 경우,객체의 속성을 삭제하기 위하여 with 구문이 있어야만 동작합니다.

+ +

delete 연산자를 var 구문을 사용하지 않고 묵시적으로 만들어진 변수를 삭제할 때 사용할 수 있습니다.

+ +

만약 delete연산자의 동작이 성공했다면, delete 연산자는 속성이나, 원소를 undefined 로 설정합니다. delete 연산자는 연산이 수행 가능할때 true값을 반환합니다; 수행이 불가능 할 경우 false 값을 반환합니다.

+ +
x = 42;
+var y = 43;
+myobj = new Number();
+myobj.h = 4;    // create property h
+delete x;       // returns true (can delete if declared implicitly)
+delete y;       // returns false (cannot delete if declared with var)
+delete Math.PI; // returns false (cannot delete predefined properties)
+delete myobj.h; // returns true (can delete user-defined properties)
+delete myobj;   // returns true (can delete if declared implicitly)
+
+ +
배열의 원소를 삭제하기
+ +

배열의 원소를 삭제할때, 배열의 길이에는 영향을 주지 못합니다. 예를 들어, 만약 a[3], a[4]를 삭제 했다면 a[4]a[3]는 undefined(정의되지 않음)상태로 되어 있습니다.

+ +

delete 연산자가 배열의 한 원소를 삭제하였을때, 그 원소는 배열에 존재하지 않습니다. 다음의 예제에서, trees[3]delete 연산자에 의해 제거되었습니다.그러나, trees[3] 는 아직도 다룰수 있고 undefined(정의 되지 않음) 을 반환합니다.

+ +
var trees = ["redwood", "bay", "cedar", "oak", "maple"];
+delete trees[3];
+if (3 in trees) {
+  // this does not get executed
+}
+
+ +

만약 배열의 원소가 존재하지만 undefined(정의 되지 않음)값을 가지고 싶으면, delete 연산자 대신 undefined 키워드를 사용하세요. 다음의 예제에서, trees[3]undefined값을 할당받습니다,그러나 배열의 원소는 아직도 존재합니다:

+ +
var trees = ["redwood", "bay", "cedar", "oak", "maple"];
+trees[3] = undefined;
+if (3 in trees) {
+  // this gets executed
+}
+
+ +

typeof

+ +

typeof 연산자는 다음과 같은 방법으로 사용됩니다:

+ +
typeof 피연산자
+typeof (피연산자)
+
+ +

typeof 연산자 피연산자의 타입을 나타내는 문자열을 반환합니다. 피연산자 는 어떤 타입인지 반환될 문자열, 변수, 키워드,또는 객체입니다 . 괄호 표현은 선택사항입니다.

+ +

다음의 변수를 정의했다고 가정하세요:

+ +
var myFun = new Function("5 + 2");
+var shape = "round";
+var size = 1;
+var foo = ['Apple', 'Mango', 'Orange'];
+var today = new Date();
+
+ +

typeof 연산자는 이 변수들에 대하여 다음과 같은 값을 반환합니다:

+ +
typeof myFun;     // returns "function"
+typeof shape;     // returns "string"
+typeof size;      // returns "number"
+typeof foo;       // returns "object"
+typeof today;     // returns "object"
+typeof dontExist; // returns "undefined"
+
+ +

typeof 연산자는 키워드truenull에 대하여 다음과 같은 결과를 반환합니다:

+ +
typeof true; // returns "boolean"
+typeof null; // returns "object"
+
+ +

typeof 연산자는 숫자와 문자열에 대하여 다음과 같은 결과를 반환합니다:

+ +
typeof 62;            // returns "number"
+typeof 'Hello world'; // returns "string"
+
+ +

typeof 연산자는 객체의 속성에 대하여 속성이 갖고있는 타입의 값을 반환합니다.

+ +
typeof document.lastModified; // returns "string"
+typeof window.length;         // returns "number"
+typeof Math.LN2;              // returns "number"
+
+ +

typeof 연산자는 메소드와 함수들에 대하여 다음과 같은 결과를 반환합니다:

+ +
typeof blur;        // returns "function"
+typeof eval;        // returns "function"
+typeof parseInt;    // returns "function"
+typeof shape.split; // returns "function"
+
+ +

typeof 연산자는 미리 정의된 객체에 대하여 다음과 같은 결과를 반환합니다:

+ +
typeof Date;     // returns "function"
+typeof Function; // returns "function"
+typeof Math;     // returns "object"
+typeof Option;   // returns "function"
+typeof String;   // returns "function"
+
+ +

void

+ +

void 연산자 는 다음과 같은 방법들로 사용됩니다:

+ +
void (식)
+void 식
+
+ +

void 연산자는 값을 반환하지 않고 평가되도록 명시합니다. 은 JavaScript의 평가될 표현 입니다. 괄호 로 둘러싸는것은 선택사항이지만, 괄호로 둘러싸는게 좋은 사용방법입니다.

+ +

void 연산자를 표현을 하이퍼링크 에서 명시할때 사용할 수 있습니다 . 구문은 실행이 되나, 현재의 문서에는 로드되지 않습니다.

+ +

다음의 코드는 사용자가 클릭을 하였을때 아무 일도 안하는 하이퍼링크를 생성합니다. 사용자가 클릭을 했을때, void(0) JavaScript에서 아무런 영향을 줄 수 없는 undefined(정의 되지않음)으로 평가됩니다.

+ +
<a href="javascript:void(0)">Click here to do nothing</a>
+
+ +

다음의 코드는 사용자가 클릭을 하였을때, 폼을 제출하는 하이퍼링크를 생성합니다.

+ +
<a href="javascript:void(document.form.submit())">
+Click here to submit</a>
+ +

관계 연산자

+ +

관계 연산자는 피연산자들을 비교하고 ,비교의 참 여부에 기반하여 부울 값을 반환합니다.

+ +

in

+ +

in 연산자는 객체에 특정한 속성이 있는경우 true를 반환합니다. 구문은 다음과 같습니다:

+ +
propNameOrNumber in objectName
+
+ +

propNameOrNumber는 속성의 이름을 나타내는 문자열 또는 배열의 인덱스를 나타내는 숫자이고, objectName은 객체의 이름입니다.

+ +

다음의 예제는 in 연산자의 사용 예를 보여줍니다.

+ +
// Arrays
+var trees = ["redwood", "bay", "cedar", "oak", "maple"];
+0 in trees;        // returns true
+3 in trees;        // returns true
+6 in trees;        // returns false
+"bay" in trees;    // returns false (you must specify the index number,
+                   // not the value at that index)
+"length" in trees; // returns true (length is an Array property)
+
+// built-in objects
+"PI" in Math;          // returns true
+var myString = new String("coral");
+"length" in myString;  // returns true
+
+// Custom objects
+var mycar = { make: "Honda", model: "Accord", year: 1998 };
+"make" in mycar;  // returns true
+"model" in mycar; // returns true
+
+ +

instanceof

+ +

instanceof 연산자는 명시된 객체가 명시된 객체형인 경우 true를 반환합니다. 구문은 다음과 같습니다:

+ +
objectName instanceof objectType
+
+ +

objectName은 objectType 과 비교할 객체의 이름이고, objectType 은 {{jsxref("Date")}} 또는 {{jsxref("Array")}}과 같은 객체형 입니다.

+ +

instanceof 연산자를 동작시간에 객체의 형태를 확인할 필요가 있을때 사용하세요. 예를 들어, 예외가 발생하였을때, 던저진 예외의 형태에 따라 예외를 처리하는 코드로 나뉘게 할 수 있습니다.

+ +

예를 들어, 다음의 코드는instanceof 연산자를theDay 객체가 Date 형의 객체인지 알아내는 코드입니다. theDay객체는 Date 형의 객체이기 때문에, if 문 안의 명령문들은 실행됩니다.

+ +
var theDay = new Date(1995, 12, 17);
+if (theDay instanceof Date) {
+  // statements to execute
+}
+
+ +

연산자 우선순위

+ +

연산자의 우선순위는 구문을 수행할 때 수행될 순서를 결정합니다. 괄호를 통하여 우선순위를 재정의 할 수 있습니다.

+ +

다음의 표는 우선순위가 높은 순서부터 낮은 순서까지, 연산자의 우선순위에 대하여 설명하고 있습니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
연산자 우선순위
Operator typeIndividual operators
맴버 연산자. []
객체 호출/생성 연산자() new
부정/증가 연산자! ~ - + ++ -- typeof void delete
곱셈/나눗셈 연산자* / %
덧셈/뺄셈 연산자+ -
비트단위 시프트 연산자<< >> >>>
관계 연산자< <= > >= in instanceof
같음 비교 연산자== != === !==
비트 단위 논리곱 연산자&
비트단위 배타적 논리합 연산자^
비트단위 논리합 연산자|
논리 곱 연산자&&
논리 합 연산자||
조건 연산자?:
할당 연산자= += -= *= /= %= <<= >>= >>>= &= ^= |=
콤마 연산자,
+ +

각 각의 연산자에 대한 추가적인 상세사항에 대해 연결된, 더 자세한 표를 보고 싶으면, JavaScript Reference에서 보실 수 있습니다.

+ +

표현식

+ +

코드 값으로 확인된 표현은 그 어떤 타당한 단위입니다.

+ +

개념적으로, 2가지의 유형이 있습니다. 첫번째는, 변수에 값을 할당시키는 것, 두번째는 단순히 값을 갖는것이 있습니다.

+ +

x = 7이란 표현은 첫번째 유형입니다. 이 표현은 x에다가 7을 할당시키기위해 =연산자를 사용합니다. 그 표현자체 7로 계산됩니다.

+ +

3 + 4란 코드는 두번째 표현방식의 예입니다. 이 표현은 7이라는 결과로 할당하는것없이 3과 4를 더하기위해 +연산자를 사용합니다.

+ +

JavaScript는 아래 표현범주를 따릅니다.

+ + + +

중요한 표현식

+ +

JavaScript에서의 기본적인 키워드와 일반적인 표현식입니다.

+ +

this

+ +

현재 객체를 참조하는 데 this 키워드를 사용합니다. 일반적으로, this는 메소드에서 호출하는 객체를 참조합니다. 점(.)이나 괄호([])로 접근할 수 있습니다.

+ +
this["propertyName"]
+this.propertyName
+
+ +

어떤 객체의 최솟값 최댓값에 대하여, value 프로퍼티가 유효범위에 속하는지를 평가하는 validate 함수를 호출했다고 가정해봅시다.

+ +
function validate(obj, lowval, hival){
+  if ((obj.value < lowval) || (obj.value > hival))
+    console.log("Invalid Value!");
+}
+
+ +

다음과 같이 각 form 요소의 onChange 이벤트 처리기에서 validate 함수를 호출할 수 있습니다. this 일차식을 사용하여 form 요소(element)를 전달할 수 있습니다:

+ +
<p>Enter a number between 18 and 99:</p>
+<input type="text" name="age" size=3 onChange="validate(this, 18, 99);">
+
+ +

그룹 연산자

+ +

그룹연산자 ()는 표현식 평가의 우선순위를 조절합니다. 예를 들어, 곱셈과 나눗셈 연산을 무시하고, 우선 덧셈 뺄셈 연산을 먼저 수행할 수도 있습니다.

+ +
var a = 1;
+var b = 2;
+var c = 3;
+
+// default precedence
+a + b * c     // 7
+// evaluated by default like this
+a + (b * c)   // 7
+
+// now overriding precedence
+// addition before multiplication
+(a + b) * c   // 9
+
+// which is equivalent to
+a * c + b * c // 9
+
+ +

좌변식

+ +

좌측값들이 좌변식의 목적입니다.

+ +

new

+ +

당신은 사용자 정의 객체 형식 또는 한 내장된 객체 형식의 인스턴스를 만드는 데는 new 연산자사용할 수 있습니다. new는 아래와 같이 사용할 수 있습니다:

+ +
var objectName = new objectType([param1, param2, ..., paramN]);
+
+ +

super

+ +

Super 키워드개체의 부모에 함수를 호출하는 데 사용됩니다. 예를 들어 이것은 부모생성자를 부르는 클래스들과 함께 유용합니다

+ +
super([arguments]); // calls the parent constructor.
+super.functionOnParent([arguments]);
+
+ +

확산연산자

+ +

확산연산자는 다중인수(함수호출)또는 다중요소(문자배열)들이 예상되는 곳에서 확장될 수 있는 표현을 하게합니다.

+ +

Example: 만약 하나의 배열에 다른 하나의 배열을 추가하고 싶을 때에는 Array 리터럴 구문이 더이상 충분하지않으므로 push, splice, concat과 같은 함수를 사용하는 것이 좋습니다. 하지만 확산연산자를 사용할 경우 좀 더 간결한 구문으로 구현할 수 있습니다. 

+ +
var parts = ['shoulder', 'knees'];
+var lyrics = ['head', ...parts, 'and', 'toes'];
+
+//[ 'head', 'shoulders', 'knees', 'and', 'toes' ]
+
+ +

위와 같이, 확산연산자의 함수 호출은 다음과 같이 사용합니다.

+ +
function f(x, y, z) { }
+var args = [0, 1, 2];
+f(...args);
+ +
{{PreviousNext("Web/JavaScript/Guide/Functions", "Web/JavaScript/Guide/Numbers_and_dates")}}
diff --git a/files/ko/web/javascript/guide/index.html b/files/ko/web/javascript/guide/index.html new file mode 100644 index 0000000000..7ae4ac0fcf --- /dev/null +++ b/files/ko/web/javascript/guide/index.html @@ -0,0 +1,138 @@ +--- +title: JavaScript 안내서 +slug: Web/JavaScript/Guide +tags: + - Guide + - JavaScript + - 'l10n:priority' + - 자바스크립트 +translation_of: Web/JavaScript/Guide +--- +
{{jsSidebar("JavaScript Guide")}}
+ +

JavaScript 안내서에서 JavaScript 언어 개요와 사용법을 알아보세요. 언어 기능에 대해 상세한 정보가 필요하면 JavaScript 참고서를 방문하세요.

+ +

목차

+ +

본 안내서는 여러 장으로 구성되어 있습니다.

+ + + + + + + + + +

{{Next("Web/JavaScript/Guide/Introduction")}}

diff --git a/files/ko/web/javascript/guide/indexed_collections/index.html b/files/ko/web/javascript/guide/indexed_collections/index.html new file mode 100644 index 0000000000..f048ddc752 --- /dev/null +++ b/files/ko/web/javascript/guide/indexed_collections/index.html @@ -0,0 +1,456 @@ +--- +title: Indexed collections +slug: Web/JavaScript/Guide/Indexed_collections +translation_of: Web/JavaScript/Guide/Indexed_collections +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Keyed_Collections")}}
+ +

이번장에서는 인덱스값에 의해 정렬이 되는 데이터 자료구조에 대해 소개합니다.  배열과 유사 배열 생성자인 {{jsxref("Array")}} 객체와 {{jsxref("TypedArray")}} 객체 같은 생성자들을 포함합니다. 

+ +

배열 객체

+ +

배열은 이름과 인덱스로 참조되는 정렬된 값들의 집합입니다. 예를 들면, 숫자로 된 사원번호를 index로하여 사원명을 가지고 있는 emp라는 배열을 가질 수 있습니다. 그래서 emp[1]은 사원번호 1번, emp[2]는 사원번호 2번, 이런식으로 사원번호를 인덱스 값으로 가질 수 있는 것입니다.

+ +

자바스크립트는 명시적인 배열 데이터 형식을 가지고 있지 않습니다. 그러나 미리 정의된 배열 객체를 사용할 수 있고 배열 객체의 메서드를 개발하는 어플리케이션에서 사용되는 배열에 사용할 수 있습니다. 배열 객체는 합치기(joining), 순서 뒤집기(reversing) 그리고 정렬(sorting)과 같은 다양한 방법으로 배열을 조작하는 메서드들을 제공합니다. 정규 표현식과 함께 사용할 배열 길이와 기타 속성을 결정하는 속성이 있습니다.

+ +

배열 생성

+ +

아래의 구문들은 동일한 요소를 가지는 배열을 생성하는 방법들입니다. 

+ +
var arr = new Array(element0, element1, ..., elementN);
+var arr = Array(element0, element1, ..., elementN);
+var arr = [element0, element1, ..., elementN];
+
+ +

요소0, 요소1, ..., 요소N은 배열내에 포함된 요소의 값 목록 입니다. 해당 값들이 명시되어 있을 경우, 해당 배열은 주어진 요소들을 포함하도록 초기화 됩니다. 해당 배열의 길이는 주어진 요소들의 갯수가 됩니다. 

+ +

대괄호 문법은 일명 "배열  문자" 혹은 "배열 초기화"라고 합니다. 대괄호 문법은 다른 배열 생성 표기법 보다 짧고 일반적으로 선호하는 문법입니다. 보다 상세한 내용은 Array literals를 참조하세요.

+ +

 길이가 0보다 크지만 아무런 요소를 가지고 있지 않은 배열을 생성하기 위한 방법은 아래와 같습니다. 

+ +
var arr = new Array(arrayLength);
+var arr = Array(arrayLength);
+
+// This has exactly the same effect
+var arr = [];
+arr.length = arrayLength;
+
+ +
+

Note : 위의 예제 코드에서, arrayLength는 반드시 숫자여야 합니다. 그렇지 않으면 하나의 요소(주어진 값)을 가지는 배열이 생성 됩니다. arr.length를 호출하면 arrayLength가 반환이 되지만 해당 배열은 실제로 아무런 요소를 가지고 있지 않습니다. {{jsxref("Statements/for...in","for...in")}} 반복문을 실행하면 해당 배열은 아무런 요소를 반환하지 않습니다.

+
+ +

추가로 아래의 예제에서 볼 수 있듯이, 새로이 정의된 혹은 이미 존재하는 객체 변수의 속성으로 배열을 할당 할 수 있습니다.

+ +
var obj = {};
+// ...
+obj.prop = [element0, element1, ..., elementN];
+
+// OR
+var obj = {prop: [element0, element1, ...., elementN]}
+
+ +

값이 숫자인 하나의 요소만을 가지는 배열을 생성하고자 할 경우, 반드시 대괄호 문법을 사용해야 합니다. 하나의 숫자 값을 Array() 생성자에게 전달할 경우, 그 숫자 값은 해당 배열의 요소가 아니라 arrayLength(배열의 길이)로 해석됩니다. 

+ +
var arr = [42];
+var arr = Array(42); // Creates an array with no element,
+                     // but with arr.length set to 42
+
+// The above code is equivalent to
+var arr = [];
+arr.length = 42;
+
+ +

만약 숫자이지만 0이 아닌 소수점을 가지는 숫자를 Array()생성자에게 인자로 줄 경우, 범위 에러(RangeError)가 발생하게 됩니다. 아래의 예제는 범위 에러가 발생되는 상황을 보여 줍니다. 

+ +
var arr = Array(9.3);  // RangeError: Invalid array length
+
+ +

만약 임의의 데이터 형식인 하나의 요소를 가지는 배열을 생성하고자 할 경우, 배열 표기법을 사용하는 것이 안전합니다. 혹은 빈 배열을 먼저 선언한 후 임의의 데이터 값을 해당 배열에 추가하는 것도 방법이 됩니다. 

+ +

ES2015에서 요소가 하나인 배열을 만들기 위해  Array.of 정적 메소드를 사용할 수 있습니다.

+ +
let wisenArray = Array.of(9.3) // wisenArray contains only one element 9.3
+ +

배열에 값 저장

+ +

배열의 요소에 값을 할당하여 배열에 값을 저장할 수 있습니다. 예를 들면, 

+ +
var emp = [];
+emp[0] = 'Casey Jones';
+emp[1] = 'Phil Lesh';
+emp[2] = 'August West';
+
+ +
+

참고: 위의 코드 예제 처럼 배열 연산자에 양의 정수가 아닌 값을 줄 경우, 배열의 요소가 대신 배열로 대변되는 객체의 속성이 생성이 됩니다. 

+
+ +
var arr = [];
+arr[3.4] = 'Oranges';
+console.log(arr.length);                // 0
+console.log(arr.hasOwnProperty(3.4));   // true
+
+ +

배열을 생성함과 동시에 배열에 값을 저장할 수 있습니다. 

+ +
var myArray = new Array('Hello', myVar, 3.14159);
+var myArray = ['Mango', 'Apple', 'Orange'];
+
+ +

배열 요소의 참조

+ +

배열의 요소를 참조하기 위해서 해당 요소의 인덱스(요소의 순서를 나타내는 )를 사용할 수 있습니다. 예를 들어, 아래와 같이 배열을 선언 하였다면

+ +
var myArray = ['Wind', 'Rain', 'Fire'];
+
+ +

배열의 첫번째 요소는 myArray[0]로 참조할 수 있고 두번째 요소는 myArray[1]로 참조할 수 있습니다. 배열의 인덱스 값은 0부터 시작합니다.

+ +
+

참고: 배열 연산자(대괄호)는 배열의 속성에 접근하기 위해서도 사용될 수 있습니다.(배열 또한 객체이기 때문입니다.) 예를 들면 아래와 같습니다.

+
+ +
var arr = ['one', 'two', 'three'];
+arr[2];  // three
+arr["length"];  // 3
+
+ +

배열 길이에 대한 이해

+ +

실제 구현에서, 자바스트립트의 배열은 배열에 포함된 요소들을 배열의 인덱스 값을 속성 이름으로 사용하여 표준 객체의 속성처럼 저장을 합니다. 길이 속성은 좀 특별합니다. 배열의 길이는 항상 마지막 요소의 인덱스에 1을 더한 값을 반환합니다.(다음 예제에서 Dusty는 인덱스 30번째에 위치하기때문에 cats배열의 길이는 31이 됩니다.) 기억하실 것은 자바스크립트 배열의 인덱스는 항상 1부터가 아닌 0부터 시작합니다. 이것이 의미하는 바는 배열의 길이 속성은 배열에 저장되어 있는 가장 큰 인덱스보다 1만큼 큰 값이 된다는 것입니다. 

+ +
var cats = [];
+cats[30] = ['Dusty'];
+console.log(cats.length); // 31
+
+
+ +

배열의 길이(length) 속성을 지정하는 것 또한 가능합니다. 만약 배열에 저장되어 있는 요소의 갯수보다 작은 값을 배열 길이로 지정하게 되면, 지정된 배열 길이보다 큰 인덱스 값을 가지는 요소는 배열에서 삭제됩니다. 0을 배열 길이로 지정하게 되면 해당 배열은 요소를 가지지 않는 빈 배열이 되는 것입니다.

+ +
var cats = ['Dusty', 'Misty', 'Twiggy'];
+console.log(cats.length); // 3
+
+cats.length = 2;
+console.log(cats); // logs "Dusty,Misty" - Twiggy has been removed
+
+cats.length = 0;
+console.log(cats); // logs []; the cats array is empty
+
+cats.length = 3;
+console.log(cats); // logs [ <3 empty items ]
+
+ +

배열의 요소를 반복처리하기

+ +

배열을 가지고 처리하는 주된 작업은 배열의 요소를 반복적으로 접근해서 읽어오는 작업입니다. 가장 간단한 방법은 아래와 같습니다. 

+ +
var colors = ['red', 'green', 'blue'];
+for (var i = 0; i < colors.length; i++) {
+  console.log(colors[i]);
+}
+
+ +

배열이 아무런 요소를 포함하고 있지 않다면  반복문 조건에서 false로 평가됩니다. 배열의 요소가 DOM node들을 포함한다면 보다 효율적인 코드 관용구를 사용할 수 있습니다. 

+ +
var divs = document.getElementsByTagName('div');
+for (var i = 0, div; div = divs[i]; i++) {
+  /* Process div in some way */
+}
+
+ +

위의 예제 코드의 for반복문 조건은 배열의 길이을 확인하는 작업을 피할 수 있고, div변수가 매 반복마다 현재의 요소를 가지게 됩니다. 

+ +

{{jsxref("Array.forEach", "forEach()")}} 메서드는 배열의 요소를 반복처리할 수 있는 또 다른 방법입니다:

+ +
var colors = ['red', 'green', 'blue'];
+colors.forEach(function(color) {
+  console.log(color);
+});
+// red
+// green
+// blue
+
+ +

ES2015 Arrow Function으로 다음과 같이 더 짧게 코드를 짤 수 있습니다.

+ +
var colors = ['red', 'green', 'blue'];
+color.forEach(color => console.log(color));
+// red
+// green
+// blue
+
+ +

forEach에 인자로 주어진 함수는 배열의 각 요소에 대해 한번씩 실행이 되고 배열의 각 요소는 인자로 주어진 함수의 인자로 주어지게 됩니다. 할당 되지 않은 요소 값은 forEach 반복문에서 처리 되지 않습니다. 

+ +

forEach반복문으로 배열의 요소를 반복처리할때, 배열을 정의할 때 생략된 요소는 처리대상이 되지 않는 것에 유의 하세요. 하지만 undefined을 생략된 요소에 할당하게 되면 undefined로 처리됩니다.  

+ +

 

+ +
var array = ['first', 'second', , 'fourth'];
+
+array.forEach(function(element) {
+  console.log(element);
+})
+// first
+// second
+// fourth
+
+if(array[2] === undefined) {
+   console.log('array[2] is undefined'); // true
+}
+
+var array = ['first', 'second', undefined, 'fourth'];
+
+array.forEach(function(element) {
+  console.log(element);
+});
+// first
+// second
+// undefined
+// fourth
+
+ +

JavaScript 요소는 표준 객체 속성으로 저장되므로 {{jsxref ( "Statements / for ... in", "for ... in")}} 루프를 사용하여 JavaScript 배열을 반복하는 것은 바람직하지 않습니다. 왜냐면 일반 요소들과 그리고 모든 열거할 수 있는 속성들이 나열이 되기 때문입니다.

+ +

배열 객체의 메서드

+ +

{{jsxref("Array")}} 객체는 다음과 같은 메서드들을 가지고 있습니다:

+ +

{{jsxref("Array.concat", "concat()")}} 메서드는 두개의 배열을 합쳐 새로운 배열을 반환합니다.

+ +
var myArray = new Array('1', '2', '3');
+myArray = myArray.concat('a', 'b', 'c');
+// myArray is now ["1", "2", "3", "a", "b", "c"]
+ +

{{jsxref("Array.join", "join(delimiter = ',')")}} 메서드는 배열의 모든 요소를 주어진 구분자로 연결된 하나의 문자열을 반환 합니다. 

+ +
var myArray = new Array('Wind', 'Rain', 'Fire');
+var list = myArray.join(' - '); // list is "Wind - Rain - Fire"
+ +

{{jsxref("Array.push", "push()")}}메서드는 하나 혹은 그 이상의 요소를 배열의 마지막에 추가하고 추가된 요소를 포함한 길이를 반환합니다.

+ +
var myArray = new Array('1', '2');
+myArray.push('3'); // myArray is now ["1", "2", "3"]
+ +

{{jsxref("Array.pop", "pop()")}} 메서드는 배열의 마지막 요소를 제거 하고 그 제거된 요소를 반환합니다.

+ +
var myArray = new Array('1', '2', '3');
+var last = myArray.pop();
+// myArray is now ["1", "2"], last = "3"
+ +

{{jsxref("Array.shift", "shift()")}}메서드는 배열의 첫번째 요소를 제거하고 그 제거된 요소를 반환합니다.

+ +
var myArray = new Array('1', '2', '3');
+var first = myArray.shift();
+// myArray is now ["2", "3"], first is "1"
+ +

{{jsxref("Array.shift", "unshift()")}}메서드는 하나 혹은 그 이상의 요소를 배열의 앞쪽에 추가하고 추가한 요소를 포함한 길이를 반환 합니다.

+ +
var myArray = new Array('1', '2', '3');
+myArray.unshift('4', '5');
+// myArray becomes ["4", "5", "1", "2", "3"]
+ +

{{jsxref("Array.slice", "slice(start_index, upto_index)")}}메서드는 배열의 특정 부분을 추출하여 그 추출된 부분을 포함하는 새로운 배열을 반환 합니다. upto_index에 해당하는 요소는 포함되지 않습니다. 

+ +
var myArray = new Array('a', 'b', 'c', 'd', 'e');
+myArray = myArray.slice(1, 4); // starts at index 1 and extracts all elements
+                               // until index 3, returning [ "b", "c", "d"]
+ +

{{jsxref("Array.splice", "splice(index, count_to_remove, addElement1, addElement2, ...)")}} 메세드는 주어진 인덱스 요소를 포함하여 count_to_remove 갯수만큼 삭제 하고 주어진 요소로 바꿔 줍니다. 

+ +
var myArray = new Array('1', '2', '3', '4', '5');
+myArray.splice(1, 3, 'a', 'b', 'c', 'd');
+// myArray is now ["1", "a", "b", "c", "d", "5"]
+// This code started at index one (or where the "2" was),
+// removed 3 elements there, and then inserted all consecutive
+// elements in its place.
+ +

 

+ +

{{jsxref ( "Array.reverse", "reverse ()")}} 배열의 요소를 제자리에 배치합니다. 첫 번째 배열 요소가 마지막 요소가되고 마지막 요소가 첫 번째 요소가됩니다. 배열에 대한 참조를 반환합니다.

+ +
var myArray = new Array('1', '2', '3');
+myArray.reverse();
+// transposes the array so that myArray = ["3", "2", "1"]
+ +

 

+ +

{{jsxref ( "Array.sort", "sort ()")}} 배열의 요소를 제자리에 정렬하고 배열에 대한 참조를 반환합니다.

+ +
var myArray = new Array('Wind', 'Rain', 'Fire');
+myArray.sort();
+// sorts the array so that myArray = [ "Fire", "Rain", "Wind" ]
+
+ +

sort() 메서드에 어떻게 해당 배열의 요소를 정렬할 지 결정하는 콜백 함수를 인자로 줄 수 있습니다.

+ +

콜백을 사용하는 sort 메소드 및 다른 메소드는 반복 메소드로 알려져 있습니다. 일부 메소드에서는 전체 배열을 반복하기 때문입니다. 각각은 thisObject라는 선택적인 두 번째 인수를 취합니다. 제공되면 thisObject는 콜백 함수의 본문에있는 this 키워드의 값이됩니다.

+ +

제공되지 않으면 함수가 명시 적 객체 컨텍스트 외부에서 호출되는 다른 경우와 마찬가지로이 함수는 콜백으로 화살표 함수를 사용할 때 전역 객체 ({{domxref ( "window")}})를 참조합니다. 정상적인 기능은 콜백입니다.

+ +

콜백 함수는 배열의 요소 인 두 개의 인수로 호출됩니다.

+ +

아래 함수는 두 값을 비교하여 세 값 중 하나를 반환합니다.

+ +

예를 들어, 다음은 문자열의 마지막 문자로 정렬합니다.

+ +
var sortFn = function(a, b){
+  if (a[a.length - 1] < b[b.length - 1]) return -1;
+  if (a[a.length - 1] > b[b.length - 1]) return 1;
+  if (a[a.length - 1] == b[b.length - 1]) return 0;
+}
+myArray.sort(sortFn);
+// sorts the array so that myArray = ["Wind","Fire","Rain"]
+
+ + + +

{{jsxref ( "Array.indexOf", "indexOf (searchElement [, fromIndex])")}}는 배열에서 searchElement를 검색하고 첫 번째 일치 항목의 인덱스를 반환합니다.

+ +
var a = ['a', 'b', 'a', 'b', 'a'];
+console.log(a.indexOf('b')); // logs 1
+// Now try again, starting from after the last match
+console.log(a.indexOf('b', 2)); // logs 3
+console.log(a.indexOf('z')); // logs -1, because 'z' was not found
+
+ +

{{jsxref("Array.lastIndexOf", "lastIndexOf(searchElement[, fromIndex])")}}메서드는 indexOf메서드와 유사하게 작동하지만 배열의 뒤쪽에서부터 요소를 찾습니다.

+ +
var a = ['a', 'b', 'c', 'd', 'a', 'b'];
+console.log(a.lastIndexOf('b')); // logs 5
+// Now try again, starting from before the last match
+console.log(a.lastIndexOf('b', 4)); // logs 1
+console.log(a.lastIndexOf('z')); // logs -1
+
+ +

{{jsxref("Array.forEach", "forEach(callback[, thisObject])")}}메서드는 배열의 모든 요소에 대해 반복적으로 주어진 callback 함수를 실행합니다. 

+ +
var a = ['a', 'b', 'c'];
+a.forEach(function(element) { console.log(element);} );
+// logs each item in turn
+
+ +

{{jsxref("Array.map", "map(callback[, thisObject])")}}메서드는 배열의 모든 요소에 대해 콜백함수를 실행하고 콜백함수의 실행결과를 새로운 배열에 담아 반환합니다.

+ +
var a1 = ['a', 'b', 'c'];
+var a2 = a1.map(function(item) { return item.toUpperCase(); });
+console.log(a2); // logs ['A', 'B', 'C']
+
+ +

{{jsxref("Array.filter", "filter(callback[, thisObject])")}}메서드는 배열의 모든 요소에 대해 콜백 함수가 true를 반환하는 요소를 새로운 배열에 담아 반환 합니다. 

+ +
var a1 = ['a', 10, 'b', 20, 'c', 30];
+var a2 = a1.filter(function(item) { return typeof item == 'number'; });
+console.log(a2); // logs ['10', '20', '30']
+
+ +

 

+ +

{{jsxref ( "Array.every", "every (callback [, thisObject])")}}는 콜백이 배열의 모든 항목에 대해 true를 반환하면 true를 반환합니다.

+ +
function isNumber(value){
+  return typeof value == 'number';
+}
+var a1 = [1, 2, 3];
+console.log(a1.every(isNumber)); // logs true
+var a2 = [1, '2', 3];
+console.log(a2.every(isNumber)); // logs false
+
+ +

{{jsxref("Array.some", "some(callback[, thisObject])")}}메서드는 배열의 모든 요소에 대해 콜백 함수를 실행하고 하나의 요소라도 콜백 함수의 결과가 true이면 some()메서드의 결과는 true가 됩니다.

+ +
function isNumber(value){
+  return typeof value == 'number';
+}
+var a1 = [1, 2, 3];
+console.log(a1.some(isNumber)); // logs true
+var a2 = [1, '2', 3];
+console.log(a2.some(isNumber)); // logs true
+var a3 = ['1', '2', '3'];
+console.log(a3.some(isNumber)); // logs false
+
+ +

{{jsxref("Array.reduce", "reduce(callback[, initialValue])")}}메서드는 배열내의 요소를 하나의 요소로 줄이기 위해 firstValue, secondValue를 인자로 받는 콜백 함수를 실행합니다.

+ +
var a = [10, 20, 30];
+var total = a.reduce(function(first, second) { return first + second; }, 0);
+console.log(total) // Prints 60
+
+ +

{{jsxref("Array.reduceRight", "reduceRight(callback[, initalvalue])")}}메서드는 reduce()와 유사하게 작동하지만 배열의 마지막 요소부터 시작합니다.

+ +

reduce와 reduceRight 메서드는 반복적인 배열 메서드 중 가장 명백합니다. 두 메서드는 재귀적으로 하나의 시퀀스를 하나의 값으로 줄이기 위해 두개의 값을 합치는 알고리즘을 위해 사용되어야 합니다. 

+ +

다차원 배열

+ +

배열은 중첩될 수 있습니다. 즉, 하나의 배열은 또 다른 배열을 요소로 포함할 수 있습니다. 자바스크립트 배열의 이런 특성을 사용하여, 다차원 배열을 생성할 수 있습니다.

+ +

아래의 예제는 2차원 배열을 생성하는 예제입니다.

+ +
var a = new Array(4);
+for (i = 0; i < 4; i++) {
+  a[i] = new Array(4);
+  for (j = 0; j < 4; j++) {
+    a[i][j] = '[' + i + ', ' + j + ']';
+  }
+}
+ +

이 예제는 다음과 같은 열을 포함하는 배열을 생성합니다.

+ +
Row 0: [0,0] [0,1] [0,2] [0,3]
+Row 1: [1,0] [1,1] [1,2] [1,3]
+Row 2: [2,0] [2,1] [2,2] [2,3]
+Row 3: [3,0] [3,1] [3,2] [3,3]
+
+ +

배열과 정규표현식

+ +

문자열내에 정규 표현식에 일치하는 결과가 배열일 경우, 해당 배열은 정규 표현식에 일치하는 문자열들의 정보를 제공해 주는 속성들과 요소들을 반환합니다. {{jsxref ( "Global_Objects / RegExp / exec", "RegExp.exec ()")}}, {{jsxref("Global_Objects/String/match","String.match()")}}, 와 {{jsxref("Global_Objects/String/split","String.split()")}}메서드는 결과를 배열로 반환합니다. 정규식과 함께 배열을 어떻게 사용하는지에 대한 정보는 정규표현식을 참조하시면 됩니다. 

+ +

배열과 유사한 객체 사용

+ +

{{domxref ( "document.getElementsByTagName ()")}} 또는 {{jsxref ( "Functions / arguments", "arguments")}}에서 반환하는 {{domxref("NodeList")}}  객체는 함수 본문 내에서 사용할 수 있게 만들어졌으며 겉으로는 배열처럼 보이고 작동하지만 모든 메서드를 공유하지는 않습니다. arguments 객체는 {{jsxref ( "Global_Objects / Function / length", "length")}} 속성을 제공하지만 {{jsxref ( "Array.forEach", "forEach ()")}} 메소드는 구현하지 않습니다.

+ +

배열 프로토 타입 메소드는 다른 배열과 유사한 객체에 대해 호출 될 수 있습니다.

+ +
function printArguments() {
+  Array.prototype.forEach.call(arguments, function(item) {
+    console.log(item);
+  });
+}
+
+ +

배열 프로토 타입 메서드는 배열과 비슷한 방식으로 문자에 순차적으로 액세스 할 수 있으므로 문자열에서도 사용할 수 있습니다.

+ +
Array.prototype.forEach.call('a string', function(chr) {
+  console.log(chr);
+});
+ +

타입 배열

+ +

자바스크립트 타입 배열은 배열과 유사한 객체이며 원시 이진 데이터 접근에 대한 메카니즘을 제공합니다. 이미 알고 있듯이, {{jsxref("Array")}}객체는 동적으로 크기가 커지고 작아 질 수 있으며 어떤 자바스크립트 값이라도 가질 수 있습니다. 자바스크립트 엔진은 그런 배열을 빠르게 만들기 위해 최적화를 수행합니다. 그러나 웹 어플케이션이 보다 강력해지고, 음성, 영상 조작, 웹소켓을 사용하여 원시 데이터에 접근하는 등의 기능들이 추가 되면서 자바스크립트 코드가 타입배열을 가지고 빠르고 쉽게 원시 이진 데이터를 조작할 수 있는 것이 가능한 시점이 되었다는 것은 보다 명백해졌습니다.

+ +

버퍼와 뷰: 타입 배열 구조

+ +

유연성과 효율성을 극대화 하기 위해, 자바스크립트 타입 배열을 버퍼라는 구조로 구현되어 있습니다. 하나의 버퍼({{jsxref("ArrayBuffer")}}객체로 구현되어 있습니다.)는 하나의 데이터 덩어리를 의미하는 객체입니다. 버퍼는 구체적으로 언급할 형식이 없고, 버퍼가 담고 있는 내용에 접근할 메카니즘을 제공하지 않습니다. 버퍼에 담겨져 있는 메모리에 접근하기 위해선, 뷰를 사용해야 합니다. 하나의 뷰는 컨덱스트를 제공하는데, 컨텍스트는 데이터 형, 시작 오프셋 그리고 실제 타입배열로 변경되는 요소의 갯수를 제공합니다. 

+ +

Typed arrays in an ArrayBuffer

+ +

배열버퍼

+ +

{{jsxref("ArrayBuffer")}}는 일반적이고, 고정길이의 이진 데이터 버퍼를 표현하기 위해 사용되는 데이터 타입입니다. ArrayBuffer의 내용을 직접 수정할 수는 없는 대신 타입 배열 뷰 혹은 특정 형식 그리고 해당 버퍼의 내용을 읽고 쓸수 있게 해주는 {{jsxref("DataView")}}를 생성할 수 있습니다.

+ +

타입 배열 뷰

+ +

타입 배열 뷰들은 스스로를 나타낼 수 있는 이름과 Int8, Uint32, Float64등의 일반적인 숫자 형들을 위한 뷰를 제공합니다.Uint8ClampedArray라는 특별한 타입 배열 뷰가 있습니다. 0부터 255까지의 값을 가질수 있습니다. 예를 들며, Uint8ClampedArray는 Canvas data processing에 유용합니다. 

+ +

{{page("/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray", "TypedArray_objects")}}

+ +

JavaScript typed arrays를 참조하시면 보다 많은 정보를 보실 수 있습니다. 

+ +

{{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Keyed_Collections")}}

diff --git a/files/ko/web/javascript/guide/inheritance_and_the_prototype_chain/index.html b/files/ko/web/javascript/guide/inheritance_and_the_prototype_chain/index.html new file mode 100644 index 0000000000..e05bab3102 --- /dev/null +++ b/files/ko/web/javascript/guide/inheritance_and_the_prototype_chain/index.html @@ -0,0 +1,531 @@ +--- +title: 상속과 프로토타입 +slug: Web/JavaScript/Guide/Inheritance_and_the_prototype_chain +tags: + - JavaScript + - 객체지향 + - 상속 + - 중급 +translation_of: Web/JavaScript/Inheritance_and_the_prototype_chain +--- +

{{jsSidebar("Advanced")}}

+ +

Java 나 C++ 같이 클래스 기반의 언어를 사용하던 프로그래머는 자바스크립트가 동적인 언어라는 점과 클래스가 없다는 것에서 혼란스러워 한다. (ES2015부터 class 키워드를 지원하기 시작했으나, 문법적인 양념일 뿐이며 자바스크립트는 여전히 프로토타입 기반의 언어다.)

+ +

상속 관점에서 자바스크립트의 유일한 생성자는 객체뿐이다. 각각의 객체는 [[Prototype]]이라는 은닉(private) 속성을 가지는데 자신의 프로토타입이 되는 다른 객체를 가리킨다. 그 객체의 프로토타입 또한 프로토타입을 가지고 있고 이것이 반복되다, 결국 null을 프로토타입으로 가지는 오브젝트에서 끝난다. null은 더 이상의 프로토타입이 없다고 정의되며, 프로토타입 체인의 종점 역할을 한다.

+ +

종종 이러한 점이 자바스크립트의 약점이라고 지적되지만, 프로토타입적 상속 모델은 사실 고전적인 방법보다 좀 더 강력한 방법이다. 그 말은, 예를 들자면, 프로토타입적 모델에서 고전적인 방식을 구현하는 건 꽤나 사소한 일이지만, 그 반대는 훨씬 더 어려운 일이기 때문이다.

+ +

프로토타입 체인을 이용한 상속

+ +

속성 상속

+ +

자바스크립트 객체는 속성을 저장하는 동적인 "가방"과 (자기만의 속성이라고 부른다) 프로토타입 객체에 대한 링크를 가진다. 객체의 어떤 속성에 접근하려할 때 그 객체 자체 속성 뿐만 아니라 객체의 프로토타입, 그 프로토타입의 프로토타입 등 프로토타입 체인의 종단에 이를 때까지 그 속성을 탐색한다.

+ +
ECMAScript 표준은 someObject.[[Prototype]]을 객체 someObject의 프로토타입을 지시하도록 명시하였다. ECMAScript 2015부터 [[Prototype]]에 조상 {{jsxref("Object.getPrototypeOf()")}}과 {{jsxref("Object.setPrototypeOf()")}}을 이용하여 접근하기 때문이다. 이것은 자바스크립트의 표준은 아니나 많은 브라우저에 구현되어 사실상의 표준이 된 속성 __proto__과 동일하다.
+ +

아래 코드에는 어떤 속성에 접근 하려할 때 일어나는 상황이다.

+ +
// o라는 객체가 있고, 속성 'a' 와 'b'를 갖고 있다고 하자.
+let f = function () {
+    this.a = 1;
+    this.b = 2;
+}
+let o = new f(); // {a: 1, b: 2}
+
+// f 함수의 prototype 속성 값들을 추가 하자.
+f.prototype.b = 3;
+f.prototype.c = 4;
+
+// f.prototype = {b: 3, c: 4}; 라고 하지 마라, 해당 코드는 prototype chain 을 망가뜨린다.
+// o.[[Prototype]]은 속성 'b'와 'c'를 가지고 있다.
+// o.[[Prototype]].[[Prototype]] 은 Object.prototype 이다.
+// 마지막으로 o.[[Prototype]].[[Prototype]].[[Prototype]]은 null이다.
+// null은 프로토타입의 종단을 말하며 정의에 의해서 추가 [[Prototype]]은 없다.
+// {a: 1, b: 2} ---> {b: 3, c: 4} ---> Object.prototype ---> null
+
+console.log(o.a); // 1
+// o는 'a'라는 속성을 가지는가? 그렇다. 속성의 값은 1이다.
+
+console.log(o.b); // 2
+// o는 'b'라는 속성을 가지는가? 그렇다. 속성의 값은 2이다.
+// 프로토타입 역시 'b'라는 속성을 가지지만 이 값은 쓰이지 않는다. 이것을 "속성의 가려짐(property shadowing)" 이라고 부른다.
+
+console.log(o.c); // 4
+// o는 'c'라는 속성을 가지는가? 아니다. 프로토타입을 확인해보자.
+// o.[[Prototype]]은 'c'라는 속성을 가지는가? 가지고 값은 4이다.
+
+console.log(o.d); // undefined
+// o는 'd'라는 속성을 가지는가? 아니다. 프로토타입을 확인해보자.
+// o.[[Prototype]]은 'd'라는 속성을 가지는가? 아니다. 다시 프로토타입을 확인해보자.
+// o.[[Prototype]].[[Prototype]]은 null이다. 찾는 것을 그만두자.
+// 속성이 발견되지 않았기 때문에 undefined를 반환한다.
+
+ +

객체의 속성에 값을 지정하면 "자기만의 속성"이 생긴다.  단, getter or a setter가 적용되는 속성이 상속되는 경우 예외적인 규칙이 적용된다.

+ +

메소드 상속

+ +

자바스크립트에 "메소드"라는건 없다. 하지만 자바스크립트는 객체의 속성으로 함수를 지정할 수 있고 속성 값을 사용하듯 쓸 수 있다. 속성 값으로 지정한 함수의 상속 역시 위에서 본 속성의 상속과 동일하다. (단 위에서 언급한 "속성의 가려짐" 대신 "메소드 오버라이딩, method overriding" 라는 용어를 사용한다)

+ +

상속된 함수가 실행 될 때,  this 라는 변수는 상속된 오브젝트를 가르킨다. 그 함수가 프로토타입의 속성으로 지정되었다고 해도 말이다.

+ +
var o = {
+  a: 2,
+  m: function(b){
+    return this.a + 1;
+  }
+};
+
+console.log(o.m()); // 3
+// o.m을 호출하면 'this' 는 o를 가리킨다.
+
+var p = Object.create(o);
+// p 는 프로토타입을 o로 가지는 오브젝트이다.
+
+p.a = 12; // p 에 'a'라는 새로운 속성을 만들었다.
+console.log(p.m()); // 13
+// p.m이 호출 될 때 'this' 는 'p'를 가리킨다.
+// 따라서 o의 함수 m을 상속 받으며,
+// 'this.a'는 p.a를 나타내며 p의 개인 속성 'a'가 된다.
+
+ +

Javascript 에서 프로토타입을 사용하는 방법

+ +

뒤에서 일어나는 일을 좀 더 자세히 파헤쳐보자.

+ +

위에서 언급했듯이, 자바스크립트에서 함수는 속성을 가질 수 있다. 모든 함수에는 prototype이라는 특수한 속성이 있다. 아래의 예제 코드는 독립적이라는 것에 유의하자. (아래의 코드 이외에는 웹페이지에 다른 자바스크립트가 없다고 가정하는 것이 좋다.)

+ +

최적의 실습을 위해서 콘솔을 열고 "Console" 탭으로 이동하여 아래의 JavaScript 코드를 복사하여 붙여넣은 다음 , 엔터키를 눌러 실행할 것을 적극 권한다. (콘솔은 대부분 웹 브라우저의 Developer Tools에 포함되어있다. 자세한 내용은 Firefox Developer ToolsChrome DevTools, Edge DevTools 에서 확인할 수 있다. )

+ +
+ +
function doSomething(){}
+console.log( doSomething.prototype );
+// It does not matter how you declare the function, a
+//  function in JavaScript will always have a default
+//  prototype property.
+var doSomething = function(){};
+console.log( doSomething.prototype );
+ +

위 내용을 토대로, 콘솔을 보면  doSomething() 은 기본 prototype 속성을 가진다. 코드를 실행한 뒤에 콘솔에서는 다음과 유사한 형태의 객체가 표시되어야한다.

+ +
{
+    constructor: ƒ doSomething(),
+    __proto__: {
+        constructor: ƒ Object(),
+        hasOwnProperty: ƒ hasOwnProperty(),
+        isPrototypeOf: ƒ isPrototypeOf(),
+        propertyIsEnumerable: ƒ propertyIsEnumerable(),
+        toLocaleString: ƒ toLocaleString(),
+        toString: ƒ toString(),
+        valueOf: ƒ valueOf()
+    }
+}
+ +

우리는 아래에 보이는 것과 같이 doSomething() 프로토타입에 속성을 추가할 수 있다.

+ +
function doSomething(){}
+doSomething.prototype.foo = "bar";
+console.log( doSomething.prototype );
+ +

결과:

+ +
{
+    foo: "bar",
+    constructor: ƒ doSomething(),
+    __proto__: {
+        constructor: ƒ Object(),
+        hasOwnProperty: ƒ hasOwnProperty(),
+        isPrototypeOf: ƒ isPrototypeOf(),
+        propertyIsEnumerable: ƒ propertyIsEnumerable(),
+        toLocaleString: ƒ toLocaleString(),
+        toString: ƒ toString(),
+        valueOf: ƒ valueOf()
+    }
+}
+
+ +

이제 new 연산자를 사용해서 프로토타입 기반의 doSomething() 인스턴스를 생성할 수 있다. new 연산자를 사용하려면 함수 호출 형식에 new 접두사를 붙이기만하면 된다. new 연산자로 함수를 호출하면 해당 함수의 인스턴스 객체를 반환받는다. 그러면 속성들을 이 객체에 추가할 수 있다.

+ +

다음의 코드를 실행해보자.

+ +
function doSomething(){}
+doSomething.prototype.foo = "bar"; // add a property onto the prototype
+var doSomeInstancing = new doSomething();
+doSomeInstancing.prop = "some value"; // add a property onto the object
+console.log( doSomeInstancing );
+ +

실행하고나면 결과는 다음과 비슷할 것이다.

+ +
{
+    prop: "some value",
+    __proto__: {
+        foo: "bar",
+        constructor: ƒ doSomething(),
+        __proto__: {
+            constructor: ƒ Object(),
+            hasOwnProperty: ƒ hasOwnProperty(),
+            isPrototypeOf: ƒ isPrototypeOf(),
+            propertyIsEnumerable: ƒ propertyIsEnumerable(),
+            toLocaleString: ƒ toLocaleString(),
+            toString: ƒ toString(),
+            valueOf: ƒ valueOf()
+        }
+    }
+}
+
+ +

위에서 본 것과 같이, doSomeInstancing 객체의 __proto__ 는 doSomething.prototype 이다.
+ 그래서 도대체 __proto__는 무엇을 하는것인지 알아보자.
+ 우리가 doSomeInstancing의 속성에 접근할때 브라우저는 우선 doSomeInstancing이 그 속성을 갖고있는지 확인한다.
+ 만약 doSomeInstancing이 속성을 갖고있지 않다면, 브라우저는 doSomeInstancing의 __proto__(doSomething.prototype)가 그 속성을 갖고있는지 확인한다.
+ 만약 doSomeInstancing의 __proto__가 브라우저가 찾던 속성을 갖고 있다면, doSomething의 __proto__가 갖고있는 그 속성을 사용한다.

+ +

그렇지 않고, doSomeInstancing의 __proto__가 그 속성을 갖고있지 않을때에는
+ doSomeInstancing의 __proto__의 __proto__가 그 속성을 갖는지 확인한다.
+ 기본적으로, 어떠한 함수던지 그 함수의 prototype 속성의 __proto__는 window.Object.prototype이다.
+ 그러므로 브라우저는 doSomeInstancing의 __proto__의 __proto__(doSomething.prototype의 __proto__(다시말해, Object.prototype))  에서 그 속성을 찾아본다.
+ 만약 그 속성을 doSomeInstancing의 __proto__의 __proto__에서 찾을 수 없다면 그다음엔 doSomeInstancing의 __proto__의 __proto__의 __proto__에서 찾을것이다.
+ 하지만 여기서 문제가 발생한다.
+ doSomeInstancing의 __proto__의 __proto__의 __proto__는 존재할 수 없다(window.Object.prototype의 __proto__는 null이기 때문).
+ 그제서야, 오직 모든 프로토타입 체인이 검사 되고 브라우저가 더이상  검사할 __proto__가 없을때에서야 브라우저는 우리가 찾던 값이 undefined라고 결론짓는다.

+ +

콘솔에 코드를 조금 더 추가해보자.

+ +
function doSomething(){}
+doSomething.prototype.foo = "bar";
+var doSomeInstancing = new doSomething();
+doSomeInstancing.prop = "some value";
+console.log("doSomeInstancing.prop:      " + doSomeInstancing.prop);
+console.log("doSomeInstancing.foo:       " + doSomeInstancing.foo);
+console.log("doSomething.prop:           " + doSomething.prop);
+console.log("doSomething.foo:            " + doSomething.foo);
+console.log("doSomething.prototype.prop: " + doSomething.prototype.prop);
+console.log("doSomething.prototype.foo:  " + doSomething.prototype.foo);
+
+ +

이 코드의 결과는 아래와 같다.

+ +
doSomeInstancing.prop:      some value
+doSomeInstancing.foo:       bar
+doSomething.prop:           undefined
+doSomething.foo:            undefined
+doSomething.prototype.prop: undefined
+doSomething.prototype.foo:  bar
+
+ +

객체를 생성하는 여러 방법과 프로토타입 체인 결과

+ +

문법 생성자로 객체 생성

+ +
var o = {a: 1};
+
+// o 객체는 프로토타입으로 Object.prototype 을 가진다.
+// 이로 인해 o.hasOwnProperty('a') 같은 코드를 사용할 수 있다.
+// hasOwnProperty 라는 속성은 Object.prototype 의 속성이다.
+// Object.prototype 의 프로토타입은 null 이다.
+// o ---> Object.prototype ---> null
+
+var a = ["yo", "whadup", "?"];
+
+// Array.prototype을 상속받은 배열도 마찬가지다.
+// (이번에는 indexOf, forEach 등의 메소드를 가진다)
+// 프로토타입 체인은 다음과 같다.
+// a ---> Array.prototype ---> Object.prototype ---> null
+
+function f(){
+  return 2;
+}
+
+// 함수는 Function.prototype 을 상속받는다.
+// (이 프로토타입은 call, bind 같은 메소드를 가진다)
+// f ---> Function.prototype ---> Object.prototype ---> null
+
+ +

생성자를 이용

+ +

자바스크립트에서 생성자는 단지 new 연산자를  사용해 함수를 호출하면 된다.

+ +
function Graph() {
+  this.vertexes = [];
+  this.edges = [];
+}
+
+Graph.prototype = {
+  addVertex: function(v){
+    this.vertexes.push(v);
+  }
+};
+
+var g = new Graph();
+// g 'vertexes' 와 'edges'를 속성으로 가지는 객체이다.
+// 생성시 g.[[Prototype]]은 Graph.prototype의 값과 같은 값을 가진다.
+
+ +

Object.create 이용

+ +

ECMAScript 5는 새로운 방법을 도입했다. Object.create라는 메소드를 호출하여 새로운 객체를 만들 수 있다. 생성된 객체의 프로토타입은 이 메소드의 첫 번째 인수로 지정된다.

+ +
var a = {a: 1};
+// a ---> Object.prototype ---> null
+
+var b = Object.create(a);
+// b ---> a ---> Object.prototype ---> null
+console.log(b.a); // 1 (상속됨)
+
+var c = Object.create(b);
+// c ---> b ---> a ---> Object.prototype ---> null
+
+var d = Object.create(null);
+// d ---> null
+console.log(d.hasOwnProperty); // undefined이다. 왜냐하면 d는 Object.prototype을 상속받지 않기 때문이다.
+
+ +
+

class 키워드 이용

+ +

ECMAScript2015에는 몇 가지 키워드가 도입되어 class를 구현하였다. 이런 생성 방식은 클래서 기반 언어의 개발자들에게 친숙하게 다가오나 동작 방식이 같지는 않다. 자바스크립트는 여전히 프로토타입 기반으로 남아있다. 새로 도입된 키워드는 {{jsxref("Statements/class", "class")}}, {{jsxref("Classes/constructor", "constructor")}}, {{jsxref("Classes/static", "static")}}, {{jsxref("Classes/extends", "extends")}}, 그리고 {{jsxref("Operators/super", "super")}}가 있다.

+ +
'use strict';
+
+class Polygon {
+  constructor(height, width) {
+    this.height = height;
+    this.width = width;
+  }
+}
+
+class Square extends Polygon {
+  constructor(sideLength) {
+    super(sideLength, sideLength);
+  }
+  get area() {
+    return this.height * this.width;
+  }
+  set sideLength(newLength) {
+    this.height = newLength;
+    this.width = newLength;
+  }
+}
+
+var square = new Square(2);
+
+ +

성능

+ +

프로토타입 체인에 걸친 속성 검색으로 성능에 나쁜 영향을 줄 수 있으며, 때때로 치명적일 수 있다. 또한 존재하지도 않는 속성에 접근하려는 시도는 항상 모든 프로토타입 체인인 전체를 탐색해서 확인하게 만든다.

+ +

객체의 속성에 걸쳐 루프를 수행 하는 경우 프로토타입 체인 전체의 모든 열거자 속성에 대하여 적용된다. 객체 개인 속성인지 프로토타입 체인상 어딘가에 있는지 확인하기 위해서는 Object.prototype에서 모든 오브젝트로 상속된 hasOwnProperty 메소드를 이용할 필요가 있다. 다음 코드를 통하여 구체적인 예를 확인하여 보자.

+ +
console.log(g.hasOwnProperty('vertices'));
+// true
+
+console.log(g.hasOwnProperty('nope'));
+// false
+
+console.log(g.hasOwnProperty('addVertex'));
+// false
+
+console.log(g.__proto__.hasOwnProperty('addVertex'));
+// true
+
+ +

hasOwnProperty 메소드만이 속성을 확인하고 프로토타입 체인 전체를 훑지 않게 할 수 있다.

+ +

참고: undefined인지 여부만 확인하는 것으로는 충분하지 않다. 여전히 속성이 존재할 수도 있는데 단지 그 값에 undefined가 할당되어 있을 수도 있기 때문이다.

+ +

좋지 않은 사례: 기본 프로타입의 확장 변형

+ +

Object.prototype 혹은 빌트인 프로토타입의 확장은 종종 이용되지만 오용이다.

+ +

이 기법은 Monkey patching으로 불리며 캡슐화를 망가뜨린다. Prototype.js와 같은 유명한 프레임워크에서도 사용되지만, 빌트인 타입에 비표준 기능을 추가하는 것은 좋은 생각이 아니다.

+ +

유일하게 좋은 사용 예라면, 새로운 자바스크립트 엔진에 Array.forEach등의 새로운 기능을 추가하면서 빌트인 프로토타입을 확장하는 것 정도다. 

+ +

+ +

B는 A를 상속한다:

+ +
function A(a) {
+  this.varA = a;
+}
+
+// A의 정의에서 this.varA는 항상 A.prototype.varA가 가려버리는데
+// prototype에 varA를 다시 넣는 이유는 무엇인가?
+A.prototype = {
+  varA: null,  // 아무것도 안하면서 varA를 쓰는 이유가 있을까?
+      // 아마도 숨겨진 클래스의 할당 구조를 최적화 하려는 것인가?
+      // https://developers.google.com/speed/articles/optimizing-javascript#Initializing-instance-variables
+      // 모든 객체의 varA가 동일하게 초기화 되어야 상기 링크 내용이 유효할 수 있다.
+  doSomething: function() {
+    // ...
+  }
+};
+
+function B(a, b) {
+  A.call(this, a);
+  this.varB = b;
+}
+B.prototype = Object.create(A.prototype, {
+  varB: {
+    value: null,
+    enumerable: true,
+    configurable: true,
+    writable: true
+  },
+  doSomething: {
+    value: function() { // override
+      A.prototype.doSomething.apply(this, arguments); // call super
+      // ...
+    },
+    enumerable: true,
+    configurable: true,
+    writable: true
+  }
+});
+B.prototype.constructor = B;
+
+var b = new B();
+b.doSomething();
+
+ +

중요한 점은:

+ + + +

prototype 그리고 Object.getPrototypeOf

+ +

Java나 C++에 익숙한 개발자는 클래스라는 것도 없고, 모든 것이 동적이고 실행 시 결정되는 자바스크립트의 특징 때문에 어려움을 겪을 수도 있다. 모든 것은 객체이고, 심지의 "class"를 흉내내는 방식도 단지 함수 오브젝트를 이용하는 것 뿐이다.

+ +

이미 알아챘겠지만 우리의 함수 A도 특별한 속성 prototype를 가지고 있다. 이 특별한 속성은 자바스크립트의 new 연산자와 함께 쓰인다. 프로토타입 객체는 새로 만들어진 인스턴스의 내부 [[Prototype]] 속성에 복사되어 참조된다. 가령, var a1 = new A()를 수행할 때, this를 포함하고 있는 함수을 수행하기 전, 메모리에 새로 생성된 객체를 생성한 직후 자바스크립트는 a1.[[Prototype]] = A.prototype를 수행한다. 그 인스턴스의 속성에 접근하려 할 때 자바스크립트는 그 객체의 개인 속성인지 우선 확인하고 그렇지 않은 경우에 [[Prototype]]에서 찾는다. 이것은 prototype에 정의한 모든 것은 모든 인스턴스가 효과적으로 공유한다는 뜻이며, 심지어 프로토타입의 일부를 나중에 변경하다고 해도 이미 생성되어 있는 인스턴스는 필요한 경우 그 변경 사항에 접근할 수 있다.

+ +

위의 예에서, 만일 var a1 = new A(); var a2 = new A(); 그 후 a1.doSomethingObject.getPrototypeOf(a1).doSomething를 가리키게 되는 것은A.prototype.doSomething으로 정의한 것과 같게 된다. 즉, Object.getPrototypeOf(a1).doSomething == Object.getPrototypeOf(a2).doSomething == A.prototype.doSomething.

+ +

요약 하자면, prototype은 타입 정의를 위한 것이고, Object.getPrototypeOf()는 모든 인스턴스가 공유한다.

+ +

[[Prototype]]은 재귀적으로 탐색된다. 즉, a1.doSomething, Object.getPrototypeOf(a1).doSomething,Object.getPrototypeOf(Object.getPrototypeOf(a1)).doSomething 등등, 이미 발견했거나 Object.getPrototypeOfnull을 반환할 때까지 반복된다.

+ +

따라서 다음 호출에 대하여

+ +
var o = new Foo();
+ +

자바스크립트는 실제로 다음 작업을 수행한다.

+ +
var o = new Object();
+o.[[Prototype]] = Foo.prototype;
+Foo.call(o);
+ +

(혹은 그런 비슷한 작업, 내부 구현은 다를 수 있다) 그리고 나중에 다음을 수행하면

+ +
o.someProp;
+ +

자바스크립트는 o가 속성 someProp을 가졌는지 확인하고, 아니면 Object.getPrototypeOf(o).someProp, 또 아니면 Object.getPrototypeOf(Object.getPrototypeOf(o)).someProp 등으로 계속 된다.

+ +

프로토타입 상속의 종류

+ +

프로토타입 상속에는 3가지 종류가 있다 : 위임형 상속, 연결형 상속, 함수형 상속.

+ +

위임형 상속(Delegation inheritance)

+ +

위임형 상속에서 프로토타입 객체는 다른 객체의 기반이 된다. 위임 프로토타입을 상속받을 경우 새 객체는 해당 프로토타입에 대한 참조를 가지고 있다.

+ +

새 객체의 속성에 접근할 때, 해당 객체가 직접적으로 속성을 소유하고 있는지 먼저 체크한다. 없다면 다음 순서로 [[Prototype]]을 체크한다. 이 과정은 프로토타입 체인을 따라서 모든 객체의 프로토타입 체인의 최상위에 있는 객체인 Object.prototype에 도달할 때 까지 반복된다.

+ +

메소드를 위임 상속할 경우 모든 객체가 각 메소드에에 대해 하나의 코드를 공유하므로 메모리를 절약할 수 있다.

+ +

Javascript에서 이를 구현하는 방법은 여러가지가 있는데 ES6에서는 아래와 같은 방식이 흔하다:

+ +
class Greeter {
+  constructor (name) {
+    this.name = name || 'John Doe';
+  }
+  hello () {
+    return `Hello, my name is ${ this.name }`;
+  }
+}
+
+const george = new Greeter('George');
+const msg = george.hello();
+console.log(msg); // Hello, my name is George
+
+ +

Object.create(null). 을 통해 프로토타입을 {{jsxref("null")}}로 지정하여 속성 위임 없이 객체를 생성할 수 있다..

+ +

이 방법의 큰 단점 중 하나는 상태를 저장하는데 그리 좋은 방법이 아니라는 것이다. 객체나 배열의 상태를 변경하게 되면 같은 프로토타입을 공유하는 모든 객체의 상태가 변경된다.

+ +

상태 변경이 전파되는 것을 막으려면 각 객체마다 상태 값의 복사본을 만들어야 한다.

+ +

연결형 상속(Concatenative inheritance)

+ +

연결형 상속은 한 객체의 속성을 다른 객체에 모두 복사함으로써 상속을 구현하는 방법이다.

+ +

이 상속법은 Javascript 객체의 동적 확장성을 이용한 방법이다. 객체 복사는 속성의 초기값을 저장하기 위한 좋은 방법이다: 이 방식은 {{jsxref("Object.assign()")}}을 통해 구현하는 것이 보통이며 ES6 이전에 Lodash, Underscore, jQuery등의 라이브러리들이 .extend() 와 비슷한 메소드로 제공한 방법이다.

+ +
const proto = {
+  hello: function hello() {
+    return `Hello, my name is ${ this.name }`;
+  }
+};
+
+const george = Object.assign({}, proto, {name: 'George'});
+const msg = george.hello();
+console.log(msg); // Hello, my name is George
+
+ +

연결형 상속은 매우 좋은 방법이며 클로져와 같이 사용한다면 훨씬 효과적인 상속 방식입니다..

+ +

함수형 상속(Functional inheritance)

+ +

함수형 상속(Functional inheritance)이라는 단어는 Douglas Crockford가 자신의 저서 “JavaScript: The Good Parts”에서 창조한 단어이다. 이 방법은 새 속성들을 연결형 상속으로 쌓되 상속 기능을 Factory 함수로 만들어 사용하는 방식이다.

+ +

기존의 객체를 확장하는데 쓰이는 함수를 일반적으로 믹스인 함수라 칭한다. 객체 확장에 함수를 사용하는 가장 큰 이점은 Private Data를 클로져를 통해 캡슐화 시킬 수 있다는 점이다.

+ +

다르게 말하자면 Private 상태를 지정할 수 있다는 의미이다.

+ +

특정 함수를 통할 필요 없이 public 접근이 가능한 속성에 대해 접근 제한을 거는 것은 문제가 있다. 따라서 private 클로져에 속성 값을 숨겨야 하며 이는 아래와 같이 구현한다:

+ +
// import Events from 'eventemitter3';
+
+const rawMixin = function () {
+  const attrs = {};
+  return Object.assign(this, {
+    set (name, value) {
+      attrs[name] = value;
+      this.emit('change', {
+        prop: name,
+        value: value
+      });
+    },
+    get (name) {
+      return attrs[name];
+    }
+  }, Events.prototype);
+};
+
+const mixinModel = (target) => rawMixin.call(target);
+const george = { name: 'george' };
+const model = mixinModel(george);
+model.on('change', data => console.log(data));
+model.set('name', 'Sam');
+/*
+{
+  prop: 'name',
+  value: 'Sam'
+}
+*/
+
+ +

attrs 을 public 속성에서 private 영역으로 옮겨서 public API를 통한 접근을 차단할 수 있다. // 접근할 수 있는 유일한 방법은 Privileged 메소드 뿐이다. Privileged 메소드는 클로져 영역에 정의된 함수로 private data에 접근 가능한 함수들을 일컫는다.

+ +

위 예제를 보면 믹스인 함수 rawMixin().에 대한 래퍼로 mixinModel() 을 선언한 것을 알 수 있다. 이는 예제에서 {{jsxref("Function.prototype.call()")}} 을 사용했듯이 함수 내에서 this의 값을 설정해야 하기 때문이다. Wrapper를 생략하고 호출자가 알아서 하도록 놔둘 수 있지만 그럴 경우 혼동될 가능성이 있다.

+ +
+

결론

+ +

복잡한 코드를 작성하여 이용하기 전에 프로토타입 기반의 상속 모델을 이해하는 것이 중요하다. 또한 프로토타입 체인의 길이는 성능을 저해하지 않도록 줄이는 방법을 고안해야 한다. 또한 빌트인 프로토타입은 새로운 자바스크립트 기능과 호환성을 갖기 위한 이유가 아닌 이상 절대 확장해서는 안된다.

+
+
diff --git a/files/ko/web/javascript/guide/iterators_and_generators/index.html b/files/ko/web/javascript/guide/iterators_and_generators/index.html new file mode 100644 index 0000000000..648b898504 --- /dev/null +++ b/files/ko/web/javascript/guide/iterators_and_generators/index.html @@ -0,0 +1,193 @@ +--- +title: 반복기 및 생성기 +slug: Web/JavaScript/Guide/Iterators_and_Generators +tags: + - Guide + - Intermediate + - JavaScript +translation_of: Web/JavaScript/Guide/Iterators_and_Generators +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Using_promises", "Web/JavaScript/Guide/Meta_programming")}}
+ +

컬렉션 내 각 항목 처리는 매우 흔한 연산입니다. JavaScript는 간단한 {{jsxref("Statements/for","for")}} 루프에서 {{jsxref("Global_Objects/Array/map","map()")}} 및 {{jsxref("Global_Objects/Array/filter","filter()")}}에 이르기까지, 컬렉션을 반복하는 많은 방법을 제공합니다. 반복기(iterator) 및 생성기(generator)는 반복 개념을 핵심 언어 내로 바로 가져와 {{jsxref("Statements/for...of","for...of")}} 루프의 동작(behavior)을 사용자 정의하는 메커니즘을 제공합니다.

+ +

자세한 내용은, 다음을 참조하세요:

+ + + +

반복자

+ +

자바스크립트에서 반복자(Iterator)는 시퀀스를 정의하고  종료시의 반환값을 잠재적으로 정의하는 객체입니다.  더 구체적으로 말하자면, 반복자는 두 개의 속성( value, done)을 반환하는 next() 메소드 사용하여  객체의 Iterator protocol을 구현합니다. 시퀀스의 마지막 값이 이미 산출되었다면 done 값은 true 가 됩니다. 만약 value값이 done 과 함께 존재한다면, 그것은 반복자의 반환값이 됩니다.

+ +

반복자를 생성하면 next() 메소드를 반복적으로 호출하여 명시적으로 반복시킬 수 있습니다.  반복자를 반복시키는 것은 일반적으로 한 번씩만 할 수 있기 때문에, 반복자를 소모시키는 것이라고 할 수 있습니다. 마지막 값을 산출하고나서  next()를 추가적으로 호출하면 {done: true}. 가 반환됩니다.

+ +

자바스크립트에서 가장 일반적인 반복자는 배열 반복자로, 배열의 각 값을 순서대로 반환합니다. 모든 반복자가 배열로 표현될수 있다고 상상할 수 있지만 , 이것은 사실은 아닙니다. 배열은 완전히 할당되어야 하지만,  반복자는 필요한만큼만 소모되므로  무제한 시퀀스로 표현할 수 있습니다. 이를 테면 0부터 무한대사이의 정수범위처럼 말이죠.

+ +

여기에 실습할 수 있는 예제가 있습니다.  start에서 end까지 step 수 만큼 띄어진  정수 시퀀스를 정의하는 간단한 범위 반복자를 만들 수 있습니다. 최종적으로 시퀀스의 크기가 반환됩니다.

+ +
function makeRangeIterator(start = 0, end = Infinity, step = 1) {
+    var nextIndex = start;
+    var n = 0;
+
+    var rangeIterator = {
+       next: function() {
+           var result;
+           if (nextIndex < end) {
+               result = { value: nextIndex, done: false }
+           } else if (nextIndex == end) {
+               result = { value: n, done: true }
+           } else {
+               result = { done: true };
+           }
+           nextIndex += step;
+           n++;
+           return result;
+       }
+    };
+    return rangeIterator;
+}
+
+ +

위의 반복자를 사용하면 아래와 같습니다:

+ +
var it = makeRangeIterator(1, 4);
+
+var result = it.next();
+while (!result.done) {
+ console.log(result.value); // 1 2 3
+ result = it.next();
+}
+
+console.log("Iterated over sequence of size: ", result.value);
+
+ +
+

It is not possible to know reflectively whether a particular object is an iterator. If you need to do this, use Iterables.

+
+ +

Generator functions

+ +

잘 만들어진 반복자(Iterator)는 유용한 도구인 반면, 이것을 생성할 때는 주의해서 프로그래밍을 해야 하는데, 반복자 내부에 명시적으로 상태를 유지할 필요가 있기 때문입니다. 생성자(Generator) 함수는 이에 대한 강력한 대안을 제공합니다: 실행이 연속적이지 않은 하나의 함수를 작성함으로서 개발자가 iterative algorithm을 정의할 수 있게 해줍니다. 생성자 함수는 {{jsxref("Statements/function*","function*")}} 문법을 사용하여 작성됩니다. 생성자 함수가 최초로 호출될 때, 함수 내부의 어떠한 코드도 실행되지 않고, 대신 생성자라고 불리는 반복자 타입을 반환합니다. 생성자의 next 메소드를 호출함으로서 어떤 값이 소비되면, 생성자 함수는 yield 키워드를 만날 때까지 실행됩니다. 

+ +

생성자 함수는 원하는 만큼 호출될 수 있고, 매번 새로운 생성자를 반환합니다다. 하지만, 각 생성자는 단 한 번만 순회될 수 있을 것입니다.

+ +

위의 예제 코드에 생성자를 적용한 것입니다. 두 코드의 행위는 동일하지만, 생성자를 사용한 쪽이 쓰거나 읽기가 훨씬 쉽습니다. 

+ +
function* makeRangeIterator(start = 0, end = Infinity, step = 1) {
+    let n = 0;
+    for (let i = start; i < end; i += step) {
+        n++;
+        yield i;
+    }
+    return n;
+}
+ +

Iterables

+ +

객체는 값이 {{jsxref("Statements/for...of", "for..of")}} 구조 내에서 반복되는 것 같은 그 반복 동작을 정의하는 경우 반복이 가능(iterable)합니다. {{jsxref("Array")}} 또는 {{jsxref("Map")}}과 같은 일부 내장 형은 기본 반복 동작이 있지만 다른 형(가령 {{jsxref("Object")}})은 없습니다.

+ +

반복가능하기 위해서, 객체는 @@iterator 메서드를 구현해야 합니다. 즉, 객체( 혹은 그 프로토타입 체인에 등장하는 객체 중 하나)가 {{jsxref("Symbol.iterator")}} 키를 갖는 속성이 있어야 함을 뜻합니다.

+ +

하나의 iterable은 단 한 번, 혹은 여러번 반복가능합니다. 어떤 순간에 어떻게 사용할 지는 프로그래머에게 달려있습니다. 단 한 번 반복가능한 iterable(e.g. Generator)은 관습적으로 자신의 @@iterator 메소드로부터 this를 반환합니다. 반면, 여러 번 반복 가능한 iterables은 @@iterator 메소드가 호출되는 매 회 새로운 iterator를 반드시 반환해야합니다. 

+ +

사용자 정의 iterable

+ +

이와 같이 자신의 반복가능 객체를 만들 수 있습니다:

+ +
var myIterable = {
+    *[Symbol.iterator]() {
+        yield 1;
+        yield 2;
+        yield 3;
+    }
+}
+
+for (let value of myIterable) {
+    console.log(value);
+}
+// 1
+// 2
+// 3
+
+or
+
+[...myIterable]; // [1, 2, 3]
+ +

내장 iterable

+ +

{{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}} 및 {{jsxref("Set")}}은 모두 내장 반복가능 객체입니다, 그들의 프로토타입 객체가 모두 {{jsxref("Symbol.iterator")}} 메서드가 있기 때문입니다.

+ +

iterable을 기대하는 구문

+ +

일부 문(statement) 및 식(expression)은 iterable합니다, 가령 {{jsxref("Statements/for...of","for-of")}} 루프, {{jsxref("Operators/Spread_operator","spread syntax","","true")}}, {{jsxref("Operators/yield*","yield*")}} 및 {{jsxref("Operators/Destructuring_assignment","해체 할당","","true")}}.

+ +
for(let value of ['a', 'b', 'c']){
+    console.log(value)
+}
+// "a"
+// "b"
+// "c"
+
+[...'abc'] // ["a", "b", "c"]
+
+function* gen(){
+  yield* ['a', 'b', 'c']
+}
+
+gen().next() // { value:"a", done:false }
+
+[a, b, c] = new Set(['a', 'b', 'c'])
+a // "a"
+
+
+
+ +

Generator 심화

+ +

 생성자 함수는 요청에 따라 그 산출된(yielded, yield 식으로 산출된) 값을 계산하고, 계산하기 비싼(힘든) 수열 또는 위에 설명한 대로 무한 수열이라도 효율적으로 나타내게 합니다.

+ +

{{jsxref("Global_Objects/Generator/next","next()")}} 메서드는 또한 생성기의 내부 상태를 수정하는 데 쓰일 수 있는 값을 받습니다. next()에 전달되는 값은 생성기가 중단된 마지막 yield 식의 결과로 처리됩니다.

+ +

여기 sequence(수열)을 재시작하기 위해 next(x)를 사용하는 피보나치 생성기가 있습니다:

+ +
function* fibonacci(){
+  var fn1 = 0;
+  var fn2 = 1;
+  while (true){
+    var current = fn1;
+    fn1 = fn2;
+    fn2 = current + fn1;
+    var reset = yield current;
+    if (reset){
+        fn1 = 0;
+        fn2 = 1;
+    }
+  }
+}
+
+var sequence = fibonacci();
+console.log(sequence.next().value);     // 0
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 2
+console.log(sequence.next().value);     // 3
+console.log(sequence.next().value);     // 5
+console.log(sequence.next().value);     // 8
+console.log(sequence.next(true).value); // 0
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 2
+
+ +

You can force a generator to throw an exception by calling its {{jsxref("Global_Objects/Generator/throw","throw()")}} method and passing the exception value it should throw. This exception will be thrown from the current suspended context of the generator, as if the yield that is currently suspended were instead a throwvalue statement.

+ +

If the exception is not caught from within the generator,  it will propagate up through the call to throw(), and subsequent calls to next() will result in the done property being true.

+ +

Generators have a {{jsxref("Global_Objects/Generator/return","return(value)")}} method that returns the given value and finishes the generator itself.

+ +

{{PreviousNext("Web/JavaScript/Guide/Using_promises", "Web/JavaScript/Guide/Meta_programming")}}

diff --git a/files/ko/web/javascript/guide/keyed_collections/index.html b/files/ko/web/javascript/guide/keyed_collections/index.html new file mode 100644 index 0000000000..a206b6556d --- /dev/null +++ b/files/ko/web/javascript/guide/keyed_collections/index.html @@ -0,0 +1,149 @@ +--- +title: 키기반의 컬렉션 +slug: Web/JavaScript/Guide/Keyed_collections +translation_of: Web/JavaScript/Guide/Keyed_collections +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}
+ +

이번 장에서는 입력된 키값을 기준으로 정렬되는 데이터의 집합(자료 구조)에 대해 소개 할 것이다. Map과 Set은 입력된 순서대로 반복적으로 접근 가능한 요소들을 포함하고 있다. 

+ +

Maps

+ +

Map 객체

+ +

ECMAScript 6에서 값들을 매핑하기 위한 새로운 데이터 구조를 소개 하고 있다.  그중 하나인 Map객체는 간단한 키와 값을 서로 연결(매핑)시켜 저장하며 저장된 순서대로 각 요소들을 반복적으로 접근할 수 있도록 한다. 

+ +

다음 코드는 Map이 제공하는 기본적인 기능들을 보여 주고 있다. 더 많은 예제와 모든 기능에 대한 API를 볼려면 {{jsxref("Map")}} 페이지를 참고하면 된다. Map객체에 저장되어 있는 각 요소들을 [키, 값] 형태의 배열로 반복적으로 반환해주는 for...of 를 사용할 수 있다.

+ +
var sayings = new Map();
+sayings.set("dog", "woof");
+sayings.set("cat", "meow");
+sayings.set("elephant", "toot");
+sayings.size; // 3
+sayings.get("fox"); // undefined
+sayings.has("bird"); // false
+sayings.delete("dog");
+
+for (var [key, value] of sayings) {
+  console.log(key + " goes " + value);
+}
+// "cat goes meow"
+// "elephant goes toot"
+
+ +

Object와 Map 비교

+ +

전통적으로 {{jsxref("Object", "objects", "", 1)}} 는 문자열을 값에 매핑하는 데 사용되었다. Object는 키를 값으로 설정하고, 값을 검색하고, 키를 삭제하고, 키에 저장된 내용을 검색 할 수 있게 만들어준다. 그러나 Map 객체는 더 나은 맵이 되도록 하는 몇 가지 장점을 가지고 있다.

+ + + +

Object 혹은 Map중에 어느 것을 사용할지를 결정하는데 도움을 줄 두가지 팁이 있다:

+ + + +

WeakMap object

+ +

{{jsxref("WeakMap")}}객체는  object만을 키로 허용하고 값은 임의의 값을 허용하는  키/값 형태의 요소의 집합이다. 키가 가지고 있는 객체에 대한 참조는 객체에 대한 참조가 더이상 존재하지 않을 경우 garbage collection(GC)의 수거 대상이 되는 약한 참조를 의미한다. WeakMap API는 Map API와 동일하다. 

+ +

단 한가지  Map객체와 다른 점은 WeakMap의 키들은 열거형이 아니라는 점이다. (즉, 키 목록을 제공해 주는 메서드가 없다는 것이다.) 만약에 키 목록을 제공한다면 garbage collection의 상태, 결과에 따라 키 목록이 변하게 될 것이다. 이는 비 결정성을 야기한다. 

+ +

WeakMap에 대한 더 많은 정보와 예제 코드 그리고 "왜 WeakMap을 사용하지?"를 보고 싶다면 {{jsxref("WeakMap")}} 페이지를 참고하면 된다. 

+ +

WeakMap를 사용하는 한가지 경우는 객체의 사적인 정보를 저장하기 위해서 이거나 상세 구현 내용을 숨기기 위한 것이다. 다음의 예제는 Nick Fitzgerald의 블로그 글- "Hiding Implementation Details with ECMAScript 6 WeakMaps"-에서 가져온 것이다. 객체가 가지고 있는 그렇지만 외부에 공개되지 않는(private) 데이터와 메서드들은 WeakMap객체인 privates에 저장이 된다. 인스턴스를 통해 접근 가능한 모든 것들과 prototype은 public이고 다른 것들은 외부에서는 접근이 불가하다 그 이유는 privates는 모듈로부터 내보내기(export)가 되지 않기 때문이다.

+ +
const privates = new WeakMap();
+
+function Public() {
+  const me = {
+    // Private data goes here
+  };
+  privates.set(this, me);
+}
+
+Public.prototype.method = function () {
+  const me = privates.get(this);
+  // Do stuff with private data in `me`...
+};
+
+module.exports = Public;
+
+ +

Sets

+ +

Set object

+ +

{{jsxref("Set")}}객체는 값들의 집합이다. 입력된 순서에따라 저장된 요소를 반복처리할 수 있다. Set은 중복된 값을 허용하지 않는다. 따라서 특정 값은 Set내에서 하나만 존재 하게 된다. 

+ +

아래의 코드는 Set의 기본적인 동작들을 보여 준다. 더 많은 예제와 모든 API는 {{jsxref("Set")}} 참조 페이지를 보면 된다. 

+ +
var mySet = new Set();
+mySet.add(1);
+mySet.add("some text");
+mySet.add("foo");
+
+mySet.has(1); // true
+mySet.delete("foo");
+mySet.size; // 2
+
+for (let item of mySet) console.log(item);
+// 1
+// "some text"
+
+ +

배열과 Set의 상호 변환

+ +

{{jsxref("Array.from")}} 혹은 spread operator를 통해 Set객체를 가지고 {{jsxref("Array")}}을 생성할 수 있다. 또한 Set 생성자는 배열을 인자로 받을 수 있고 해당 배열을 Set객체의 요소로 저장한다. 한번 더 상기시키면 Set객체는 중복된 값을 저장하지 않기때문에 주어진 배열내의 중복된 요소들을 제거되어 Set으로 변환된다. 

+ +
Array.from(mySet);
+[...mySet2];
+
+mySet2 = new Set([1,2,3,4]);
+
+ +

배열과 Set비교

+ +

일반적으로 Javascript에선 배열에 특정 요소의 집합을 저장한다. 하지만 Set객체는 몇가지 이점을 제공한다. 

+ + + +

WeakSet 객체

+ +

{{jsxref("WeakSet")}} objects are collections of objects. An object in the WeakSet may only occur once; it is unique in the WeakSet's collection and objects are not enumerable.

+ +

{{jsxref("WeakSet")}}객체는 객체를 저장하는 일종의 집합이다. WeakSet내의 중복된 객체는 없으며 WeakSet내의 요소를 열거할 수는 없다.  

+ +

{{jsxref("Set")}}과 가장 큰 차이점은 다음과 같다.

+ + + +

WeakSet객체의 사용 사례는 제한되어 있다. 메모리 누수가 발생되지 않기때문에 안전하게 DOM요소를 키로 저장할 수 있고 예를 들면 추적을 위해 DOM요소들을 WeakSet에 저장할 수 있다. 

+ +

 

+ +

Map과 Set의 키와 값의 동치성

+ +

Map객체의 key에 대한 동치성 비교와 Set객체의  값에 대한 동치성 비교 모두 "same-value-zero algorithm"에 근거한다. 

+ + + +

{{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}

diff --git a/files/ko/web/javascript/guide/loops_and_iteration/index.html b/files/ko/web/javascript/guide/loops_and_iteration/index.html new file mode 100644 index 0000000000..4b0ac738b6 --- /dev/null +++ b/files/ko/web/javascript/guide/loops_and_iteration/index.html @@ -0,0 +1,332 @@ +--- +title: 루프와 반복 +slug: Web/JavaScript/Guide/Loops_and_iteration +translation_of: Web/JavaScript/Guide/Loops_and_iteration +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}
+ +

루프는 어떤 것을 반복적으로 시행할때 빠르고 간편한 방법을 제공합니다. JavaScript Guide의 이 항목은 JavaScript 에서 사용이 가능한 서로 다른 여러가지 반복문을 소개합니다.

+ +

반복문을 게임의 컴퓨터화된 버전이라고 생각해 보세요. 누군가에게 한 방향으로 X만큼 가게 시키고 다른 방향으로 Y만큼 더 가게 한다고 생각해 보십시오. 예를들어, "동쪽으로 5만큼 가세요"는 다음과 같이 반복문으로 표현 될 수 있습니다.

+ +
var step;
+for (step = 0; step < 5; step++) {
+  // Runs 5 times, with values of step 0 through 4.
+  console.log('Walking east one step');
+}
+
+ +

반복문은 매우 다양한 종류가 있습니다. 하지만 반복문이 기본적으로 하는일은 모두 같습니다. 반복문은 한 동작을 여러 번 반복합니다. (사실 0회 반복하는 것도 가능합니다.) 다양한 반복문 메커니즘은 다양한 방법으로 반복문의 시작점과 끝나는 점을 정할 수 있습니다.

+ +

자바스크립트가 지원하는 반복문은 다음과 같습니다:

+ + + +

for

+ +

for 반복문은 어떤 특정한 조건이 거짓으로 판별될 때까지 반복합니다. 자바스크립트의 반복문은 C의 반복문과 비슷합니다. for 반복문은 다음과 같습니다.

+ +
for ([초기문]; [조건문]; [증감문])
+  문장
+
+ +

for문이 실행될 때, 다음과 같이 실행됩니다.:

+ +
    +
  1. 초기화 구문인 초기문이 존재한다면 초기문이 실행됩니다. 이 표현은 보통 1이나 반복문 카운터로 초기 설정이 됩니다. 그러나 복잡한 구문으로 표현 될 때도 있습니다. 또한 변수로 선언 되기도 합니다.
  2. +
  3. 조건문은 조건을 검사합니다. 만약 조건문이 참이라면, 그 반복문은 실행됩니다. 만약 조건문이 거짓이라면, 그 for문은 종결됩니다. 만약 그 조건문이 생략된다면, 그 조건문은 참으로 추정됩니다.
  4. +
  5. 문장이 실행됩니다. 많은 문장을 실행할 경우엔, { } 를 써서 문장들을 묶어 줍니다.
  6. +
  7. 갱신 구문인 증감문이 존재한다면 실행되고 2번째 단계로 돌아갑니다.
  8. +
+ +

예시

+ +

다음 함수는 스크롤링 목록(다중 선택을 허용하는 요소 {{HTMLElement("select")}}). 에서 선택된 옵션들을 세는 for문 입니다. 이 for문은 변수 i 를 선언하고 0으로 초기화 시킵니다. 이것은 i 가  <select> 요소 안의 옵션 수가 i 보다 작은지 확인 합니다. 다음의 if문을 수행하고 각 루프를 빠져나간 뒤 i 를 1 증가시킵니다.

+ +
<form name="selectForm">
+  <p>
+    <label for="musicTypes">Choose some music types, then click the button below:</label>
+    <select id="musicTypes" name="musicTypes" multiple="multiple">
+      <option selected="selected">R&B</option>
+      <option>Jazz</option>
+      <option>Blues</option>
+      <option>New Age</option>
+      <option>Classical</option>
+      <option>Opera</option>
+    </select>
+  </p>
+  <p><input id="btn" type="button" value="How many are selected?" /></p>
+</form>
+
+<script>
+function howMany(selectObject) {
+  var numberSelected = 0;
+  for (var i = 0; i < selectObject.options.length; i++) {
+    if (selectObject.options[i].selected) {
+      numberSelected++;
+    }
+  }
+  return numberSelected;
+}
+
+var btn = document.getElementById("btn");
+btn.addEventListener("click", function(){
+  alert('Number of options selected: ' + howMany(document.selectForm.musicTypes))
+});
+</script>
+
+
+ +

do...while

+ +

do...while 문은 특정한 조건이 거짓으로 판별될 때까지 반복합니다. do...while 문은 다음과 같습니다.

+ +
do
+  문장
+while (조건문);
+
+ +

조건문을 확인하기 전에 문장은 한번 실행됩니다. 많은 문장을 실행하기 위해선 { }를 써서 문장들을 묶어줍니다. 만약 조건이 참이라면, 그 문장은 다시 실행됩니다. 매 실행 마지막마다 조건문이 확인됩니다. 만약 조건문이 거짓일 경우, 실행을 멈추고 do...while 문 바로 아래에 있는 문장으로 넘어가게 합니다.

+ +

예시

+ +

다음 예제에서, do 반복문은 최소 한번은 반복됩니다. 그리고 i 가 5보다 작지 않을 때까지 계속 반복됩니다.

+ +
do {
+  i += 1;
+  console.log(i);
+} while (i < 5);
+ +

while

+ +

while 문은 어떤 조건문이 참이기만 하면 문장을 계속해서 수행합니다. while 문은 다음과 같습니다.

+ +
while (조건문)
+  문장
+
+ +

만약 조건문이 거짓이 된다면, 그 반복문 안의 문장은 실행을 멈추고 반복문 바로 다음의 문장으로 넘어갑니다.

+ +

조건문은 반복문 안의 문장이 실행되기 전에 확인 됩니다. 만약 조건문이 참으로 리턴된다면, 문장은 실행되고 그 조건문은 다시 판별됩니다. 만약 조건문이 거짓으로 리턴된다면, 실행을 멈추고 while문 바로 다음의 문장으로 넘어가게 됩니다.

+ +

많은 문장들을 실행하기 위해선, { }를 써서 문장들을 묶어줍니다.

+ +

예시 1

+ +

다음 while 반복문은 n이 3보다 작은 한, 계속 반복됩니다.

+ +
n = 0;
+x = 0;
+while (n < 3) {
+  n++;
+  x += n;
+}
+
+ +

매 반복과 함께, n이 증가하고 x에 더해집니다. 그러므로, x와 n은 다음과 같은 값을 갖습니다.

+ + + +

세번째 경과 후에, n < 3 은 더이상 참이 아니므로, 반복문은 종결됩니다.

+ +

예시 2

+ +

조건문은 항상 거짓이 될지라도 무한 루프는 피해야 합니다. 그렇지 않으면 그 반복문은 영원히 끝나지 않을 것입니다. 아래의 while 문은 조건문이 절대 거짓이 될 수 없으므로 영원히 반복될 것입니다.

+ +
// 다음과 같은 코드는 피하세요.
+while (true) {
+  console.log("Hello, world");
+}
+ +

레이블 문

+ +

레이블은 여러분이 프로그램에서 다른 곳으로 참조할 수 있도록 식별자로 문을 제공합니다. 예를 들어, 여러분은 루프를 식별하기 위해 레이블을 사용하고, 프로그램이 루프를 방해하거나 실행을 계속할지 여부를 나타내기 위해 break나 continue 문을 사용할 수 있습니다.

+ +

레이블 문의 구문은 다음과 같습니다:

+ +
label :
+   statement
+
+ +

레이블  값은 예약어가 아닌 임의의 JavaScript 식별자일 수 있습니다. 여러분이 레이블을 가지고 식별하는 은 어떠한 문이 될 수 있습니다.

+ +

예시

+ +

이 예에서, 레이블 markLoop는 while 루프를 식별합니다.

+ +
markLoop:
+while (theMark == true) {
+   doSomething();
+}
+ +

break

+ +

break문은 반복문, switch문, 레이블 문과 결합한 문장을 빠져나올  때 사용합니다.

+ + + +

break문의 문법은 다음과 같습니다.

+ +
    +
  1. break;
  2. +
  3. break [레이블];
  4. +
+ +

break문의 첫번째 형식은 가장 안쪽의 반복문이나 switch문을 빠져나옵니다. 두번째 형식는 특정한 레이블 문을 빠져나옵니다.

+ +

예시 1

+ +

다음 예

+ +
for (i = 0; i < a.length; i++) {
+  if (a[i] == theValue) {
+    break;
+  }
+}
+ +

예시 2: Breaking to a label

+ +
var x = 0;
+var z = 0
+labelCancelLoops: while (true) {
+  console.log("Outer loops: " + x);
+  x += 1;
+  z = 1;
+  while (true) {
+    console.log("Inner loops: " + z);
+    z += 1;
+    if (z === 10 && x === 10) {
+      break labelCancelLoops;
+    } else if (z === 10) {
+      break;
+    }
+  }
+}
+
+ +

continue 문

+ +

continue 문은 while, do-while, for, 레이블 문을 다시 시작하기 위해 사용될 수 있습니다.

+ + + +

continue 문의 구문은 다음과 같습니다:

+ +
    +
  1. continue;
  2. +
  3. continue label;
  4. +
+ +

예시 1

+ +

다음의 예는 i 값이 3일 때 실행하는 continue 문과 함께 while 루프를 보여줍니다. 따라서, n은 값 1, 3, 7, 12를 취합니다.

+ +
i = 0;
+n = 0;
+while (i < 5) {
+  i++;
+  if (i == 3) {
+    continue;
+  }
+  n += i;
+}
+
+ +

예시 2

+ +

checkiandj 레이블 문은 checkj 레이블 문을 포함합니다. continue가 발생하는 경우, 프로그램은 checkj의 현재 반복을 종료하고, 다음 반복을 시작합니다. 그 조건이 false를 반환 할 때까지 continue가 발생할 때마다, checkj는 반복합니다. false가 반환될 때, checkiandj 문의 나머지 부분은 완료되고, 그 조건이 false를 반환 할 때까지 checkiandj는 반복합니다. false가 반환될 때, 이 프로그램은 다음 checkiandj 문에서 계속됩니다.

+ +

continue가 checkiandj의 레이블을 가지고 있다면, 프로그램은 checkiandj 문 상단에서 계속될 것입니다.

+ +
checkiandj:
+  while (i < 4) {
+    console.log(i);
+    i += 1;
+    checkj:
+      while (j > 4) {
+        console.log(j);
+        j -= 1;
+        if ((j % 2) == 0) {
+          continue checkj;
+        }
+        console.log(j + " is odd.");
+      }
+      console.log("i = " + i);
+      console.log("j = " + j);
+  }
+ +

for...in

+ +

for...in  문은 객체의 열거 속성을 통해 지정된 변수를 반복합니다. 각각의 고유한 속성에 대해, JavaScript는 지정된 문을 실행합니다. for...in 문은 다음과 같습니다:

+ +
for (variable in object) {
+  statements
+}
+
+ +

예시

+ +

다음 함수는 객체와 객체의 이름을 함수의 인수로 취합니다. 그런 다음 모든 객체의 속성을 반복하고 속성 이름과 값을 나열하는 문자열을 반환합니다.

+ +
function dump_props(obj, obj_name) {
+  var result = "";
+  for (var i in obj) {
+    result += obj_name + "." + i + " = " + obj[i] + "<br>";
+  }
+  result += "<hr>";
+  return result;
+}
+
+ +

속성 make와 model을 가진 객체 car의 경우, 결과는 다음과 같습니다:

+ +
car.make = Ford
+car.model = Mustang
+
+ +

배열

+ +

{{jsxref("배열")}} 요소를 반복하는 방법으로 이를 사용하도록 유도될 수 있지만, for...in 문은 숫자 인덱스에 추가하여 사용자 정의 속성의 이름을 반환합니다. 따라서 만약 여러분이 사용자 정의 속성 또는 메서드를 추가하는 등 Array 객체를 수정한다면, 배열 요소 이외에도 사용자 정의 속성을 통해 for...in 문을 반복하기 때문에, 배열을 통해 반복할 때 숫자 인덱스와 전통적인 for 루프를 사용하는 것이 좋습니다.

+ +

for...of

+ +

for...of 문은 각각의 고유한 특성의 값을 실행할 명령과 함께 사용자 지정 반복 후크를 호출하여, 반복 가능한 객체({{jsxref("배열")}}, {{jsxref("Map")}}, {{jsxref("Set")}}, 인수 객체 등을 포함)를 통해 반복하는 루프를 만듭니다.

+ +
for (variable of object) {
+  statement
+}
+ +

다음 예는 for...of 루프와 for...in 루프의 차이를 보여줍니다. 속성 이름을 통해 for...in이 반복하는 동안, for...of은 속성 값을 통해 반복합니다:

+ +
let arr = [3, 5, 7];
+arr.foo = "hello";
+
+for (let i in arr) {
+   console.log(i); // logs "0", "1", "2", "foo"
+}
+
+for (let i of arr) {
+   console.log(i); // logs "3", "5", "7"
+}
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}

diff --git a/files/ko/web/javascript/guide/modules/index.html b/files/ko/web/javascript/guide/modules/index.html new file mode 100644 index 0000000000..b52283a0fc --- /dev/null +++ b/files/ko/web/javascript/guide/modules/index.html @@ -0,0 +1,414 @@ +--- +title: JavaScript modules +slug: Web/JavaScript/Guide/Modules +translation_of: Web/JavaScript/Guide/Modules +--- +
{{jsSidebar("JavaScript Guide")}}{{Previous("Web/JavaScript/Guide/Meta_programming")}}
+ +

이 가이드는 자바스크립트 모듈 구문을 시작하는데 필요한 모든 것을 제공합니다.

+ +

A background on modules

+ +

자바스크립트 프로그램은 꽤 작게 시작되었습니다. 초기에 사용 된 대부분의 스크립트는 독립적인 작업을 수행하여, 필요한 경우 웹 페이지에 약간의 상호 작용을 제공하므로 일반적으로 큰 스크립트가 필요하지 않았습니다. 몇년 후 자바스크립트는 많은 브라우저에서 실행되고 있는 완전한 애플리케이션을 실행할 수 있을 뿐 아니라,  다른 컨텍스트에서 (예를들면 Node.js) 자바스크립트를 사용하게 됩니다.

+ +

따라서 최근 몇 년 동안 자바스크립트 프로그램을 필요에 따라 가져올 수 있는, 별도의 모듈로 분할하기 위한 매커니즘을 제공하는 것에 대해 생각하기 시작했습니다.  node.js는 오랫동안 이러한 능력을 가지고 있었고, 모듈 사용을 가능하게하는 많은 자바스크립트 라이브러리와 프레임워크가 있습니다. (예를들어 RequireJS와 같은 CommonJS 와 AMD기반 모듈 시스템, 더 최근에는 Webpack과 Babel 같은 모듈 기반 시스템이 있습니다.)

+ +

좋은 소식은 최신 브라우저가 기본적으로 모듈 기능을 지원하기 시작했으며, 이것이 이 기사의 전부입니다. 브라우저는 모듈의 로딩을 최적화 할 수 있기 때문에 라이브러리를 사용하는 것보다 더 효율적이며, 클라이언트 측에서의 추가 처리와 여분의 왕복을 모두 해야하는 것 보다 효율적입니다.

+ +

Browser support

+ +

네이티브 자바스크립트 모듈은 import와 export 문(statement)에 의존적이며, 호환성은 다음과 같습니다.

+ +

import

+ +

{{Compat("javascript.statements.import")}}

+ +

export

+ +

{{Compat("javascript.statements.export")}}

+ +

Introducing an example

+ +

모듈 사용법을 설명하기 위해 Github에 간단한 예제 모음을 만들었습니다. 이 예제들은 웹 페이지에 {{htmlelement("canvas")}} 요소(element)를 만들고, 캔버스에 다양한 도형을 그리고, 그린것에 대한 정보를 보고하는 간단한 모듈 집합입니다.

+ +

이것들은 매우 사소한 것이지만, 모듈을 명확하게 설명하기 의해 의도적으로 단순하게 유지중입니다.

+ +
+

주의: 예제를 다운로드하여 로컬에서 실행하려면, 로컬 웹 서버를 통해 예제를 실행해야 합니다.

+
+ +

Basic example structure

+ +

첫 번째 예제(basic-modules)를 보면 다음과 같은 파일 구조가 있습니다.

+ +
index.html
+main.js
+modules/
+    canvas.js
+    square.js
+ +
+

주의: 이 가이드의 모든 예제는 기본적으로 동일한 구조를 가집니다. 위의 내용에 익숙해지시는게 좋습니다.

+
+ +

modules 디렉토리의 두 모듈은 다음과 같습니다.

+ + + +

Exporting module features

+ +

모듈 기능을 사용하려면 먼저 함수를 export 해야 합니다. 이 작업은 export 문(statement)을 사용하여 수행합니다.

+ +

이를 사용하는 가장 쉬운 방법은 모듈 밖으로 내보내려는 항목 앞에 (export를) 배치하는 것입니다. 예를들면 다음과 같습니다.

+ +
export const name = 'square';
+
+export function draw(ctx, length, x, y, color) {
+  ctx.fillStyle = color;
+  ctx.fillRect(x, y, length, length);
+
+  return {
+    length: length,
+    x: x,
+    y: y,
+    color: color
+  };
+}
+ +

functions, var, let, const, class를 내보낼 수 있지만, 최상위 항목이어야 합니다. 예를들어, 함수 안에서 export를 사용할 수 없습니다.

+ +

여러 항목을 내보내는 더 편리한 방법은 모듈 파일 끝에 하나의 export 문을 사용하는 것입니다. 그 다음에 내보내려는 기능들을 쉼표로 구분하여 나열하고 중괄호로 묶습니다.

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

Importing features into your script

+ +

모듈에서 일부 기능을 내보낸 후에는, 이를 사용할 수 있도록 우리가 사용할 스크립트로 가져와야 합니다. 가장 간단한 방법은 다음과 같습니다.

+ +
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
+ +

import 문(statement)을 사용하고, 가져올 목록을 쉼표로 구분하여 나열한 뒤 괄호로 묶습니다. 그 뒤에는 from을 쓰고 모듈 파일의 경로를 작성합니다. (사이트 루트에 연관된 경로로, 우리의 basic-modules 예제는 /js-examples/modules/basic-modules 입니다) main.js에서 이러한 코드를 볼 수 있습니다.

+ +

그러나 우리는 경로를 조금 다르게 작성했습니다. 우리는 "현재 위치"를 의미하는 점(.) 구문을 사용하고 있으며, 그 다음에 찾고자하는 파일의 경로를 뒤에 써 줍니다. 이것은 상대적으로 전체 상대 경로를 작성하는 것보다 훨씬 빠르며, URL이 더 짧아 지므로 사이트 계층 구조의 다른 위치로 이동하더라도 이 예제가 계속 작동합니다.

+ +

예를들면,

+ +
/js-examples/modules/basic-modules/modules/square.js
+ +

이렇게 쓸 수 있습니다.

+ +
./modules/square.js
+ +

main.js에서 이러한 코드를 볼 수 있습니다.

+ +
+

주의: 일부 모듈 시스템에서는 파일 확장명을 생략할 수 있습니다. (예: '/modules/square'). 이것은 네이티브 자바스크립트에서는 작동하지 않습니다. 또한 앞에 슬래시를 포함해야 합니다.

+
+ +

우리의 스크립트에 기능을 가져오면 동일한 파일 내에 정의한 것처럼 기능을 사용할 수 있습니다. 다음은 main.js 의 import 행 아래에 있습니다.

+ +
let myCanvas = create('myCanvas', document.body, 480, 320);
+let reportList = createReportList(myCanvas.id);
+
+let square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
+reportArea(square1.length, reportList);
+reportPerimeter(square1.length, reportList);
+
+ +

Applying the module to your HTML

+ +

이제 main.js 모듈을 HTML 페이지에 적용하면 됩니다. 이는 몇 가지 주목할만한 차이점을 제외하면 HTML페이지에 일반 스크립트를 적용하는것과 매우 유사합니다.

+ +

이 스크립트를 모듈로 선언하려면 {{htmlelement("script")}} 요소(element)에 type="module" 을 포함시켜야 합니다.

+ +
<script type="module" src="main.js"></script>
+ +

기본적으로 모듈 기능을 가져오는 스크립트는 최상위 모듈로 작동합니다. 이를 생략하면 파이어폭스로 예를들면, "SyntaxError: import declarations may only appear at top level of a module"라는 오류를 줍니다.

+ +

import 와 export 문(statement)은 모듈 내에서만 사용할 수 있습니다. 정규 스크립트가 아닙니다.

+ +
+

주의: type="module"을 포함하면 인터널 스크립트에서도 import 모듈을 사용할 수 있습니다. 예: <script type="module"> /* 여기에 코드를 작성하세요 */ </script>.

+
+ +

Other differences between modules and standard scripts

+ + + +

Default exports versus named exports

+ +

지금까지 우리가 export 한 기능은 named exports 로 구성되었습니다. 각 항목(function, const 등)은 export 할 때 이름으로 참조되었으며, import 할 때에 이 이름을 참조하여 사용합니다.

+ +

그 외에도 default export 라고 부르는 export 도 있습니다. 이것은 모듈이 제공하는 기본 기능을 쉽게 만들 수 있도록 설계되었습니다. 또한 자바스크립트 모듈을 기존의 CommonJS 와 AMD 모듈 시스템과 함께 사용(interpolate)하는데도 도움이 됩니다. (Jason Orendorff에 의해 작성된 ES6 In Depth: Modules 에 설명되어있습니다. "Default exports"를 검색해보세요)

+ +

예제를 가지고 어떻게 작동하는지 살펴보겠습니다. 예제 중 basic-modules 프로젝트의 square.js 파일에서 임의의 색상, 크기, 위치로 갖는 사각형을 만드는 randomSquare() 라는 함수를 찾을 수 있습니다. 이것을 기본값으로 export하려고 하므로, 파일의 맨 아래에 다음과 같이 씁니다.

+ +
export default randomSquare;
+ +

중괄호가 없음에 주의하세요.

+ +

대신 함수 앞에 export default 를 추가하고, 다음과 같이 익명함수로 선언할 수 있습니다.

+ +
export default function(ctx) {
+  ...
+}
+ +

main.js 파일에서 다음 코드처럼 사용하면, default function이 import 됩니다.

+ +
import randomSquare from './modules/square.js';
+ +

다시 말하지만, 중괄호가 없다는 점에 유의하세요. 하나의 모듈은 하나의 default export만 허용하기 때문에 우리는 randomSquare 가 해당 모듈임을 알 수 있습니다. 위의 코드는 아래의 코드를 단축하여 사용한 것입니다.

+ +
import {default as randomSquare} from './modules/square.js';
+ +
+

주의: export한 항목의 이름을 바꾸는 구문은 {{anch("Renaming imports and exports")}} 섹션에서 설명합니다.

+
+ +

Avoiding naming conflicts

+ +

지금까지 우리의 캔버스 도형 그리기 모듈은 제대로 작동하는 것 같습니다. 원이나 삼각형처럼 다른 도형을 그리는 모듈을 추가하려고 하면 어떻게 될까요? 이 도형(shape)에는 아마도 draw(), reportArea() 등과 같은 관련 함수가 있을 것입니다. 동일한 이름의 여러 함수를 동일한 최상위 모듈로 가져오려고 하면, 충돌과 에러가 발생합니다.

+ +

다행스럽게도 이 문제를 해결할 수 있는 여러가지 방법이 있습니다. 다음 섹션에서 이 내용을 살펴보겠습니다.

+ +

Renaming imports and exports

+ +

import 와 export 문(statement)의 중괄호 안에 as 키워드를 새 함수의 이름으로 함께 사용하여, 최상위 모듈 내부의 함수들을 식별 가능한 이름으로 변경할 수 있습니다.

+ +

예를들어 다음 두 가지 방법은 약간의 차이가 있지만, 두 방법 모두 동일한 작업을 수행하고 있습니다.

+ +
// inside module.js
+export {
+  function1 as newFunctionName,
+  function2 as anotherNewFunctionName
+};
+
+// inside main.js
+import { newFunctionName, anotherNewFunctionName } from './modules/module.js';
+ +
// inside module.js
+export { function1, function2 };
+
+// inside main.js
+import { function1 as newFunctionName,
+         function2 as anotherNewFunctionName } from './modules/module.js';
+ +

실제 사례를 살펴보겠습니다. renaming 디렉토리에서 원과 삼각형을 그리고 보고하기 위해 circle.js 와 triangle.js 모듈을 추가한다는 점만 제외하면, 앞의 예와 동일한 모듈 시스템을 볼 수 있습니다.

+ +

이 모듈듈 각각에는 내부적으로 동일한 이름의 기능이 있습니다. 따라서 각각 하단에 동일한 export 문(statement)이 있습니다.

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

이것들을 main.js에 가져올 때 우리는 다음과 같이 시도할 수 있습니다.

+ +
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
+import { name, draw, reportArea, reportPerimeter } from './modules/circle.js';
+import { name, draw, reportArea, reportPerimeter } from './modules/triangle.js';
+ +

위와같이 적으면 브라우저에서 "SyntaxError: redeclaration of import name"과 같은 오류가 발생합니다. (Firefox).

+ +

대신 import가 고유하도록(식별 가능하도록) 이름을 변경해야 합니다.

+ +
import { name as squareName,
+         draw as drawSquare,
+         reportArea as reportSquareArea,
+         reportPerimeter as reportSquarePerimeter } from './modules/square.js';
+
+import { name as circleName,
+         draw as drawCircle,
+         reportArea as reportCircleArea,
+         reportPerimeter as reportCirclePerimeter } from './modules/circle.js';
+
+import { name as triangleName,
+        draw as drawTriangle,
+        reportArea as reportTriangleArea,
+        reportPerimeter as reportTrianglePerimeter } from './modules/triangle.js';
+ +

다음과 같이 import하는 파일 대신 모듈 파일에서 문제를 해결할 수도 있습니다.

+ +
// in square.js
+export { name as squareName,
+         draw as drawSquare,
+         reportArea as reportSquareArea,
+         reportPerimeter as reportSquarePerimeter };
+ +
// in main.js
+import { squareName, drawSquare, reportSquareArea, reportSquarePerimeter } from './modules/square.js';
+ +

그리고 이것은 똑같이 작동 할 것입니다. 사용하는 스타일은 개인의 취향이지만, 모듈 코드를 그대로 두고 import 를 변경하는 것이 더 합리적입니다. 특히 제어 권한이 없는 써드 파티 모듈에서 import를 사용하는 경우에 특히 유용합니다.

+ +

Creating a module object

+ +

위의 방법은 정상적으로 작동하지만, 다소 지저분하고 길어질 수 있습니다. 보다 나은 해결책은 각 모듈의 기능을 모듈 객체 내부로 가져오는 것입니다. 다음과 같은 구문을 사용합니다.

+ +
import * as Module from './modules/module.js';
+ +

이 모듈은 module.js 내에서 사용할 수 있는 모든 export를 가져옵니다. 그리고 그것들을 객체 Module 의 멤버로 만들고 우리 임의의 효과적인 네임스페이스를 제공합니다.

+ +
Module.function1()
+Module.function2()
+etc.
+ +

다시 한 번 실제 사례를 살펴보겠습니다. module-objects 디렉토리로 가면 같은 예제를 볼 수 있지만, 새로운 구문을 이용하기 위해 다시 작성합니다. 모듈에서 export는 모두 다음과 같은 간단한 형식으로 이루어집니다.

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

반면에 import는 다음과 같습니다.

+ +
import * as Canvas from './modules/canvas.js';
+
+import * as Square from './modules/square.js';
+import * as Circle from './modules/circle.js';
+import * as Triangle from './modules/triangle.js';
+ +

각각의 경우에, 지정한 객체 이름 아래에 있는 모듈의 import에 접근할 수 있습니다. 다음은 그 예시입니다.

+ +
let square1 = Square.draw(myCanvas.ctx, 50, 50, 100, 'blue');
+Square.reportArea(square1.length, reportList);
+Square.reportPerimeter(square1.length, reportList);
+ +

따라서 이제는 이전과 똑같은 코드를 작성할 수 있습니다. (필요한 경우 객체 이름을 포함해야 합니다) import는 보다 깔끔해졌습니다.

+ +

Modules and classes

+ +

이전에 암시 했듯이 class를 export하거나 import 할 수도 있습니다. 이것은 코드에서 충돌을 피하기 위한 또 다른 옵션으로, 모듈 코드가 이미 객체 지향 스타일로 작성된 경우에 특히 유용합니다.

+ +

우리의 classes 디렉토리에서 ES 클래스로 다시 작성된 도형 그리기 모듈의 예를 볼 수 있습니다. 예를들어 square.js 파일에는 모든 기능이 단일 클래스에 포함되어 있습니다.

+ +
class Square {
+  constructor(ctx, listId, length, x, y, color) {
+    ...
+  }
+
+  draw() {
+    ...
+  }
+
+  ...
+}
+ +

우리는 다음과 같이 export 합니다.

+ +
export { Square };
+ +

main.js 에서 우리는 다음과 같이 import 합니다.

+ +
import { Square } from './modules/square.js';
+ +

그런다음 클래스를 이용하여 사각형을 그립니다.

+ +
let square1 = new Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
+square1.draw();
+square1.reportArea();
+square1.reportPerimeter();
+ +

Aggregating modules

+ +

모듈을 모아야 할 때가 있을 것입니다. 여러 서브 모듈을 하나의 부모 모듈로 결합하여 여러 단계의 종속성을 가질 수 있습니다. 상위 모듈에서 다음 양식의 export 구문을 사용하할 수 있습니다.

+ +
export * from 'x.js'
+export { name } from 'x.js'
+ +
+

주의: 이것은 실제로 import 의 줄임말이고, 그 뒤에 export가 옵니다. 예를들면, "나는 모듈 x.js를 가져온 다음, 일부 또는 전부를 export 하겠다" 라는 뜻입니다.

+
+ +

예를들어 module-aggregation 디렉토리를 참조하겠습니다. 이 예제에서는 이전 클래스 예제를 기반으로 circle.js, square.js, triangle.js 의 모든 기능을 함께 모으는 shapes.js라는 추가 모듈이 있습니다. 또한 우리는 shapes 모듈 디렉토리 안에 있는 서브 디렉토리 내에서 서브 모듈을 이동 시켰습니다. 이제 모듈 구조는 다음과 같습니다.

+ +
modules/
+  canvas.js
+  shapes.js
+  shapes/
+    circle.js
+    square.js
+    triangle.js
+ +

각 하위 모듈에서 export 형태는 같습니다. 예)

+ +
export { Square };
+ +

다음은 집합(aggregation) 부분입니다. shapes.js 안에는 다음과 같은 내용이 포함되어 있습니다.

+ +
export { Square } from './shapes/square.js';
+export { Triangle } from './shapes/triangle.js';
+export { Circle } from './shapes/circle.js';
+ +

이 모듈은 각각의 서브 모듈의 export를 가져와서 shapes.js 모듈에서 효과적으로 사용할 수 있도록 합니다.

+ +
+

주의: shapes.js 에서 참조되는 export는 기본적으로 파일을 통해 리다이렉트 되고 실제로는 존재하지 않으므로, 같은 파일 내에 유용한 코드를 쓸 수 없습니다.

+
+ +

이제 main.js 파일에서 우리는 세 개의 모듈 클래스를 모두 대체할 수 있습니다.

+ +
import { Square } from './modules/square.js';
+import { Circle } from './modules/circle.js';
+import { Triangle } from './modules/triangle.js';
+ +

다음과 같은 한 줄로 작성할 수 있습니다.

+ +
import { Square, Circle, Triangle } from '/js-examples/modules/module-aggregation/modules/shapes.js';
+ +

Dynamic module loading

+ +

브라우저에서 사용할 수 있는 자바스크립트 모듈 기능의 최신 부분은 동적 모듈 로딩 입니다. 이렇게 하면 모든 것을 최상위에서 불러오지 않고, 필요할 때만 모듈을 동적으로 불러올 수 있습니다. 이것은 몇 가지 분명한 성능 이점이 있습니다. 계속 읽어보고 어떻게 작동하는지 살펴봅시다.

+ +

이 새로운 기능을 통해 import() 를 함수로 호출하여 모듈 경로를 매개 변수(parameter)로 전달할 수 있습니다. 모듈 객체({{anch("Creating a module object")}} 참조)를 사용하여 promise를 반환하면 해당 객체의 export에 접근할 수 있습니다. 

+ +
import('/modules/myModule.js')
+  .then((module) => {
+    // Do something with the module.
+  });
+ +

예제를 보겠습니다. In the dynamic-module-imports 디렉토리에는 classes 예제를 기반으로 한 또 다른 예제가 있습니다. 이번에는 예제가 로딩될 때 캔버스에 아무것도 그리지 않습니다. 대신 우리는 세 개의 버튼("Circle", "Square", "Triangle")이 포함되어 있습니다. 이 버튼을 누르면 필요한 모듈을 동적으로 불러온 다음, 이를 사용하여 연관된 도형을 그립니다.

+ +

이 예제에서 우리는 index.html 파일과 main.js 파일만 변경했습니다. 모듈 export는 이전과 동일하게 유지됩니다.

+ +

main.js 에서 document.querySelector() 를 사용하여 각 버튼에 대한 참조를 가져왔습니다. 예를들면 다음과 같습니다.

+ +
let squareBtn = document.querySelector('.square');
+ +

그런 다음 각 버튼에 이벤트 리스너를 연결하여 해당 모듈을 누르면, 동적으로 로드되어 도형을 그리는데 사용됩니다.

+ +
squareBtn.addEventListener('click', () => {
+  import('/js-examples/modules/dynamic-module-imports/modules/square.js').then((Module) => {
+    let square1 = new Module.Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
+    square1.draw();
+    square1.reportArea();
+    square1.reportPerimeter();
+  })
+});
+ +

Note that, promise fulfillment 가 모듈 객체를 반환하기 때문에 클래스는 객체의 하위 기능으로 만들어집니다. 따라서 이제 Module 을 사용하여 생성자(contructor)에 접근해야 합니다. 예를들어 Module.Square( ... ) 와 같이 앞에 Module이 붙습니다.

+ +

See also

+ + + +

{{Previous("Web/JavaScript/Guide/Meta_programming")}}

diff --git a/files/ko/web/javascript/guide/numbers_and_dates/index.html b/files/ko/web/javascript/guide/numbers_and_dates/index.html new file mode 100644 index 0000000000..6a45e1ef7f --- /dev/null +++ b/files/ko/web/javascript/guide/numbers_and_dates/index.html @@ -0,0 +1,384 @@ +--- +title: 숫자와 날짜 +slug: Web/JavaScript/Guide/Numbers_and_dates +tags: + - JavaScript +translation_of: Web/JavaScript/Guide/Numbers_and_dates +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}
+ +

이 장에서는 JavaScript에서 숫자와 날짜를 사용하기 위한 개념과 객체, 함수에 대해 소개합니다. 그리고 숫자를 10진법, 2진법, 16진법 등의 다양한 형태로 표현하는 방법과 더불어 {{jsxref("Math")}} 객체를 사용해 다양한 수학 연산을 수행하는 방법을 알 수 있습니다.

+ +

숫자

+ +

JavaScript에서 모든 숫자는 double-precision 64-bit binary format IEEE 754 (즉, ±2−1022 과 ±2+1023 또는 대략 ±10−308 to ±10+308 사이의 숫자이며 53bits의 수치정밀도 )로 구현되어 있습니다. ± 253 - 1까지의 정수 값을 정확하게 나타낼 수 있습니다.

+ +

여기 부동 소수점 숫자를 나타낼 수 있으며, 숫자 형식은 세 개의 상징적인 값: +{{jsxref("Infinity")}}, -{{jsxref("Infinity")}}, and {{jsxref("NaN")}} (숫자가 아닌 값)을 갖습니다.

+ +

JavaScript에 최근 추가 된 것은 {{jsxref ( "BigInt")}}로, 매우 큰 정수를 나타낼 수 있습니다. BigInt를사용할땐 다음을 주의해야 합니다. 예를 들면, BigInt와 {{jsxref ( "Number")}} 값을 같은 연산으로 혼합하고 일치시킬 수는 없으며 {{jsxref ( "Math")}} 객체를 BigInt값과 함께 사용할 수 없습니다.

+ +

JavaScript에서 다른 기본형과 문맥에 대한 내용은 JavaScript data types and structures를 참조하세요.

+ +

여러분은 숫자 리터럴의 네 가지 유형을 사용할 수 있습니다: 10진수, 2진수, 8진수, 16진수

+ +

10진수

+ +
1234567890
+42
+
+// 앞에 0이 붙은 숫자를 조심하세요:
+
+0888 // 10진수 888로 해석됩니다.
+0777 // non-strict mode에서 10진수 511로 해석됩니다.
+
+ +

10진수 리터럴도 영(0)으로 시작될 수 있다는 점에 유의하세요. 그러나 만약 영0 다음 숫자가 8보다 작으면, 그 숫자는 8진법으로 해석됩니다.

+ +

2진수

+ +

2진수 구문은 앞에 오는 0과 소문자 또는 대문자 라틴 문자 "B"(0B 또는 0b)를 사용합니다. 0b 다음의 숫자가 0 또는 1이 아니면 다음의 SyntaxError가 발생합니다. "0b 이후에 누락 된 2 진수"("Missing binary digits after 0b")입니다.

+ +
var FLT_SIGNBIT  = 0b10000000000000000000000000000000; // 2147483648
+var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
+var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607
+ +

8진수

+ +

8 진수 구문은 앞에 0을 사용합니다. 0 이후의 숫자가 0에서 7까지 범위 밖에 있는 경우, 숫자는 10진수로 해석됩니다.

+ +
var n = 0755; // 493
+var m = 0644; // 420
+
+ +

ECMAScript 5의 Strict 모드는 8 진수 구문을 금지합니다. 8 진수 구문은 ECMAScript 5의 일부가 아니지만, 0644 === 420"\ 045"=== "%"의 8 진수에 접두사를 붙이면 모든 브라우저에서 지원됩니다. ECMAScript 2015에서는 접두어가 0o인 경우 8 진수가 지원됩니다 (예 :

+ +
var a = 0o10; // ES2015: 8
+ +

16진수

+ +

16진수 구문은 앞에 0 다음에 소문자나 대문자 라틴어 문자 "X"(0x 또는 0X)를 사용합니다. 0X 이후 숫자가 범위(0123456789ABCDEF) 밖에 있는 경우, 다음 SyntaxError가 발생합니다: "식별자는 숫자 리터럴 후 즉시 시작됩니다".

+ +
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
+0x123456789ABCDEF   // 81985529216486900
+0XA                 // 10
+
+ +

지수 계산

+ +
1E3   // 1000
+2e6   // 2000000
+0.1e2 // 10
+
+ +

Number 객체

+ +

{{jsxref("Number")}} 내장객체는 최대값, not-a-number, 무한대와 같은 숫자 상수를 위한 속성들이 있습니다. 여러분은 이러한 속성의 값을 변경 할 수 없고 다음과 같이 사용합니다:

+ +
var biggestNum = Number.MAX_VALUE;
+var smallestNum = Number.MIN_VALUE;
+var infiniteNum = Number.POSITIVE_INFINITY;
+var negInfiniteNum = Number.NEGATIVE_INFINITY;
+var notANum = Number.NaN;
+
+ +

여러분은 직접 생성한 Number 객체의 속성이 아닌, 위와같이 항상 미리 정의된 Number 객체의 속성을 참조해야합니다.

+ +

다음 표에서는 Number 객체의 속성이 요약되어 있습니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Number 속성들
특성묘사
{{jsxref("Number.MAX_VALUE")}}표현가능한 가장 큰 수 (±1.7976931348623157e+308)
{{jsxref("Number.MIN_VALUE")}}표현가능한 가장 작은 수(±5e-324)
{{jsxref("Number.NaN")}}"숫자가 아닌" 특수값
{{jsxref("Number.NEGATIVE_INFINITY")}}음의 무한대값; 오버 플로로 반환됨.
{{jsxref("Number.POSITIVE_INFINITY")}}양의 무한대 값; 오버 플로로 반환됨.
{{jsxref("Number.EPSILON")}}표현가능한 매우 작은 값{{jsxref("Number")}}.(2.220446049250313e-16)
{{jsxref("Number.MIN_SAFE_INTEGER")}}자바스크립트에서 안전한 최소의 정수.(−253 + 1, or −9007199254740991)
{{jsxref("Number.MAX_SAFE_INTEGER")}}자바스크립트에서 안전한 최대의 정수.(+253 − 1, or +9007199254740991)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Number 메소드들
방법묘사
{{jsxref("Number.parseFloat()")}} +

문자열 인수를 파싱하고 부동 소수점 숫자를 반환합니다. 전역 {{jsxref("parseFloat", "parseFloat()")}} 함수와 동일합니다.

+
{{jsxref("Number.parseInt()")}}문자열 라인 인수를 파싱해, 지정된 기수 또는 밑줄의 정수를 돌려줍니다. 전역 {{jsxref("parseInt", "parseInt()")}}함수와 동일합니다.
{{jsxref("Number.isFinite()")}}전달된 값이 유한한 수인지 판정합니다.
{{jsxref("Number.isInteger()")}}전달된 값이 정수인지 판정합니다.
{{jsxref("Number.isNaN()")}}이 전달된 값 {{jsxref("Global_Objects/NaN", "Not-a-Number")}}여부를 확인합니다. 원본 글로벌 {{jsxref("Global_Objects/isNaN", "(isNaN)")}}의 더욱 강력한 버전입니다.
{{jsxref("Number.isSafeInteger()")}}제공된 값이 안전한 정수인지 여부를 확인합니다.
+ +

Number 프로토 타입은 다양한 형식의 Number 객체에서 정보를 검색하는 메소드를 제공합니다. 다음 표는 Number.prototype의 메소드를 요약 한 것입니다.

+ + + + + + + + + + + + + + + + + + + + + + + +
Number.prototype의 방법
방법Description
{{jsxref("Number.toExponential", "toExponential()")}}지수표기법 안에서 번호를 나타내는 문자열을 반환합니다.
{{jsxref("Number.toFixed", "toFixed()")}}문자열 고정 소수 점 표기법의 수를 나타내는 문자열을 반환합니다.
{{jsxref("Number.toPrecision", "toPrecision()")}}지정된 정밀에 고정 소수 점 표기법의 수를 나타내는 문자열을 반환합니다.
+ +

Math 객체

+ +

내장 {{jsxref ( "Math")}} 객체는 수학 상수 및 함수에 대한 속성 및 메서드를 포함합니다. 예를 들어, Math 객체의 PI 속성에는 pi (3.141 ...) 값이 있습니다.이 값은 응용 프로그램에서 다음과 같이 사용합니다.

+ +
Math.PI
+
+ +

마찬가지로 표준 수학 함수도 Math의 함수입니다. 여기에는 삼각 함수, 로그 함수, 지수 함수 및 기타 함수가 포함됩니다. 예를 들어 삼각 함수 sine을 사용하려면 다음과 같이 작성합니다.

+ +
Math.sin(1.56)
+
+ +

Math의 모든 삼각 함수에는 라디안으로 매게변수를 입력해야 합니다.

+ +

다음 표에서는 Math 개체의 방법을 요약하였습니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Math의 메소드들
방법묘사
{{jsxref("Math.abs", "abs()")}}절대 값
{{jsxref("Math.sin", "sin()")}}, {{jsxref("Math.cos", "cos()")}}, {{jsxref("Math.tan", "tan()")}}표준 삼각 함수; 라디안에서의 인수
{{jsxref("Math.asin", "asin()")}}, {{jsxref("Math.acos", "acos()")}}, {{jsxref("Math.atan", "atan()")}}, {{jsxref("Math.atan2", "atan2()")}}역삼각 함수; 라디안에 반환 값
{{jsxref("Math.sinh", "sinh()")}}, {{jsxref("Math.cosh", "cosh()")}}, {{jsxref("Math.tanh", "tanh()")}}쌍곡삼각함수; 라디안에 반환 값.
{{jsxref("Math.asinh", "asinh()")}}, {{jsxref("Math.acosh", "acosh()")}}, {{jsxref("Math.atanh", "atanh()")}}역쌍곡삼각함수; 라디안에 반환 값.
+

{{jsxref("Math.pow", "pow()")}}, {{jsxref("Math.exp", "exp()")}}, {{jsxref("Math.expm1", "expm1()")}}, {{jsxref("Math.log10", "log10()")}}, {{jsxref("Math.log1p", "log1p()")}}, {{jsxref("Math.log2", "log2()")}}

+
지수와 로그 기능.
{{jsxref("Math.floor", "floor()")}}, {{jsxref("Math.ceil", "ceil()")}} 가장큰/가장작은 정수 보다 적은/많은 또는 그와 동등한 원칙으로 반환해라.
{{jsxref("Math.min", "min()")}}, {{jsxref("Math.max", "max()")}}더적거나 더많은 쉼표의 (각각) 숫자 인수의 나뉜목록으로 반환해라.
{{jsxref("Math.random", "random()")}}0과 1사이의 난수를 반환해라.
{{jsxref("Math.round", "round()")}}, {{jsxref("Math.fround", "fround()")}}, {{jsxref("Math.trunc", "trunc()")}},반올림과 절단 기능들.
{{jsxref("Math.sqrt", "sqrt()")}}, {{jsxref("Math.cbrt", "cbrt()")}}, {{jsxref("Math.hypot", "hypot()")}}제곱 근, 세 제곱 근, 평방 인수의 합의 제곱 근.
{{jsxref("Math.sign", "sign()")}}그 수가 양수인지 음수인지 0인지를 가르키는 숫자의 표시.
{{jsxref("Math.clz32", "clz32()")}},
+ {{jsxref("Math.imul", "imul()")}}
32비트 이진 표시의 주요 제로 비트 수.
+ 그 두 인수의 C-like 32비트 곱셈의 결과.
+ +

다른 많은 객체와 달리 자신의 Math 개체를 만들필요가 없습니다. 언제든 내장 된 Math 객체 바로 사용할 수 있습니다.

+ +

Date 객체

+ +

자바스크립트에는 날짜 데이터 타입이 없습니다. 그러나, {{jsxref ( "Date")}} 객체와 그 메소드를 사용하여 응용 프로그램에서 날짜와 시간을 처리 할 수 ​​있습니다. Date 객체에는 날짜 설정, 가져 오기 및 조작을위한 많은 메소드가 있습니다. 속성(properties)이 없습니다.

+ +

자바스크립트는 자바와 비슷하게 날짜를 처리합니다. 두 언어에는 동일한 날짜 메소드가 많으며 두 언어 모두 1970 년 1 월 1 일 00:00:00 이후의 밀리 초 수로 날짜를 저장합니다. 유닉스 타임 스탬프는 1970 년 1 월 1 일 00:00:00 이후의 초 수입니다.

+ +

Date 개체 범위는 UTC 1970 년 1 월 1 일을 기준으로 -100,000,000 일에서 100,000,000 일입니다.

+ +

Date 객체를 만들려면 :

+ +
var dateObjectName = new Date([parameters]);
+
+ +

여기서 dateObjectName은 만들려는 Date 객체의 이름입니다. 새로운 객체 또는 기존 객체의 속성 일 수 있습니다.

+ +

new 키워드없이 Date를 호출하면 현재 날짜와 시간을 나타내는 문자열이 반환됩니다.

+ +

앞 구문에서 parameters는 아래 규칙을 따릅니다.

+ + + +

Data 개체의 표현 방법

+ +

날짜와 시간을 조절하는 Date객체표현 방법은 아래 종류로 나뉩니다:

+ + + +

"get"및 "set"메소드를 사용하여 초, 분,시, 일, 요일, 월 및 연도를 별도로 가져 와서 설정할 수 있습니다. 요일이 자동적으로 설정되기 (위해) 때문에, 요일을 돌려주는 getDay 메소드가 있습니다만, 대응하는 setDay 메소드는 없습니다. 이러한 메서드는 정수를 사용하여 다음과 같이 값을 나타냅니다.

+ + + +

예를 들어, 아래와 같이 값들을 정의해봅시다 :

+ +
var Xmas95 = new Date("December 25, 1995");
+
+ +

그러면 Xmas95.getMonth()는 11을 반환합니다, 그리고 Xmas95.getFullYear()는 1995를 반환합니다.

+ +

getTimesetTime방법들은 날짜를 나눌때 유용합니다. getTime함수는 Date객체에 대해 1970년 1월 1일 00:00시부터 밀리초단위로 리턴합니다.

+ +

예를 들어, 다음 코드는 현재 년도에 남아 수를 표시합니다:

+ +
var today = new Date();
+var endYear = new Date(1995, 11, 31, 23, 59, 59, 999); // Set day and month
+endYear.setFullYear(today.getFullYear()); // Set year to this year
+var msPerDay = 24 * 60 * 60 * 1000; // Number of milliseconds per day
+var daysLeft = (endYear.getTime() - today.getTime()) / msPerDay;
+var daysLeft = Math.round(daysLeft); //returns days left in the year
+
+ +

이 예제에는 오늘 날짜가 포함된 today라는 명칭을 가진 Date객체를 만듭니다. 그리고 나서 endYear라는 Date객체를 만들고 현재연도를 설정합니다. 그런 다음 하루에 밀리 초 수를 사용하여 getTime을 사용하고 전체 일 수를 반올림하여 todayendYear 사이의 일 수를 계산합니다.

+ +

Parse 함수는 날짜문자열부터 기존의 Date객체까지의 값을 할당하기에 유용합니다. 예를 들어, 다음 코드는 그 IPOdate 객체에 날짜값을 할당하기위해 parsesetTime을 사용합니다;

+ +
var IPOdate = new Date();
+IPOdate.setTime(Date.parse("Aug 9, 1995"));
+
+ +

예제

+ +

다음 예제 에서 JSClock()는 digital 시계형식의 시간을 반환합니다.

+ +
function JSClock() {
+  var time = new Date();
+  var hour = time.getHours();
+  var minute = time.getMinutes();
+  var second = time.getSeconds();
+  var temp = "" + ((hour > 12) ? hour - 12 : hour);
+  if (hour == 0)
+    temp = "12";
+  temp += ((minute < 10) ? ":0" : ":") + minute;
+  temp += ((second < 10) ? ":0" : ":") + second;
+  temp += (hour >= 12) ? " P.M." : " A.M.";
+  return temp;
+}
+
+ +

JSClock 함수는 먼저 time이라는 새 Date 객체를 만듭니다. 인수가 없으므로 현재 날짜와 시간으로 시간이 생성됩니다. 그런 다음 getHours, getMinutesgetSeconds 메소드를 호출하면 현재 시간, 분 및 초 값이hour, minute, second로 할당됩니다.

+ +

다음 네 문장은 시간을 기준으로 문자열 값을 만듭니다. 첫 번째 명령문은 변수 temp를 작성하고 조건식을 사용하여 값을 할당합니다. hour가 12보다 큰 경우 (hour - 12), 그렇지 않은 경우 시간이 0이 아닌 경우 시간이 12 일 경우 시간이 12가됩니다.

+ +

다음 명령문은 temp 값에 minute 값을 추가합니다. 분(minute)의 값이 10보다 작 으면 조건식은 앞에 0이 있는 문자열을 추가합니다. 그렇지 않으면 콜론을 구분하는 문자열을 추가합니다. 그런 다음 같은 방법으로 temp에 초 값을 추가합니다.

+ +

마지막으로 조건부 표현식에 "P.M."이 추가됩니다. 시간(hour)이 12 시간 이상이면 임시(temp)로; 그렇지 않으면 "A.M."을 temp에 추가합니다.

+ +

{{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/about/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/about/index.html new file mode 100644 index 0000000000..05deb2017f --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/about/index.html @@ -0,0 +1,109 @@ +--- +title: About +slug: Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/About +--- +

이번 릴리즈의 새 기능

+

JavaScript 버전 1.5는 다음과 같은 개선과 새 기능을 제공합니다: +

런타임 오류
+런타임 오류가 예외로서 보고됩니다. +

숫자 표현 서식 개선
+숫자를 표현하는 서식이 Number.prototype.toExponential, Number.prototype.toFixed, Number.prototype.toPrecision 메소드를 포함함으로서 개선되었습니다. Number 개체 페이지를 보십시오. +

정규 표현식 개선
+정규표현식이 다음과 같이 개선되었습니다: +

+ +

조건부 함수 선언
+함수를 if 조건안에서 선언할 수 있습니다. 함수 정의 페이지를 참고하세요. +

함수 표현식
+함수를 표현식 안에서 선언할 수 있습니다. 함수 정의 페이지를 참고하세요. +

Multiple catch clauses
+Multiple catch clauses in a try...catch statement are supported. See The catch Block page. +

Getters와 Setters
+JavaScript writers can now add getters and setters to their objects. This feature is available only in the C implementation of JavaScript. See the Defining Getters and Setters page. +

상수
+읽기전용의 상수가 지원됩니다. This feature is available only in the C implementation of JavaScript. See the Constants page. +

+

미리 알고 있어야 할 것

+

이 안내서는 당신이 다음과 같은 배경지식을 지녔다고 가정합니다: +

+ +

C 혹은 Visual Basic에 대한 프로그래밍 경험이 있으면 좋지만, 필수사항은 아닙니다. +

+

JavaScript 버전

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
JavaScript 버전Navigator 버전
JavaScript 1.0Navigator 2.0
JavaScript 1.1Navigator 3.0
JavaScript 1.2Navigator 4.0-4.05
JavaScript 1.3Navigator 4.06-4.7x
JavaScript 1.4 
JavaScript 1.5Navigator 6.0
모질라 (오픈소스 브라우저)
+

표1: JavaScript와 Navigator 버전
+
+Each version of the Netscape Enterprise Server also supports a different version of JavaScript. To help you write scripts that are compatible with multiple versions of the Enterprise Server, this manual uses an abbreviation to indicate the server version in which each feature was implemented. +

+ + + + + + + + + + + + + +
AbbreviationEnterprise Server version
NES 2.0Netscape Enterprise Server 2.0
NES 3.0Netscape Enterprise Server 3.0
+

Table 2: Abbreviations of Netscape Enterprise Server versions +

+

JavaScript 정보를 찾을 수 있는 곳

+

The core JavaScript documentation includes the following books: +

+ +

If you are new to JavaScript, start with the Core JavaScript Guide. Once you have a firm grasp of the fundamentals, you can use the Core JavaScript Reference to get more details on individual objects and statements. +

+

문서 규약

+

JavaScript 응용프로그램은 많은 운영체제에서 실행됩니다. 이 책에 있는 정보는 모든 운영체제에 적용됩니다. 파일과 디렉토리 경로는 Windows 형식(디렉토리 이름을 구분하는데 역슬래시를 사용)으로 썼습니다. Unix에서는 역슬래시를 슬래시로 바꾸어 사용하면 됩니다. +

이 안내서에서 URL은 다음과 같은 형태로 씁니다. +

http://server.domain/path/file.html +

이 URL에서 "server"는 우리가 응용프로그램을 실행하는 서버 이름(research1이나 www 등)이고, "domain"은 인터넷 도메인 이름(netscape.com이나 uiuc.edu 등)입니다. "path"는 서버의 디렉토리 구조를 나타내고, "file.html"은 파일 이름입니다. 일반적으로 URL에서 이탤릭체로 쓴 부분은 알맞은 내용으로 바꿔써야 할 내용(placeholder)이고, 평범한 고정폭 글꼴은 그대로 쓰면 되는 내용입니다. Secure Socket Layer(SSL)을 사용하는 서버라면 http 대신 https를 쓰면 됩니다. +

이 안내서는 다음과 같은 관례를 따릅니다. +

+ +

{{ PreviousNext("Core_JavaScript_1.5_Guide", "Core_JavaScript_1.5_Guide:JavaScript_Overview") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/About", "fr": "fr/Guide_JavaScript_1.5/\u00c0_propos", "ja": "ja/Core_JavaScript_1.5_Guide/About", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/O" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/class-based_vs._prototype-based_languages/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/class-based_vs._prototype-based_languages/index.html new file mode 100644 index 0000000000..20601a0e81 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/class-based_vs._prototype-based_languages/index.html @@ -0,0 +1,26 @@ +--- +title: Class-Based vs. Prototype-Based Languages +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Class-Based_vs._Prototype-Based_Languages +--- +

클래스 기반언어와 프로토타입 기반언어

+

Java와 C++이라는 클래스 기반의 객체지향언어는 클래스와 인스턴스라는 2개의 다른 실체가 있다는 개념에 기초하고 있습니다.

+ +

JavaScript のようなプロトタイプベース言語はこの区別がありません。単にオブジェクトがあるだけです。プロトタイプベース言語には原型的なオブジェクトという概念があります。このオブジェクトは新しいオブジェクトの初期プロパティを取得する元になるテンプレートとして使用されます。どのオブジェクトもそれ独自のプロパティを指定できます。オブジェクト作成時にも実行時にも可能です。さらに、どのオブジェクトも別のオブジェクトに対するプロトタイプとして関連付けることができます。2 つ目のオブジェクトが 1 つ目のオブジェクトのプロトタイプを共有するということもできます。

+

クラスの定義

+

クラスベース言語ではクラス定義ごとにクラスを定義します。定義では特殊なメソッドを指定してそのクラスのインスタンスを作成することができます。そのようなメソッドはコンストラクタと呼びます。コンストラクタメソッドはインスタンスのプロパティに対する初期値を指定することができます。また、作成時に他の適当な処理を実行することもできます。new 演算子をコンストラクタメソッドと一緒に用いることでクラスのインスタンスを作成できます。

+

JavaScript は同様のモデルに従っていますが、コンストラクタと別になっているクラス定義がありません。その代わりに、プロパティと値からなる特定の初期的なセットを持つオブジェクトを作成するコンストラクタ関数を定義します。どの JavaScript 関数もコンストラクタとして使用できます。new 演算子をコンストラクタ関数とともに使用することで新しいオブジェクトを作成します。

+

サブクラスと継承

+

クラスベース言語ではクラス定義を通じてクラスの階層を作ります。クラス定義では新しいクラスがある既存のクラスのサブクラスになるように指定することができます。サブクラスはスーパークラスの全プロパティを継承します。さらに新しくプロパティを追加したり継承したものを変更することもできます。例えば、Employee クラスが name および dept プロパティのみを含んでおり、Manager は reports プロパティを追加する Employee のサブクラスであるとします。この場合、Manager クラスのインスタンスは name、dept、reports という 3 つのプロパティをすべて持つことになります。

+

JavaScript では、原型的なオブジェクトをどのコンストラクタ関数にも結びつけることができるようにして継承を実装しています。そのため、全く同じような Employee と Manager の例を作成することができますが、使用する用語が若干異なります。まず、Employee コンストラクタ関数を定義します。これは name および dept プロパティを指定します。次に Manager コンストラクタ関数を定義します。これは reports プロパティを指定します。最後に新しい Employee オブジェクトを Manager コンストラクタ関数に対するプロトタイプとして代入します。そして新しい Manager を作成すると、このオブジェクトは Employee オブジェクトから name および dept プロパティを継承します。

+

プロパティの追加と削除

+

クラスベース言語では一般的にクラスをコンパイル時に生成し、コンパイル時または実行時にクラスのインスタンスを作成します。クラス定義後にそのクラスのプロパティの数や型を変更することはできません。しかし、JavaScript ではどんなオブジェクトでも実行時にプロパティを追加したり削除したりすることができます。あるオブジェクトのセットでプロトタイプとして使用されているオブジェクトにプロパティを追加すると、そのプロトタイプの使用元であるオブジェクトにも新しいプロパティが追加されます。

+

違いの概要

+

次の表でこれらの違いをいくつか短くまとめてみます。この章の残りで、JavaScript のコンストラクタとプロトタイプを用いてオブジェクト階層を作成することについての詳細を説明していきます。また、この方法が Java ではどう変わるかという比較もします。

+ +
クラスベース (Java) プロトタイプベース (JavaScript)
クラスとインスタンスは異なる実体である。 すべてのオブジェクトはインスタンスである。
クラス定義を用いてクラスを定義する。また、コンストラクタメソッドを用いてクラスをインスタンス化する。 コンストラクタ関数を用いてオブジェクトのセットを定義し、作成する。
new 演算子を用いて単一のオブジェクトを作成する。 同じ。
既存のクラスのサブクラスを定義するクラス定義を用いてオブジェクト階層を構築する。 コンストラクタ関数に結びつけられたプロトタイプとしてオブジェクトを代入することでオブジェクト階層を構築する。
クラスチェーンに従ってプロパティを継承する。 プロトタイプチェーンに従ってプロパティを継承する。
クラス定義がクラスの全インスタンスの全プロパティを指定する。実行時に動的にプロパティを追加することはできない。 コンストラクタ関数またはプロトタイプがプロパティの初期セットを指定する。個々のオブジェクトやオブジェクトの全体のセットに動的にプロパティを追加したり、それらからプロパティを除去したりできる。
+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Predefined_Core_Objects:String_Object", "Core_JavaScript_1.5_Guide:The_Employee_Example") }}

+
+

{{ languages( { "zh-tw": "zh_tw/Core_JavaScript_1.5_教學/以類別為基礎的語言_vs._以原型為基礎的語言", "en": "en/Core_JavaScript_1.5_Guide/Class-Based_vs._Prototype-Based_Languages", "es": "es/Gu\u00eda_JavaScript_1.5/Lenguajes_basados_en_clases_frente_a_basados_en_prototipos", "fr": "fr/Guide_JavaScript_1.5/Langages_bas\u00e9s_sur_les_classes_et_langages_bas\u00e9s_sur_les_prototypes", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/J\u0119zyki_oparte_na_klasach_vs._oparte_na_prototypach", "zh-cn": "cn/Core_JavaScript_1.5_Guide/Class-Based_vs._Prototype-Based_Languages" } ) }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/constants/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/constants/index.html new file mode 100644 index 0000000000..48a697fdc2 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/constants/index.html @@ -0,0 +1,28 @@ +--- +title: Constants +slug: Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Constants +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +

상수

+

const 키워드를 이용하면 읽기 전용의 이름 있는 상수를 만들 수 있습니다. 상수 식별자(const identifier)는 변수의 식별자와 동일합니다. 문자나 밑줄로 시작해야 하고, 알파벳, 숫자, 밑줄 문자를 사용할 수 있습니다. +

+
const prefix = '212';
+
+

상수는 스크립트 실행 중에 값을 대입하거나 다시 선언하여 값을 바꿀 수 없습니다. +

전역 상수인 경우에도 항상 const 키워드를 붙여야 한다는 점만 제외하면, 상수의 범위 규칙은 변수의 경우와 동일합니다. const 키워드가 없으면 변수라고 판정됩니다. +

같은 범위에 있는 함수나 변수의 이름과 같은 이름으로 상수를 만들 수 없습니다. 예를 들어, +

+
//이 코드는 에러를 낼 것입니다
+function f() {};
+  const f = 5;
+
+//이 코드 또한 에러를 냅니다.
+function f() {
+  const g = 5;
+  var g;
+
+  //그 외 코드...
+
+}
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Variables", "Core_JavaScript_1.5_Guide:Literals") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Constants", "fr": "fr/Guide_JavaScript_1.5/Constantes", "ja": "ja/Core_JavaScript_1.5_Guide/Constants", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Sta\u0142e" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_a_regular_expression/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_a_regular_expression/index.html new file mode 100644 index 0000000000..d969b378f4 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_a_regular_expression/index.html @@ -0,0 +1,35 @@ +--- +title: Creating a Regular Expression +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Creating_a_Regular_Expression +--- +

정규표현식 만들기

+

정규표현식은 다음의 두 가지 방법으로 만들 수 있습니다.

+ +
 re = /ab+c/; 
+
+
+
+
+ 정규표현식 상수값은 스크립트가 실행될 때 컴파일됩니다. 따라서 정규표현식의 값이 변하지 않을 경우, 이 방법을 사용하면 좀 더 나은 성능을 얻을 수 있습니다.
+
+
+
+ +
 re = new RegExp("ab+c"); 
+
+
+
+
+ 생성자를 이용하면 실행 시간에 정규표현식이 컴파일됩니다. 정규표현식 패턴이 바뀔 것을 알고 있거나, 또는 패턴을 사용자의 입력 등을 통해 외부에서 가져오려고 할 때 이 방법을 사용하십시오.
+
+
+
+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Operators:Special_Operators", "Core_JavaScript_1.5_Guide:Writing_a_Regular_Expression_Pattern") }}

+
+

 

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_getters_and_setters/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_getters_and_setters/index.html new file mode 100644 index 0000000000..3238e19b0f --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_getters_and_setters/index.html @@ -0,0 +1,84 @@ +--- +title: Defining Getters and Setters +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Creating_New_Objects/Defining_Getters_and_Setters +--- +

getter/setter 정의하기

+ +

getter는 속성의 값을 얻어오는 메소드이고, setter는 속성의 값을 설정하는 메소드입니다. 우리는 언어에서 미리 정의한 핵심 개체들과 사용자 정의 개체에 getter/setter를 정의할 수 있습니다. getter와 setter를 정의할 때 쓰이는 문법은 개체 상수값 문법입니다.

+ +

다음의 JS 쉘 세션은 사용자가 정의한 개체 o에 대해서 getter와 setter가 어떻게 동작하는지 보여줍니다. JS 쉘은 JavaScript를 한 번에 실행(batch)하거나 대화식으로(interactively) 실행할 수 있게 해주는 응용프로그램입니다.

+ +

o 개체에는 이런 속성이 있습니다.

+ + + +
js> o = new Object;
+[object Object]
+js> o = {a:7, get b() {return this.a+1; }, set c(x) {this.a = x/2}};
+[object Object]
+js> o.a
+7
+js> o.b
+8
+js> o.c = 50
+js> o.a
+25
+js>
+
+ +

다음 JavaScript 쉘 세션은 이미 정의된 Date 모든 인스턴스에 year 속성을 추가하기 위해서 getter/setter가 어떻게 Date 프로토타입을 확장하는지 보여줍니다. 이 세션에서는 year 속성의 getter와 setter를 지원하기 위해서 Date에 있는 getFullYear 메소드와 setFullYear 메소드를 사용하고 있습니다.

+ +

이 문장들은 year 속성에 대한 getter와 setter를 정의합니다.

+ +
js> var d = Date.prototype;
+js> d.__defineGetter__("year", function() { return this.getFullYear(); });
+js> d.__defineSetter__("year", function(y) { this.setFullYear(y); });
+
+ +

이 문장들은 Date의 getter/setter를 사용합니다.

+ +
js> var now = new Date;
+js> print(now.year);
+2000
+js> now.year=2001;
+987617605170
+js> print(now);
+Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
+
+ +
JavaScript 1.5를 개발하는 동안 이미 존재하는 개체에 getter/setter를 추가할 때 getter =, setter =이라는 식의 문법을 사용하던 때가 잠깐 있었습니다. 이 문법은 이제 사용하지 말아야 합니다. 현재의 JS 1.5 엔진에서는 경고를 발생시키고, 더 나중의 버전에서는 문법 에러를 발생시키게 될 것입니다.
+ +

 

+ +

요약

+ +

getter/setter를

+ + + +

개체 초기화 지정자를 이용할 때는 단순히 getter 메소드 앞에는 get을 써주고 setter 메소드 앞에는 set을 써주기만 하면됩니다. 물론 getter 메소드에는 매개변수가 없어야 하고 setter에는 정확히 하나만 있어야 합니다. 다음 예제에서와 같이 말입니다.

+ +
o = {
+  a:7,
+  get b() { return this.a+1; },
+  set c(x) { this.a = x/2; }
+};
+
+ +

개체가 생성된 이후에 어느 때라도 __defineGetter____defineSetter__라는 메소드를 이용하면 getter/setter를 정의할 수 있습니다. 두 메소드 모두 첫 번째 매개변수에 getter/setter 이름을 나타내는 문자열을 받습니다. 두 번째 매개변수는 getter/setter로서 호출될 함수를 받습니다. 예제를 보십시오.

+ +
o.__defineGetter__("b", function() { return this.a+1; });
+o.__defineSetter__("c", function(x) { this.a = x/2; });
+
+ +

두 가지 중에서 어떤 방식을 택할지는 프로그래밍 스타일이나 해야할 작업에 달려있습니다. 프로토타입을 정의하는데 이미 개체 초기화 지정자를 사용하고 있다면 거의 첫 번째 방식을 사용할 것입니다. 첫 번째가 좀 더 단순하고 자연스러운 방식입니다. 그러나 우리가 직접 프로토토입을 만들거나 개체를 생성할 수 없어서 나중에 getter/setter를 추가해야 하는 상황이라면 두 번째 방식을 사용할 수 밖에 없습니다. 두 번째 방식은 JavaScript의 동적인 특성을 잘 보여주는 방식입니다. 하지만 코드를 읽고 이해하기 어렵게 만들 수도 있습니다.

+ +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Creating_New_Objects:Using_this_for_Object_References", "Core_JavaScript_1.5_Guide:Creating_New_Objects:Deleting_Properties") }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_methods/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_methods/index.html new file mode 100644 index 0000000000..8e91a2007f --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_methods/index.html @@ -0,0 +1,43 @@ +--- +title: Defining Methods +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Creating_New_Objects/Defining_Methods +--- +

메소드 정의

+

+ + 메소드 + 는 개체와 연관되어 있는 함수입니다. 일반적인 함수를 정의하는 것과 같은 방법으로 메소드를 정의합니다. 그 후에, 존재하는 개체와 함수를 연관시키기 위해서 다음과 같은 문법을 사용합니다.

+
object.methodname = function_name
+
+

object는 존재하는 개체중에 하나이고, methodname은 지금 추가하려는 메소드 이름이며, function_name은 함수 이름입니다.

+

이제 우리는 개체의 메소드를 호출할 때 다음과 같이 할 수 있습니다.

+
object.methodname(params);
+
+

개체 생성자 함수에 메소드 정의를 포함시켜서 개체 타입에 대한 메소드를 정의할 수 있습니다. 예를 들어, 미리 정의된 car 개체의 속성을 출력해주는 함수를 정의할 수 있습니다.

+
function displayCar() {
+   var result = "A Beautiful " + this.year + " " + this.make
+      + " " + this.model;
+   pretty_print(result);
+}
+
+

pretty_print는 가로선과 문자열을 출력하는 함수입니다. 이 메소드가 포함된 개체를 참조하기 위해서 this를 사용하고 있다는 것을 주의해서 보십시오.

+

아래 문장을 개체 정의에 추가함으로써 이 함수를 car의 메소드로 만들 수 있습니다.

+
this.displayCar = displayCar;
+
+

그러므로 car 개체의 완벽한 정의는 아래와 같은 모습이 될 것입니다.

+
function car(make, model, year, owner) {
+   this.make = make;
+   this.model = model;
+   this.year = year;
+   this.owner = owner;
+   this.displayCar = displayCar;
+}
+
+

그러면 우리는 모든 car 개체에 대해서 이런 식으로 displayCar 메소드를 호출할 수 있게됩니다.

+
car1.displayCar()
+car2.displayCar()
+
+

이 코드는 다음 그림과 같은 내용을 만들어냅니다.

+

Image:obja.gif 그림 7.1: 메소드 출력 결과

+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Creating_New_Objects:Defining_Properties_for_an_Object_Type", "Core_JavaScript_1.5_Guide:Creating_New_Objects:Using_this_for_Object_References") }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_properties_for_an_object_type/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_properties_for_an_object_type/index.html new file mode 100644 index 0000000000..17c2aa7de8 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/defining_properties_for_an_object_type/index.html @@ -0,0 +1,11 @@ +--- +title: Defining Properties for an Object Type +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Creating_New_Objects/Defining_Properties_for_an_Object_Type +--- +

개체 형식에 속성 정의하기

+

prototype 속성을 이용하면 이미 정의해 놓은 개체 형식에 속성을 추가할 수 있습니다. 이 방법을 사용하면 개체의 인스턴스 하나에만 속성이 추가되는 것이 아니라 같은 타입의 모든 개체가 공유하는 속성을 정의합니다. 다음 코드는 car 형식의 모든 개체에 color 속성을 추가하고, car1 개체의 color 속성에 값을 할당하는 코드입니다.

+
Car.prototype.color=null;
+car1.color="black";
+
+

더 많은 정보를 얻으려면 기본 JavaScript 레퍼런스에 있는 Function 개체의 prototype 속성을 보십시오. {{ PreviousNext("Core_JavaScript_1.5_Guide:Creating_New_Objects:Indexing_Object_Properties", "Core_JavaScript_1.5_Guide:Creating_New_Objects:Defining_Methods") }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/deleting_properties/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/deleting_properties/index.html new file mode 100644 index 0000000000..1b6f50cc11 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/deleting_properties/index.html @@ -0,0 +1,20 @@ +--- +title: Deleting Properties +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Creating_New_Objects/Deleting_Properties +--- +

속성 제거

+

delete 연산자를 사용하여 속성을 제거할 수 있습니다. 어떻게 속성을 제거하는지 코드를 보십시오.

+
//a와 b라는 속성을 가지는 새 개체를 만듭니다.
+myobj = new Object;
+myobj.a = 5;
+myobj.b = 12;
+
+//myobj가 속성 b만을 가지도록 속성 a를 지웁니다.
+delete myobj.a;
+
+

전역 변수를 선언할 때 var 키워드를 사용하지 않았다면 그 전역 변수를 제거하는데 delete 연산자를 사용할 수 있습니다.

+
g = 17;
+delete g;
+
+

더 많은 정보를 얻으려면 delete를 보십시오. {{ PreviousNext("Core_JavaScript_1.5_Guide:Creating_New_Objects:Defining_Getters_and_Setters", "Core_JavaScript_1.5_Guide:Predefined_Core_Objects") }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/index.html new file mode 100644 index 0000000000..8345ba1478 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/index.html @@ -0,0 +1,6 @@ +--- +title: Creating New Objects +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Creating_New_Objects +--- +{{wiki.localize('System.API.page-generated-for-subpage')}} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/indexing_object_properties/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/indexing_object_properties/index.html new file mode 100644 index 0000000000..84b9df2c2d --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/indexing_object_properties/index.html @@ -0,0 +1,9 @@ +--- +title: Indexing Object Properties +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Creating_New_Objects/Indexing_Object_Properties +--- +

개체 속성 접근하기

+

JavaScript 1.0에서는 개체의 속성을 참조할 때 개체 이름이나 순서 인덱스를 사용할 수 있습니다. 그러나 JavaScript 1.1과 그 이후 버전에서는 처음에 속성을 정의할 때 이름으로 정의했으면 항상 이름으로만 참조해야 하고, 인덱스로 정의했으면 인덱스로만 참조해야 합니다.

+

이런 제한은 앞 페이지 예제의 car 개체 형식처럼 생성자 함수로 개체와 개체 속성을 만들 때나 명시적으로 개별 속성을 만들 때(예를 들어 myCar.color = "red" 같은 식으로 속성을 추가할 때) 모두 적용됩니다. 그러므로 myCar{{ mediawiki.external(5) }} = "25 mpg"라고 인덱스를 이용해서 속성을 정의하면 그 이후로는 항상 myCar{{ mediawiki.external(5) }}로 참조할 수 있습니다.

+

이 규칙은 forms 배열 같이 HTML을 반영하여 생성된 개체에는 예외입니다. 이 배열에 있는 개체를 참조할 때는 순서(문서에 기록된 순서)를 나타내는 숫자나 이름(이름을 정의한 경우에만)을 이용하여 참조할 수 있습니다. 예를 들어, 문서에 있는 두 번째 <FORM> 태그가 "myForm"이라는 값을 가진 NAME 속성을 갖고 있다면 이 폼은 document.forms{{ mediawiki.external(1) }}, document.forms{{ mediawiki.external('\"myForm\"') }}, document.myForm으로 접근할 수 있습니다. {{ PreviousNext("Core_JavaScript_1.5_Guide:Creating_New_Objects:Using_a_Constructor_Function", "Core_JavaScript_1.5_Guide:Creating_New_Objects:Defining_Properties_for_an_Object_Type") }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/using_a_constructor_function/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/using_a_constructor_function/index.html new file mode 100644 index 0000000000..552347b70e --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/using_a_constructor_function/index.html @@ -0,0 +1,58 @@ +--- +title: Using a Constructor Function +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Creating_New_Objects/Using_a_Constructor_Function +--- +

생성자 함수 사용하기

+

다른 방법으로, 다음 두 단계를 거쳐서 개체를 만들 수도 있습니다.

+
    +
  1. 생성자 함수를 작성함으로써 개체를 정의합니다.
  2. +
  3. new 키워드를 사용하여 개체의 인스턴스를 만듭니다.
  4. +
+

개체 형식을 정의하기 위해서, 개체의 이름, 속성, 메소드를 지정하는 함수를 만듭니다. 자동차를 나타내기 위한 개체를 만들고 싶다고 해봅시다. 그렇다면 이 형식이 car라고 불리길 원할 것이고, make, model, year라는 속성이 있기를 원할 것입니다. 원하는 것을 이루기 위해서 이런 함수를 작성합니다.

+
function car(make, model, year) {
+   this.make = make;
+   this.model = model;
+   this.year = year;
+}
+
+

함수의 인자로 전달받은 값을 개체의 속성에 할당하기 위해서 this를 사용했다는 것을 명심하십시오.

+

이제 우리는 mycar라는 개체를 이렇게 만들 수 있습니다.

+
mycar = new car("Eagle", "Talon TSi", 1993);
+
+

이 문장은 mycar를 만들고, 지정된 값을 mycar의 속성에 할당합니다. 그러면 mycar.make는 "Eagle"이라는 문자열 값을 가지고, mycar.year는 1993이라는 정수를 가질 것입니다.

+

우리는 new를 써서 car 개체를 몇 개라도 만들 수 있습니다.

+
kenscar = new car("Nissan", "300ZX", 1992);
+vpgscar = new car("Mazda", "Miata", 1990);
+
+

개체는 다른 개체를 속성으로 가질 수 있습니다. 예를 들어, person 개체를 다음과 같이 정의했다고 합시다.

+
function person(name, age, sex) {
+   this.name = name;
+   this.age = age;
+   this.sex = sex;
+}
+
+

그리고나서 person 개체의 인스턴스 두 개를 만듭니다.

+
rand = new person("Rand McKinnon", 33, "M");
+ken = new person("Ken Jones", 39, "M");
+
+

이제 우리는 car가 owner라는 속성으로 person 개체를 가지도록 car의 정의를 바꿀 수 있습니다.

+
function car(make, model, year, owner) {
+   this.make = make;
+   this.model = model;
+   this.year = year;
+   this.owner = owner;
+}
+
+

새 개체 인스턴스를 만들 때 이렇게 쓸 수 있습니다.

+
car1 = new car("Eagle", "Talon TSi", 1993, rand);
+car2 = new car("Nissan", "300ZX", 1992, ken);
+
+

위 문장에서 owner 인자로 문자열 상수값이나 정수값을 전달하는 대신 randken이라는 개체를 전달했다는 사실에 주의하십시오. 이제 car2의 소유자 이름을 알고 싶으면 이런식으로 접근할 수 있습니다.

+
car2.owner.name
+
+

정의된 개체에 아무때나 속성을 추가할 수 있다는 사실을 기억하십시오.

+
car1.color = "black"
+
+

이 문장은 car1에 color 속성을 추가하고 "black"이라는 값을 할당합니다. 그러나 이 문장이 다른 개체에 영향을 미치지는 않습니다. 같은 형식을 가지는 모든 개체에 새 속성을 추가하고 싶으면 car 개체 형식의 정의에 속성을 추가해야 합니다.

+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Creating_New_Objects:Using_Object_Initializers", "Core_JavaScript_1.5_Guide:Creating_New_Objects:Indexing_Object_Properties") }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/using_this_for_object_references/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/using_this_for_object_references/index.html new file mode 100644 index 0000000000..0ed663ae1f --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/creating_new_objects/using_this_for_object_references/index.html @@ -0,0 +1,25 @@ +--- +title: Using this for Object References +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Creating_New_Objects/Using_this_for_Object_References +--- +

this를 사용한 개체 참조

+

JavaScript에는 this라는 키워드가 있는데, 메소드 안에서 현재 개체를 참조하기 위해서 이 키워드를 사용할 수 있습니다. 예를 들어, 개체의 값 속성을 검증하는 validate라는 함수가 있다고 해봅시다.

+
function validate(obj, lowval, hival) {
+   if ((obj.value < lowval) || (obj.value > hival))
+      alert("Invalid Value!");
+}
+
+

그러면 폼의 각 요소의 onchange 이벤트 핸들러에서 validate를 호출할 때, 다음 예제와 같은 방법으로 this를 사용해서 폼 요소를 validate에 전달할 수 있습니다.

+
<input type="text" name="age" size="3"
+   onChange="validate(this, 18, 99)">
+
+

form 속성과 같이 사용하면, this는 현재 개체의 부모 폼을 참조할 수 있습니다. 다음 예제에서, myForm이라는 폼은 Text 개체와 버튼을 포함하고 있습니다. 사용자가 버튼을 클릭하면 Text 개체의 값을 폼 이름으로 바꿉니다. 버튼의 onclick 이벤트 핸들러에서 부모 폼인 myForm을 참조하기 위해서 this.form을 사용하고 있습니다.

+
<form name="myForm">
+<p><label>Form name:<input type="text" name="text1" value="Beluga"></label>
+<p><input name="button1" type="button" value="Show Form Name"
+      onclick="this.form.text1.value=this.form.name">
+</p>
+</form>
+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Creating_New_Objects:Defining_Methods", "Core_JavaScript_1.5_Guide:Creating_New_Objects:Defining_Getters_and_Setters") }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/expressions/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/expressions/index.html new file mode 100644 index 0000000000..d9f8bb0bf9 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/expressions/index.html @@ -0,0 +1,16 @@ +--- +title: Expressions +slug: Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Expressions +--- +

표현식

+

표현식은 상수(literals), 변수, 연산자 그리고 단일값을 반환하는 계산식(값은 숫자, 문자열, 논리값이 가능)이 알맞게 조합된 집합체다. +

개념적으로 보면 표현식에는 두가지 타입이 있다: 하나는 변수에 값을 할당하는 것이고 다른 하나는 단순히 값을 가지고 있는 것이다. 예를 들어, x = 7 이라는 표현식은 x 에 7이라는 값을 할당하는 표현식이다. 이 표현식은 스스로 7이라는 값을 부여한다. 이런 표현식들은 할당 연산자를 사용한다. 반면에, 3 + 4 라는 표현식은 단순히 7이라는 값을 계산할 뿐이다; 할당하지 않는다. 이런 표현식에서 사용되는 연산자는 그냥 단순히 연산자라고만 한다. +

JavaScript에는 다음과 같은 타입의 표현식이 있다: +

+ +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Unicode", "Core_JavaScript_1.5_Guide:Operators") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Expressions", "fr": "fr/Guide_JavaScript_1.5/Expressions", "ja": "ja/Core_JavaScript_1.5_Guide/Expressions", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Wyra\u017cenia" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/javascript_overview/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/javascript_overview/index.html new file mode 100644 index 0000000000..310ab25c67 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/javascript_overview/index.html @@ -0,0 +1,44 @@ +--- +title: JavaScript Overview +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/JavaScript_Overview +--- +

JavaScript란 무엇인가?

+

JavaScript는 크로스 플랫폼, 객체 지향 스크립트 언어입니다. JavaScript는 작고, 가벼운 언어입니다; JavaScript는 단독으로 쓰이는 언어로는 유용하지 않지만, 웹 브라우져 같은 다른 제품이나 프로그램에 포함하기 쉽습니다. 호스트 환경에서 JavaScript는 그 환경의 다른 개체(object)들을 프로그램적으로 제어하기 위해서 그들과 연결될 수 있습니다.

+

기본 JavaScript(core JavaScript)는 Array, Date, Math등 기본이 되는 개체들(core set of objects)과 연산자, 제어 구조, 문장등 언어의 기본 요소들(core set of language elements)을 포함하고 있습니다. 기본 JavaScript는 다른 개체를 추가함으로써 다양한 목적을 위해 확장될 수 있습니다. 예를 들면 다음과 같은 것들입니다.

+ +

JavaScript의 LiveConnect 기능을 통해서, Java와 JavaScript 코드가 서로 통신할 수 있습니다. JavaScript에서 Java 개체를 초기화하여 개체의 공개 메소드와 필드에 접근할 수 있습니다. Java에서 JavaScript 개체, 속성(property), 메소드에 접근할 수 있습니다.

+

Netscape가 JavaScript를 개발했고 Netscape 브라우저에서 JavaScript가 가장 먼저 사용되었습니다.

+

JavaScript와 Java

+

JavaScript 와 Java 는 여러가지 면에서 비슷하지만 본질적으로 다릅니다. JavaScript는 Java 와 공통점이 있지만 Java 처럼 형(type)을 검사하지 않습니다. JavaScript는 Java 문법의 대부분과 제어흐름의 기본적인 개념들을 지원합니다.

+

Java의 클래스 선언으로 이루어지는 컴파일 타임 시스템에 대조적으로, JavaScript는 수, 불리언, 문자열 값을 나타내는 작은 규모의 자료형에 기반한 런타임 시스템을 지원합니다. JavaScript는 클래스 기반 개체 모델이 아닌 프로토타입 기반(prototype-based) 개체 모델을 갖고 있습니다. 프로토타입 기반 개체 모델은 동적인 상속을 제공합니다. 즉, 각각의 개체를 상속할 수 있는 것입니다. JavaScript는 또 특별히 선언시의 요구사항이 없는 함수도 지원합니다. 함수는 느슨하게 타입된 메소드로 실행됨으로써 개체의 속성이 될 수 있습니다.(Functions can be properties of objects, executing as loosely typed methods.)

+

Java에 비해 JavaScript는 형식이 자유로운 언어입니다. 모든 변수, 클래스, 메소드들을 꼭 선언 할 필요는 없습니다. 메소드가 public, private, protected 인지 고민해야할 필요가 없고, interface를 구현할 필요도 없습니다. 변수, 매개변수(parameter), 함수의 반환 형식도 명시적으로 지정할 필요가 없습니다.

+

Java는 클래스 기반 프로그래밍 언어로서, 빠른 실행과 형 안정성(type safety)을 위해 설계되었습니다. 형 안정성이란 예를 들면 Java에서 정수를 개체 참조로 변환할 수 없고, Java 바이트코드에 오류를 일으켜서 사적인(private) 메모리 공간에 접근할 수 없다는 말입니다. 자바의 클래스 기반 모델은 프로그램이 클래스와 클래스의 메소드로만 이루어진다는 의미입니다. Java의 클래스 상속과 엄격한 형 검사(strong typing)는 일반적으로 단단히 결합된 개체의 계층 구조를 필요로 합니다. 이런 요구사항이 JavaScript 프로그래밍에 비해 Java 프로그래밍을 더 복잡하게 만듭니다.

+

반면 JavaScript는 HyperTalk나 dBASE 같이 적은 줄수의 동적 타입 언어를 계승한 것입니다. 이런 스크립트 언어는 더 많은 사람들을 위한 프로그래밍 도구로서 제공되는데, 이 언어들이 문법이 쉽고, 내장되기에 쉬우며, 개체 생성에 요구 사항이 단순하기 때문입니다.

+ +
JavaScript Java
개체 지향. 개체의 형식 사이에 구분이 없음. 프로토타입 메커니즘을 통해 상속을 지원하고, 어떤 개체에든지 동적으로 속성과 메소드를 추가할 수 있습니다. 클래스 기반. 개체는 클래스 계층 구조를 관통하는 상속을 통해서 클래스와 인스턴스(instance)로 나뉩니다. 클래스와 인스턴스에는 동적으로 속성과 메소드를 추가할 수 없습니다.
변수의 자료형을 선언하지 않음(동적 형 검사) 변수의 자료형을 반드시 선언해야 함(정적 형 검사)
Cannot automatically write to hard disk. Cannot automatically write to hard disk.
+

표(Table) 1.1: JavaScript 와 Java 비교
+
+Java와 JavaScript 사이의 차이점에 대해서 더 알고 싶으시면 개체 모델의 상세 내용을 보시기 바랍니다.

JavaScript와 ECMAScript 명세

+

Netscape가 JavaScript를 개발했고, Netscape 브라우저에서 가장 처음으로 사용되었습니다. 그러나 Ecma International - 정보와 통신 시스템을 표준화하기 위한 유럽 기구(공식적으로 ECMA - the European Computer Manufacturers Association으로 알려짐) - 과 Netscape가 공동으로 작업하여 기본 JavaScript에 기반하여 표준화되고 국제적인 프로그래밍 언어를 만들어냈습니다. JavaScript의 표준화된 버전은 ECMAScript라고 부르고, 표준을 지원하는 응용프로그램에서는 모두 동일하게 동작합니다. 회사들은 그들의 JavaScript 구현을 개발하기 위해서 공개된 표준 언어를 사용할 수 있습니다. ECMAScript 표준은 ECMA-262 명세에 문서화되어 있습니다.

+

ECMA-262 표준은 ISO (International Organization for Standardization, 국제 표준화기구)의 승인을 받아 ISO-16262가 되었습니다. Mozilla 웹사이트에서 ECMA-262의 PDF 문서를 얻을 수 있습니다. the Ecma International 웹사이트 에서도 명세를 찾을 수 있습니다. ECMAScript 명세는 World Wide Web Consortium (W3C)에서 표준화 한 Document Object Model(DOM)에 대해서는 설명하지 않습니다. DOM은 HTML 문서 개체들이 스크립트에 노출되는 방식을 정의합니다.

+

JavaScript 버전과 ECMAScript 판본 사이의 관계

+

Netscape는 ECMA와 밀접하게 작업하여 ECMAScript Specification(ECMA-262)를 만들었습니다. JavaScript 버전과 ECMAScript 판본(edition)들 사이의 관계가 아래 표에 설명되어 있습니다.

+ +
JavaScript 버전 ECMAScript 판본과의 관계
JavaScript 1.1 ECMA-262, 1판은 JavaScript 1.1에 기초합니다.
JavaScript 1.2 JavaScript 1.2가 발표됐을 때 ECMA-262가 아직 완성되지 않았습니다. 다음과 같은 이유때문에 JavaScript 1.2는 ECMA-262 1판과 완벽하게 호환되지 않습니다.
  • Netscape는 JavaScript 1.2에 몇 가지 기능을 추가했으나, ECMA-262에서 고려하지 못했습니다.
  • ECMA-262는 두 가지 새 기능을 추가했습니다. 유니코드를 이용한 국제화, 모든 플랫폼에서의 동일한 동작. Date 개체 같은 JavaScript 1.2의 몇 가지 기능이 플랫폼에 의존적이었습니다.

JavaScript 1.3

JavaScript 1.3은 ECMA-262 1판과 완벽하게 호환됩니다.

JavaScript 1.3은 ==와 !=연산자를 제외하고는 JavaScript 1.2의 추가적인 기능을 그대로 유지하면서 JavaScript 1.2가 ECMA-262와 어긋나던 점들을 해결했습니다. ==, != 연산자는 ECMA-262에 맞추기 위해 수정되었습니다.

JavaScript 1.4

JavaScript 1.4는 ECMA-262 1판과 완벽하게 호환됩니다.

JavaScript 1.4가 발표되었을 때 ECMAScript 명세의 세 번째 버전이 아직 완성되지 않았습니다.

JavaScript 1.5 JavaScript 1.5는 ECMA-262 3판과 완벽하게 호환됩니다.
+

표 1.2: JavaScript 버전과 ECMAScript 판본
+
+참고: ECMA-262 2판은 1판에 편집상 사소한 변경과 버그 수정을 가한 판본입니다. 현재 ECMA의 TC39 워킹그룹에서 ECMAScript 4판을 작업하고 있습니다. 4판은 JavaScript 2.0과 대응될 것입니다.

+

JavaScript 기본 레퍼런스에서 ECMAScript 호환 기능을 보여줍니다.

+

JavaScript는 항상 ECMAScript Specification에 포함되지 않은 기능들을 포함할 것입니다. JavaScript는 추가적인 기능을 제공하지만 ECMAScript와 호환됩니다.

+

JavaScript 문서 vs ECMAScript 명세서

+

ECMAScript 명세는 ECMAScript를 구현하는데 필요한 요구사항을 모아놓은 것입니다. 이것은 우리가 JavaScript의 한 기능이 다른 ECMAScript 구현에서도 지원될 것인지 결정하는데 유용합니다. ECMAScript에서 지원하는 기능만을 사용하는 JavaScript 코드를 작성할 계획이라면 ECMAScript 명세를 살펴볼 필요가 있을 것입니다.

+

ECMAScript 문서는 스크립트 프로그래머를 돕기위해 작성된 것이 아닙니다. 스크립트 작성에 대한 정보를 얻으려면 JavaScript 문서를 보십시오.

+

JavaScript와 ECMAScript 용어

+

ECMAScript 명세는 JavaScript 프로그래머에게는 친숙하지 않은 용어와 문법을 사용하여 작성되었습니다. 비록 ECMAScript의 언어 설명이 다르긴 하지만 언어는 똑같습니다. JavaScript는 ECMAScript 명세에서 설명하는 모든 기능을 지원합니다.

+

JavaScript 문서는 JavaScript 프로그래머에게 적당한 언어의 측면을 설명합니다. 예를 들면 이렇습니다.

+ +

{{ PreviousNext("Core_JavaScript_1.5_Guide:About", "Core_JavaScript_1.5_Guide:Values") }}

+

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/JavaScript_Overview", "fr": "fr/Guide_JavaScript_1.5/Aper\u00e7u_de_JavaScript", "ja": "ja/Core_JavaScript_1.5_Guide/JavaScript_Overview", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Podgl\u0105d_JavaScriptu" } ) }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/literals/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/literals/index.html new file mode 100644 index 0000000000..dfaff2c586 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/literals/index.html @@ -0,0 +1,174 @@ +--- +title: Literals +slug: Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Literals +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +

상수값(Literal)

+

JavaScript에서 값을 표현하기 위해 상수값을 사용할 수 있습니다. 그것은 변수가 아니라 고정된 값으로서 "문자 그대로(literally)" 스크립트에 값을 제공하는 것입니다. 이 절에서 다음과 같은 상수값에 대해서 설명하겠습니다.

+ +

배열 상수값

+

배열 상수값은 대괄호([])안에 배열의 원소(element)를 0개 이상 나열한 것입니다. 배열 상수값으로 배열을 만드면 배열은 지정된 원소를 가지도록 초기화되고, 지정된 원소의 개수만큼의 길이를 갖게 됩니다.

+

다음 예제는 세 개의 원소를 가지고 길이가 3인 coffees 배열을 만드는 예제입니다.

+
coffees = ["French Roast", "Colombian", "Kona"]
+

참고 배열 상수값은 개체 초기화지정자(object initializer) 중의 하나입니다. 개체 초기화지정자 사용하기를 보십시오.

+

최상위 스크립트에서 상수값을 이용하여 배열을 만들면 JavaScript는 배열 상수값을 포함하는 표현식을 평가(evaluate)할 때마다 배열을 만듭니다. 또한, 함수 안에서 사용된 상수값은 함수가 호출될 때마다 생성됩니다.

+

배열 상수값은 Array 개체입니다. Array 개체에 대한 상세한 내용은 Array 개체를 보십시오.

+

배열 상수값의 추가적인 쉼표

+

배열 상수값에 모든 원소를 지정할 필요는 없습니다. 쉼표만 찍어 두면 값이 할당되지 않은 빈 공간을 가진 배열이 만들어집니다. 다음 예제는 fish 배열을 만듭니다.

+
fish = ["Lion", , "Angel"]
+

이 배열은 값을 가진 원소 두 개와 빈 원소 하나를 갖게됩니다. (fish{{ mediawiki.external(0) }}은 "Lion", fish{{ mediawiki.external(1) }}undefined, fish{{ mediawiki.external(2) }}는 "Angel"이라는 값을 가집니다.)

+

원소 목록 끝에 남겨둔 쉼표는 무시됩니다. 다음 예제에서 배열 길이는 3입니다. myList{{ mediawiki.external(3) }}은 만들어지지 않습니다. 그외에 목록에 있는 다른 쉼표들은 각각 새로운 원소를 나타냅니다.

+
myList = ['home', , 'school', ];
+

다음 예제에서 배열 길이는 4이고, myList{{ mediawiki.external(0) }}myList{{ mediawiki.external(2) }}는 비게 됩니다.

+
myList = [ , 'home', , 'school'];
+

다음 예제에서 배열 길이는 4이고 myList{{ mediawiki.external(1) }}myList{{ mediawiki.external(3) }}이 비게 됩니다. 오직 마지막 쉼표만 무시됩니다.

+
myList = ['home', , 'school', , ];
+

불리언 상수값

+

불리언 형은 두 가지 상수값을 가질 수 있는데, 그것은 truefalse입니다.

+

true, false라는 기본(primitive) 불리언 값과 true, false 값의 불리언 개체를 혼동하지 마십시오. 불리언 개체는 기본 불리언 데이터 형을 감싸는 역할을 할 뿐입니다. 더 많은 정보는 불리언 개체를 참조하십시오.

+

정수

+

10진수, 16진수, 8진수 정수를 쓸 수 있습니다. 10진수 정수 상수값은 0(영)으로 시작하지 않는 숫자의 나열입니다. 0(영)으로 시작하는 정수 상수값은 8진수입니다. 0x(또는 0X)로 시작하면 16진수입니다. 16진수는 0부터 9까지의 숫자와 a부터 f나 A부터 F까지의 문자를 포함할 수 있습니다. 8진수에는 0부터 7까지만 쓸 수 있습니다.

+

8진수 정수 상수값은 사용하지 말기를 추천하고 있으며, ECMA-262 표준 3판에서는 아예 제거되었습니다. 하위 호환성을 위해 JavaScript 1.5에서는 여전히 8진수 정수 상수값을 지원하고 있습니다.

+

몇 가지 정수 상수값을 예를 보여드리겠습니다.

+
0, 117, -345 (10진수)
+015, 0001, -077 (8진수)
+0x1123, 0x00111, -0xF1A7 (16진수 또는 "hex")
+
+

소수 상수값

+

소수 상수값은 이런 부분으로 이뤄집니다.

+ +

지수 부분은 "e"나 "E" 뒤에 숫자가 붙은 형태입니다. 숫자 앞에는 부호("+"나 "-")를 붙일 수도 있습니다. 소수 상수값은 적어도 하나의 숫자에 소수점 또는 지수 부분을 가져야 합니다.

+

소수 상수값의 몇 가지 예제를 보여드리겠습니다. 3.1415, -3.1E12, .1e12, 2E-12

+

개체 상수값

+

개체 상수값은 중괄호({}) 안에 특성(property) 이름과 그에 해당하는 값의 쌍을 나열한 것입니다. 문장(statement)의 시작 부분에 개체 상수값을 사용해서는 안됩니다. { 가 블럭의 시작을 나타내기 때문에, 에러가 나거나 의도하지 않은 동작을 보일 것입니다.

+

다음은 개체 상수값의 예입니다. car 개체의 첫 번째 원소는 myCar라는 특성을 정의하고 있습니다. 두 번째 원소는 getCar 특성을 정의하는데, (CarTypes("Honda"));라는 함수를 호출하고 있습니다. 세 번째 원소는 special 특성을 정의하는데에 Sales라는 변수를 사용합니다.

+
var Sales = "Toyota";
+
+function CarTypes(name) {
+   if(name == "Honda")
+      return name;
+   else
+      return "Sorry, we don't sell " + name + ".";
+}
+
+car = {myCar: "Saturn", getCar: CarTypes("Honda"), special: Sales}
+
+document.write(car.myCar); // Saturn
+document.write(car.getCar); // Honda
+document.write(car.special); // Toyota
+

개체 특성 이름에 정수 상수값이나 문자열 상수값을 사용할 수 있고, 개체 안에 다른 개체를 포함시킬 수도 있습니다. 다음 예제를 보십시오.

+
car = {manyCars: {a: "Saab", b: "Jeep"}, 7: "Mazda"}
+
+document.write(car.manyCars.b); // Jeep
+document.write(car[7]); // Mazda
+
+

다음 사항을 참고하십시오.

+
foo = {a: "alpha", 2: "two"}
+document.write (foo.a)    // alpha
+document.write (foo[2])   // two
+//document.write (foo.2)  // Error: missing ) after argument list
+//document.write (foo[a]) // Error: a is not defined
+document.write (foo["a"]) // alpha
+document.write (foo["2"]) // two
+
+

문자열 상수값

+

문자열 상수값은 큰따옴표(")나 작은따옴표(')로 둘러싸인 0개 이상의 문자들 입니다. 문자열은 같은 종류의 따옴표로 묶어야 합니다. 즉, 작은따옴표 둘로 묶거나, 큰따옴표 둘로 묶어야 한다는 말입니다. 문자열 상수값의 예를 보여드리겠습니다.

+ +

우 리는 문자열 상수값에 String 개체의 모든 메소드를 호출할 수 있습니다. JavaScript는 자동으로 문자열 상수값을 임시 String 개체로 만들어서 메소드를 호출한 후, 임시 String 개체를 제거합니다. 문자열 상수값에 String.length 특성을 사용할 수도 있습니다. 이렇게 말입니다.

+ +

우리가 특별하게 String 개체를 필요로 하는 경우가 아니라면 문자열 상수값을 사용해야만 합니다. String 개체에 대한 자세한 내용은 String 개체를 보십시오.

+
문자열에서 특수문자 사용하기
+

다음 예제에서 볼 수 있듯이 일반적인 문자뿐만 아니라 특수문자도 문자열에 쓸 수 있습니다.

+
"one line \n another line"
+

JavaScript 문자열에 사용할 수 있는 특수문자를 표로 나타낸 것입니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
문자의미
\bBackspace
\fForm feed
\nNew line
\rCarriage return
\tTab
\vVertical tab
\'Apostrophe or single quote
\"Double quote
\\Backslash character (\).
\XXX세 자리 까지의 8진수 "XXX"로 지정하는 Latin-1 인코딩의 문자. 0부터 377 사이. 예를 들어, \251은 저작권 기호의 8진수 표현입니다.
\xXX두 자리 까지의 16진수 "XX"로 지정하는 Latin-1 인코딩의 문자. 00부터 FF 사이. 예를 들어, \xA9는 저작권 기호의 16진수 표현입니다.
\uXXXX네 자리의 16진수 "XXXX"로 지정하는 유니코드 문자. 예를 들어, \u00A9는 저작권 기호의 유니코드 표현입니다. 유니코드 이스케이프 시퀀스를 보십시오.
+

표 2.1: JavaScript 특수문자

+
문자 이스케이프
+

표 2.1에 없는 문자에 대해서는 역슬래시가 무시됩니다. 그러나 이러한 기능은 사용하지 않기를 권장하므로 사용을 피해야만 합니다.

+

역슬래시를 앞에 붙이면 문자열 안에 따옴표를 넣을 수 있습니다. 이것은 따옴표 "이스케이프(escaping)"라고 알려져 있습니다.

+
var quote = "He read \"The Cremation of Sam McGee\" by R.W. Service."
+document.write(quote)
+
+

이 코드의 결과는 다음과 같습니다.

+
He read "The Cremation of Sam McGee" by R.W. Service.
+
+

문자열 안에 역슬래시 문자를 넣고 싶으면 역슬래시 문자를 이스케이프시켜야 합니다. 예를 들어, c:\temp 라는 경로를 문자열에 할당하고 싶으면 다음과 같이 하면 됩니다.

+
var home = "c:\\temp"
+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Constants", "Core_JavaScript_1.5_Guide:Unicode") }}

+

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Literals", "fr": "fr/Guide_JavaScript_1.5/Constantes_litt\u00e9rales", "ja": "ja/Core_JavaScript_1.5_Guide/Literals", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Litera\u0142y" } ) }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/objects_and_properties/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/objects_and_properties/index.html new file mode 100644 index 0000000000..abe9ff83f4 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/objects_and_properties/index.html @@ -0,0 +1,39 @@ +--- +title: Objects and Properties +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Objects_and_Properties +--- +

객체와 속성

+

자바스크립트 객체는 객체를 구성하는 속성을 가지고 있습니다. 속성에는 간단한 방법으로 접근할 수 있습니다.: +

+
객체이름.속성이름
+
+

객체 이름과 속성 이름 두 가지 모두에 대해 알기쉬운 예가 있습니다. 속성은 값을 지정하여 정의합니다. 예를 들어 myCar라는 객체가 있다면(객체가 이미 존재한다고 가정합니다.), make, model, year라는 속성에 다음과 같이 값을 지정할 수 있습니다. +

+
myCar.make = "Ford";
+myCar.model = "Mustang";
+myCar.year = 1969;
+
+

배열은 한 가지 변수 이름으로 결합되어 있는 연속된 값의 집합입니다. 자바스크립트에서 속성과 배열은 밀접한 관련이 있습니다; 말하자면 그 두 가지는 같은 데이터 구조에 다른 인터페이스라는 뜻입니다. 예를 들면 myCar 객체에 다음과 같이 접근할 수도 있습니다: +

+
myCar["make"] = "Ford";
+myCar["model"] = "Mustang";
+myCar["year"] = 1967;
+
+

이러한 배열의 종류는 연관 배열이라고 부릅니다. 왜냐하면 각각의 인덱스 요소가 문자열 값과 연관되어 있기 때문입니다. 이러한 방식에 대한 설명은 다음의 함수에 객체와 객체의 이름을 입력했을 때 객체의 속성을 표시해주는 다음과 같은 함수에서 알아볼 수 있습니다: +

+
function show_props(obj, obj_name) {
+   var result = "";
+   for (var i in obj)
+      result += obj_name + "." + i + " = " + obj[i] + "\n";
+   return result;
+}
+
+

결과적으로 call show_props(myCar, "myCar")라는 함수 호출은 다음과 같은 값을 반환합니다: +

+
myCar.make = Ford
+myCar.model = Mustang
+myCar.year = 1967
+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Predefined_Functions:escape_and_unescape_Functions", "Core_JavaScript_1.5_Guide:Creating_New_Objects") }} +

{{ languages( { "fr": "fr/Guide_JavaScript_1.5/Objets_et_propri\u00e9t\u00e9s", "ja": "ja/Core_JavaScript_1.5_Guide/Objects_and_Properties", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Obiekty_i_w\u0142a\u015bciwo\u015bci" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/arithmetic_operators/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/arithmetic_operators/index.html new file mode 100644 index 0000000000..ce55c0e3f2 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/arithmetic_operators/index.html @@ -0,0 +1,44 @@ +--- +title: Arithmetic Operators +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Operators/Arithmetic_Operators +translation_of: Web/JavaScript/Guide/Expressions_and_Operators +--- +

산술 연산자

+

산술 연산자는 수(상수값이든지 변수든지)를 받아서 하나의 수를 반환합니다. 표준 산술 연산자는 더하기(+), 빼기(-), 곱하기(*), 나누기(/)입니다. 이 연산자들은 대부분의 다른 프로그래밍 언어에서 처럼 동작합니다. 예외적으로 / 연산자는 JavaScript에서 소수를 반환합니다. C나 Java 같은 다른 언어에서는 / 연산자가 소수 부분은 잘라버립니다. 예를 들면 이렇습니다. +

+
1/2 //returns 0.5 in JavaScript
+1/2 //returns 0 in Java
+
+

JavaScript는 다음 표에 나오는 산술 연산자를 제공합니다. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
연산자설명예제
%
(나머지)
2항(binary) 연산자. 두 피연산자의 나눗셈에서 나온 나머지를 반환합니다.12 % 5 returns 2.
++
(증가)
단항(unary) 연산자. 피연산자에 1을 더함. 전위 연산자(++x)를 사용하면 피연산자에 1을 더한 후 그 값을 반환합니다. 후위 연산자(x++)를 사용하면 피연산자에 1을 더하기 전에 피연산자의 값을 반환합니다.x가 3일 때, ++xx를 4로 만들고 4를 반환합니다. 반면 x++x를 4로 만들고 3을 반환합니다.
--
(감소)
단항 연산자. 피연산자에서 1을 뺌. 반환값은 증가 연산자와 동일한 방식으로 결정됩니다.x가 3일 때, --xx를 2로 만들고 2를 반환합니다. 반면 x--x를 2로 만들고 3을 반환합니다.
-
(단항 부정)
단항 연산자. 피연산자의 부호를 바꾼 값을 반환합니다.x가 3이면 -x는 -3을 반환합니다.
+

표 3.4: 산술 연산자 +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Operators:Comparison_Operators", "Core_JavaScript_1.5_Guide:Operators:Bitwise_Operators") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Operators/Arithmetic_Operators", "fr": "fr/Guide_JavaScript_1.5/Op\u00e9rateurs/Op\u00e9rateurs_arithm\u00e9tiques", "ja": "ja/Core_JavaScript_1.5_Guide/Operators/Arithmetic_Operators", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Operatory/Operatory_arytmetyczne" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/assignment_operators/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/assignment_operators/index.html new file mode 100644 index 0000000000..dbc284f12f --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/assignment_operators/index.html @@ -0,0 +1,62 @@ +--- +title: Assignment Operators +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Operators/Assignment_Operators +--- +

할당 연산자

+

할당 연산자는 왼쪽 피연산자에 오른쪽 피연산자의 값을 할당합니다. 가장 기본적인 할당 연산자에는 등호(=)가 있는데, 왼쪽 피연산자의 값을 오른쪽 연산자에 할당합니다. 즉, x = y 라고 하면 y의 값이 x에 할당되는 것입니다.

+

다른 할당 연산자는 다음 표에서 보듯이 표준연산을 약식으로 쓰는 것입니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
약식 연산자의미
x += yx = x + y
x -= yx = x - y
x *= yx = x * y
x /= yx = x / y
x %= yx = x % y
x <<= yx = x << y
x >>= yx = x >> y
x >>>= yx = x >>> y
x &= yx = x & y
x ^= yx = x ^ y
x |= yx = x | y
+

표: 할당 연산자

+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Operators", "Core_JavaScript_1.5_Guide:Operators:Comparison_Operators") }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/bitwise_operators/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/bitwise_operators/index.html new file mode 100644 index 0000000000..860e6787e9 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/bitwise_operators/index.html @@ -0,0 +1,101 @@ +--- +title: Bitwise Operators +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Operators/Bitwise_Operators +translation_of: Web/JavaScript/Guide/Expressions_and_Operators +--- +


+

+

비트 연산자

+

비트 연산자는 피연산자를 10진수나 16진수, 8진수로 다루지 않고 32개의 비트 집합으로 다룹니다. 예를 들어, 10진수 9는 2진수로 1001입니다. 비트 연산자는 2진수 표현으로 연산을 하지만 반환값은 JavaScript 표준 수 값으로 반환합니다. +

JavaScript의 비트 연산자를 다음 표에 요약했습니다. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
연산자사용법설명
비트 ANDa & b두 피연산자의 대응되는 비트가 모두 1이면 1을 반환.
비트 ORa | b두 피연산자의 대응되는 비트에서 둘 중 하나가 1이거나 모두 1인 경우 1을 반환.
비트 XORa ^ b두 피연산자의 대응되는 비트에서 둘 중 하나가 1이고, 둘 다 1이 아닐 경우 1을 반환.
비트 NOT~ a피연산자의 비트를 뒤집음.
왼쪽으로 이동a << ba의 2진수 표현을 b 비트만큼 왼쪽으로 이동함. 오른쪽은 0으로 채움.
부호 비트로 채우는 오른쪽 이동a >> ba의 2진수 표현을 b 비트만큼 오른쪽으로 이동함. 오른쪽 남는 비트는 버림.
0으로 채우는 오른쪽 이동a >>> ba의 2진수 표현을 b 비트만큼 오른쪽으로 이동함. 오른쪽 남는 비트는 버리고, 왼쪽은 0으로 채움.
+

표 3.5: 비트 연산자 +

+

비트 논리 연산자

+

개념적으로 비트 논리 연산자는 다음과 같이 동작합니다. +

+ +

예를 들어, 9를 2진수로 쓰면 1001이고 15를 2진수로 표현하면 1111입니다. 두 값에 비트 연산을 적용하면 결과는 다음과 같습니다. +

+ +

비트 이동 연산자

+

비트 이동 연산자는 피연산자 두 개를 받습니다. 첫 번째는 이동하려는 수이고, 두 번째는 첫 번째 피연산자를 몇 비트나 이동시킬지 나타내는 비트 수입니다. 이동 방향은 사용된 연산자에 따라 다릅니다. +

이동 연산자는 피연산자를 32비트 정수로 변환하여 연산하고, 왼쪽 연산자와 같은 자료형으로 반환합니다. +

이동 연산자는 다음 표에 있습니다. +

+ + + + + + + + + + + + + + + + + + + + +
연산자설명예제
<<
+(왼쪽 이동)
이 연산자는 첫 번째 피연산자의 비트를 지정된 수만큼 왼쪽으로 옮깁니다. 왼쪽으로 넘친 비트는 버립니다. 오른쪽 빈 자리는 0으로 채웁니다. 9<<2는 36을 반환합니다. 1001을 왼쪽으로 2비트 이동하면 100100이 되고 이것은 36이기 때문입니다.
>>
+(부호 비트로 채우는 오른쪽 이동)
이 연산자는 첫 번째 피연산자의 비트를 지정된 수 만큼 오른쪽으로 옮깁니다. 오른쪽으로 넘친 비트는 버립니다. 왼쪽 빈 자리는 원래 가장 왼쪽에 있던 비트 값으로 채웁니다.9>>2는 2를 반환합니다. 1001을 2비트 오른쪽으로 이동하면 10이 되는데 이것은 2이기 때문입니다. 비슷하게 -9>>2는 -3을 반환하는데, 부호가 유지되기 때문입니다.
>>>
+(0으로 채우는 오른쪽 이동)
이 연산자는 첫 번째 피연산자의 비트를 지정된 수 만큼 오른쪽으로 옮깁니다. 오른쪽으로 넘친 비트는 버립니다. 왼쪽 빈 자리는 0으로 채웁니다.19>>>2는 4를 반환합니다. 10011을 2비트 오른쪽으로 이동하면 100이 되기 때문입니다. 음수가 아닌 수에 대해서는 0을 채우는 오른쪽 이동이나 부호 비트로 채우는 오른쪽 이동이 똑같은 결과를 반환합니다.
+

표 3.6: 비트 이동 연산자 +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Operators:Arithmetic_Operators", "Core_JavaScript_1.5_Guide:Operators:Logical_Operators") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Operators/Bitwise_Operators", "fr": "fr/Guide_JavaScript_1.5/Op\u00e9rateurs/Op\u00e9rateurs_bit-\u00e0-bit", "ja": "ja/Core_JavaScript_1.5_Guide/Operators/Bitwise_Operators", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Operatory/Operatory_bitowe" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/index.html new file mode 100644 index 0000000000..53b8e67492 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/index.html @@ -0,0 +1,108 @@ +--- +title: Operators +slug: Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Operators +--- +

연산자

+

JavaScript에는 다음과 같은 연산자 타입이 있습니다. 이 섹션은 연산자에 대해 기술하고 연산자 우선순위에 대한 정보를 제공합니다. +

+ +

JavaScript는 이항연산자와 단항연산자를 모두 사용할 수 있습니다. 이항연산자는 두개의 피연산자(operand)를 가지며, 하나의 피연산자는 연산자 앞에 나머지 하나는 뒤에 위치합니다: +

+
operand1 operator operand2
+
+

예를 들자면, 3+4 혹은 x*y와 같은 것입니다. +

단항연산자는 연산자 앞 혹은 뒤쪽에 하나의 피연산자만 있으면 됩니다: +

+
operator operand
+
+

혹은 +

+
operand operator
+
+

예를 들자면, x++ 혹은 ++x와 같은 것입니다. +

덧붙여, JavaScript는 한개의 삼항연산자, 조건 연산자를 가지고 있습니다. 삼항 연산자는 세개의 피연산자가 필요합니다. +

+

연산자 우선순위

+

관련된 논의에 따라서, 아래의 표는 우선순위 순으로 내림차순 정렬되었습니다. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
연산자 타입사용하는 연산자
멤버 .  []
호출 / 인스턴스 생성 ()  new
부정/증감 !  ~  -  +  ++  --  typeof  void  delete
곱하기/나누기 *  /  %
더하기/빼기 +  -
비트 이동 <<  >>  >>>
관계 <  <=  >  >=  in  instanceof
같음 ==  !=  ===  !==
비트연산-and &
비트연산-xor ^
비트연산-or |
논리연산-and &&
논리연산-or ||
조건 ?:
할당 =  +=  -=  *=  /=  %=  <<=  >>=  >>>=  &=  ^=  |=
컴마,
+

표: 연산자 우선순위 +

이 표의 보다 자세한 버전은 레퍼런스 섹션에 있는 각 연산자별 상세한 추가 설명 링크를 참고하세요. +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Expressions", "Core_JavaScript_1.5_Guide:Operators:Assignment_Operators") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Operators", "fr": "fr/Guide_JavaScript_1.5/Op\u00e9rateurs", "ja": "ja/Core_JavaScript_1.5_Guide/Operators", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Operatory" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/logical_operators/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/logical_operators/index.html new file mode 100644 index 0000000000..6b30493f83 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/logical_operators/index.html @@ -0,0 +1,68 @@ +--- +title: Logical Operators +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Operators/Logical_Operators +translation_of: Web/JavaScript/Guide/Expressions_and_Operators +--- +

논리 연산자

+

논리 연산자는 주로 불리언(논리적) 값과 함께 사용됩니다. 그때 논리 연산자는 불리언 값을 반환합니다. 그러나 &&와 || 연산자는 실제로는 피연산자 중에 하나의 값을 반환하기 때문에, 이 연산자가 불리언 값이 아닌 값과 함께 사용되면 불리언 값이 아닌 값을 반환할 것입니다. 다음 표에 논리 연산자에 대해서 설명했습니다. +

+ + + + + + + + + + + + + + + + + + + + + +
연산자사용법설명
&&expr1 && expr2(논리적 AND) expr1이 false로 변환될 수 있으면 expr1을 반환하고, 그렇지 않으면 expr2를 반환합니다. 그러므로 불리언 값과 같이 사용하면 피연산자 둘 모두가 true일 때 &&는 true를 반환하고 그렇지 않을 때는 false를 반환합니다.
||expr1 || expr2(논리적 OR) expr1이 true로 변환될 수 있으면 expr1을 반환하고 그렇지 않으면 expr2를 반환합니다. 그러므로 불리언 값과 같이 사용하면 ||는 피연산자 중에서 하나만 true이면 true를 반환합니다. 둘 다 false이면 false를 반환합니다.
!!expr(논리적 NOT) 피연산자가 true로 변환될 수 있으면 false를 반환합니다. 그렇지 않으면 true를 반환합니다.
+

표 3.7: 논리 연산자 +

false로 변환될 수 있는 표현식은 null, 0, 빈 문자열(""), undefined로 평가될 수 있는 표현식들입니다. +

다음 코드는 && 연산자를 사용하는 예를 보여줍니다. +

+
a1=true && true       // t && t returns true
+a2=true && false      // t && f returns false
+a3=false && true      // f && t returns false
+a4=false && (3 == 4)  // f && f returns false
+a5="Cat" && "Dog"     // t && t returns Dog
+a6=false && "Cat"     // f && t returns false
+a7="Cat" && false     // t && f returns false
+
+

다음 코드는 || 연산자를 사용하는 예를 보여줍니다. +

+
o1=true || true       // t || t returns true
+o2=false || true      // f || t returns true
+o3=true || false      // t || f returns true
+o4=false || (3 == 4)  // f || f returns false
+o5="Cat" || "Dog"     // t || t returns Cat
+o6=false || "Cat"     // f || t returns Cat
+o7="Cat" || false     // t || f returns Cat
+
+

다음 코드는 ! 연산자를 사용하는 예를 보여줍니다. +

+
n1=!true              // !t returns false
+n2=!false             // !f returns true
+n3=!"Cat"             // !t returns false
+
+

단축 평가

+

논리 표현식이 왼쪽부터 오른쪽으로 평가되기 때문에 다음 규칙을 이용해서 "단축(short-circuit)" 평가를 할 수 있습니다. +

+ +

이 규칙을 따라 평가를 수행한다고 해서 피연산자를 모두 평가할 때와 결과가 달라지지 않습니다. 아무 표현식 부분은 평가되지 않기 때문에 아무런 부수 효과(side effect)도 일어나지 않는다는 것에 주의하십시오. +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Operators:Bitwise_Operators", "Core_JavaScript_1.5_Guide:Operators:String_Operators") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Operators/Logical_Operators", "fr": "fr/Guide_JavaScript_1.5/Op\u00e9rateurs/Op\u00e9rateurs_logiques", "ja": "ja/Core_JavaScript_1.5_Guide/Operators/Logical_Operators", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Operatory/Operatory_logiczne" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/special_operators/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/special_operators/index.html new file mode 100644 index 0000000000..aa66b296fc --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/special_operators/index.html @@ -0,0 +1,228 @@ +--- +title: Special Operators +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Operators/Special_Operators +translation_of: Web/JavaScript/Guide/Expressions_and_Operators +--- +

특수 연산자

+

JavaScript 다음과 같은 특별한 연산자를 제공합니다. +

+ +

조건 연산자

+

조건 연산자는 JavaScript에서 유일하게 세 개의 피연산자를 사용하는 연산자입니다. 연산자는 조건에 따라 둘 중에 하나의 값을 가질 수 있습니다. 문법은 이렇습니다. +

+
condition ? val1 : val2
+
+

condition이 true이면 연산자는 val1의 값을 갖습니다. 그렇지 않으면 val2의 값을 갖습니다. 다른 표준 연산자를 사용할 수 있는 곳이면 어디든지 조건 연산자를 사용할 수 있습니다. +

+
status = (age >= 18) ? "adult" : "minor"
+
+

이 문장은 age가 18이거나 더 큰 경우에 status 변수에 "adult"라는 값을 할당합니다. 그렇지 않으면 "minor"라는 값을 할당합니다. +

+

쉼표 연산자

+

쉼표 연산자(,)는 단순히 피연산자 둘을 모두 평가하고 두 번째 피연산자의 값을 반환하는 연산자입니다. 이 연산자는 주로 for 반복문에서 변수 여러 개가 매번 업데이트 되게 하는데 쓰입니다. +

예를 들어 a가 각각 10줄의 원소를 가지는 2차원 배열일 때, 다음 코드에서는 변수 두 개를 한 번에 바꾸기 위해서 쉼표 연산자를 사용하고 있습니다. 이 코드는 배열의 대각선 원소를 출력합니다. +

+
for (var i=0, j=9; i <= 9; i++, j--)
+   document.writeln("a["+i+"]["+j+"]= " + a[i][j])
+
+

delete

+

delete는 개체(object), 개체의 속성(property), 배열의 특정 인덱스에 있는 원소(element)를 지우는 연산자입니다. 문법은 이렇습니다. +

+
delete objectName
+delete objectName.property
+delete objectName[index]
+delete property // with 문장 안에서만 유효합니다
+
+

objectName은 개체 이름이고, property는 개체에 존재하는 속성이고, index는 배열의 원소 위치를 나타내는 정수입니다. +

네 번째 형식은 개체의 속성을 지우는 코드인데, with 문장 안에서만 사용할 수 있습니다. +

암시적으로 선언된 변수를 지울 때는 delete 연산자를 사용할 수 있지만 var 문장을 이용해서 선언된 변수는 지울 수 없습니다. +

delete 연산자 실행이 성공하면, 속성이나 원소가 undefined로 설정됩니다. delete 연산자는 실행이 가능하면 true를 반환하고, 불가능하면 false를 반환합니다. +

+
x=42
+var y= 43
+myobj=new Number()
+myobj.h=4      // h라는 속성을 만듭니다
+delete x       // returns true (암시적으로 선언된 변수는 지울 수 있습니다)
+delete y       // returns false (var로 선언한 변수는 지울 수 없습니다)
+delete Math.PI // returns false (미리 정의된 속성은 지울 수 없습니다)
+delete myobj.h // returns true (사용자 정의 속성은 지울 수 있습니다)
+delete myobj   // returns true (암시적으로 선언되었으므로 지울 수 있습니다)
+
+

배열의 원소를 지우기
+배열의 원소를 지울 때, 배열의 길이에는 변화가 없습니다. 예를 들어, a{{ mediawiki.external(3) }}, a{{ mediawiki.external(4) }}를 지우더라도 a{{ mediawiki.external(4) }}와 a{{ mediawiki.external(3) }}은 여전히 정의되지 않습니다. +

delete 연산자가 배열 원소를 제거할 때 원소는 더이상 배열에 존재하지 않습니다. 아래 예제에서 trees{{ mediawiki.external(3) }}은 delete로 제거되었습니다. +

+
trees=new Array("redwood","bay","cedar","oak","maple")
+delete trees[3]
+if (3 in trees) {
+   // 이 블록은 실행되지 않습니다.
+}
+
+

배열 원소가 존재하긴 하지만 정의되지 않은 값을 가지도록 하고 싶다면 delete 연산자 대신 undefined 키워드를 사용하십시오. 다음 예제에서 trees{{ mediawiki.external(3) }}undefined 값을 할당했지만 배열 요소는 여전히 존재합니다. +

+
trees=new Array("redwood","bay","cedar","oak","maple")
+trees[3]=undefined
+if (3 in trees) {
+   // 이 블록은 실행됩니다.
+}
+
+

in

+

in 연산자는 지정된 속성이 지정된 개체에 있으면 true를 반환합니다. 문법은 이렇습니다. +

+
propNameOrNumber in objectName
+
+

propNameOrNumber은 속성 이름을 나타내는 문자열이나 배열 인덱스를 나타내는 수이고, objectName은 개체 이름입니다. +

다음 예제는 in 연산자의 몇 가지 사용법을 보여줍니다. +

+
// 배열
+trees=new Array("redwood","bay","cedar","oak","maple")
+0 in trees        // returns true
+3 in trees        // returns true
+6 in trees        // returns false
+"bay" in trees    // returns false (원하는 인덱스를 지정해야 하는데,
+                  // 그 인덱스에 있는 값을 지정하면 안됩니다.)
+"length" in trees // returns true (length는 배열의 속성입니다.)
+
+// 미리 정의된 개체
+"PI" in Math          // returns true
+myString=new String("coral")
+"length" in myString  // returns true
+
+// 사용자 개체
+mycar = {make:"Honda",model:"Accord",year:1998}
+"make" in mycar  // returns true
+"model" in mycar // returns true
+
+

instanceof

+

instanceof는 지정된 개체가 지정된 개체 형식이면 true를 반환합니다. 문법은 이렇습니다. +

+
objectName instanceof objectType
+
+

objectNameobjectType과 비교할 개체의 이름이고, objectType은 개체 형식으로 DateArray 같은 것입니다. +

실행중에 개체의 형식을 알고 싶으면 instanceof를 사용하면 됩니다. 예를 들어 예외를 처리할 때, 발생한 예외의 형식에 따라 서로 다른 예외 처리 코드를 실행할 수 있습니다. +

다음 코드에서 theDayDate 개체인지 결정하기 위해서 instanceof를 사용합니다. theDayDate 개체이기 때문에 if문 안에 있는 문장이 실행됩니다. +

+
theDay=new Date(1995, 12, 17)
+if (theDay instanceof Date) {
+   // 실행할 문장
+}
+
+

new

+

사용자 정의 개체 형식이나 Array, Boolean, Date, Function, Image, Number, Object, Option, RegExp, String 같이 미리 정의된 개체 형식의 인스턴스를 만들 때 new 연산자를 사용합니다. 서버에서는 DbPool, Lock, File, SendMail 등을 만들 때 사용할 수 있습니다. new는 다음과 같이 사용합니다. +

+
objectName = new objectType ( param1 [,param2] ...[,paramN] )
+
+

개체 초기화 지정자 사용하기에 설명한 것처럼 개체 초기화 지정자를 이용해서 개체를 만들 수도 있습니다. +

더 많은 정보를 얻으려면 JavaScript 레퍼런스의 new 연산자 페이지를 보시기 바랍니다. +

+

this

+

현재 개체를 참조할 때 this 키워드를 사용합니다. 일반적으로 this는 메소드를 호출하는 개체를 참조합니다. 다음과 같이 사용하면 됩니다. +

+
this[.propertyName]
+
+

예제 1.
+개체의 value 속성이 높거나 낮은 값을 가지는지 검증하는 validate라는 함수가 있다고 가정합시다. +

+
function validate(obj, lowval, hival) {
+   if ((obj.value < lowval) || (obj.value > hival))
+      alert("Invalid Value!")
+}
+
+

이제 우리는 폼의 각 요소의 onChange 이벤트 핸들러에서 validate 함수를 호출하면서, this를 이용하여 스스로를 함수에 전달할 수 있습니다. +

+
<B>Enter a number between 18 and 99:</B>
+<INPUT TYPE = "text" NAME = "age" SIZE = 3
+   onChange="validate(this, 18, 99)">
+
+

예제 2.
+form 속성과 결합되면, this는 현재 개체가 포함된 폼을 참조할 수 있습니다. 다음 예제에서 myForm 폼은 Text 개체와 버튼을 포함하고 있습니다. 사용자가 버튼을 클릭하면 Text 개체의 값이 폼 이름으로 설정됩니다. 버튼의 onClick 이벤트 핸들러는 부모 폼인 myForm을 참조하기 위해서 this.form을 사용하고 있습니다. +

+
<FORM NAME="myForm">
+Form name:<INPUT TYPE="text" NAME="text1" VALUE="Beluga">
+<P>
+<INPUT NAME="button1" TYPE="button" VALUE="Show Form Name"
+   onClick="this.form.text1.value=this.form.name">
+</FORM>
+
+

typeof

+

typeof 연산자는 둘 중 한 가지 방법으로 사용할 수 있습니다. +

+
1. typeof operand
+2. typeof (operand)
+
+

typeof 연산자는 피연산자의 평가되지 않은 형식을 나타내는 문자열을 반환합니다. 피연산자는 string, variable, keyword, object 등의 타입을 반환하게 됩니다. 괄호는 선택적입니다. +

우리가 이런 변수를 정의했다고 해봅시다. +

+
var myFun = new Function("5+2")
+var shape="round"
+var size=1
+var today=new Date()
+
+

typeof는 이 변수들에 대해서 다음과 같은 결과를 반환할 것입니다. +

+
typeof myFun is function
+typeof shape is string
+typeof size is number
+typeof today is object
+typeof dontExist is undefined
+
+

truenull 키워드에 대해서 typeof 연산자는 다음과 같은 결과를 반환합니다. +

+
typeof true is boolean
+typeof null is object
+
+

수와 문자열에 대해서 typeof 연산자는 다음과 같은 결과를 반환합니다. +

+
typeof 62 is number
+typeof 'Hello world' is string
+
+

속성 값에 대해서 typeof 연산자는 속성이 포함하고 있는 값의 형식을 반환합니다. +

+
typeof document.lastModified is string
+typeof window.length is number
+typeof Math.LN2 is number
+
+

메소드와 함수에 사용하면 typeof 연산자는 다음과 같은 결과를 반환합니다. +

+
typeof blur is function
+typeof eval is function
+typeof parseInt is function
+typeof shape.split is function
+
+

미리 정의된 개체들에 대해서 typeof 연산자는 다음과 같은 결과를 반환합니다. +

+
typeof Date is function
+typeof Function is function
+typeof Math is function
+typeof Option is function
+typeof String is function
+
+

void

+

void 연산자는 다음과 같이 사용할 수 있습니다. +

+
1. void (expression)
+2. void expression
+
+

void 연산자는 표현식이 값을 반환하지 않으면서 평가되어야 한다고 지정하는데 사용됩니다. expression은 평가하려는 JavaScript 표현식입니다. 표현식을 감싸는 괄호는 선택적이지만 사용하는 쪽이 더 좋은 스타일입니다. +

표현식을 하이퍼텍스트 링크로 지정하기 위해서 void 연산자를 사용할 수 있습니다. 표현식이 평가되기는 하지만 현재 문서 대신 로드되지는 않습니다. +

아래 코드는 사용자가 클릭할 때 아무 동작도 하지 않는 하이퍼텍스트 링크를 만듭니다. 사용자가 링크를 클릭하면 void(0)는 정의되지 않은 것(undefined)으로 평가되고 JavaScript에서 아무런 효과가 없습니다. +

+
<A HREF="javascript:void(0)">Click here to do nothing</A>
+
+

다음 코드는 클릭하면 폼을 제출하는 하이퍼텍스트 링크를 만듭니다. +

+
<A HREF="javascript:void(document.form.submit())">
+Click here to submit</A>
+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Operators:String_Operators", "Core_JavaScript_1.5_Guide:Creating_a_Regular_Expression") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Operators/Special_Operators", "fr": "fr/Guide_JavaScript_1.5/Op\u00e9rateurs/Op\u00e9rateurs_sp\u00e9ciaux", "ja": "ja/Core_JavaScript_1.5_Guide/Operators/Special_Operators", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Operatory/Operatory_specjalne" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/string_operators/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/string_operators/index.html new file mode 100644 index 0000000000..41c6c07286 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/operators/string_operators/index.html @@ -0,0 +1,11 @@ +--- +title: String Operators +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Operators/String_Operators +translation_of: Web/JavaScript/Guide/Expressions_and_Operators +--- +

문자열 연산자

+

문자열 값에 사용할 수 있는 비교 연산자 외에도 연결 연산자(+)가 있는데, 이 연산자는 두 문자열 값을 연결한 새로운 문자열 값을 반환합니다. 예를 들어, "my " + "string""my string"라는 문자열을 반환합니다. +

축약된 할당 연산자인 += 또한 문자열 연결에 사용할 수 있습니다. 예를 들어 mystring 변수가 "alpha"라는 값을 가지고 있을 때, mystring += "bet"은 "alphabet"으로 평가되고, 그 값이 mystring에 할당됩니다. +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Operators:Logical_Operators", "Core_JavaScript_1.5_Guide:Operators:Special_Operators") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Operators/String_Operators", "fr": "fr/Guide_JavaScript_1.5/Op\u00e9rateurs/Op\u00e9rateurs_li\u00e9s_aux_cha\u00eenes", "ja": "ja/Core_JavaScript_1.5_Guide/Operators/String_Operators", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Operatory/Operacje_na_\u0142a\u0144cuchach" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/predefined_core_objects/array_object/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/predefined_core_objects/array_object/index.html new file mode 100644 index 0000000000..1f6ef48f3a --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/predefined_core_objects/array_object/index.html @@ -0,0 +1,133 @@ +--- +title: Array Object +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Predefined_Core_Objects/Array_Object +--- +

Array 개체

+

JavaScript에는 명시적인 배열 자료형이 없습니다. 하지만 배열을 다루기 위해서 Array 개체와 그 개체의 메소드를 이용할 수 있습니다. Array 개체에는 다양한 방법으로 배열을 다루기 위한 메소드들이 있는데, 배열을 합치거나, 순서를 뒤집거나, 정렬하는 등의 작업을 할 수 있습니다. 배열 길이를 알 수 있는 속성과 정규 표현식에 사용할 수 있는 속성들이 있습니다. + + 배열 + 은 이름이나 색인으로 참조할 수 있는 값들을 모아놓은, 값의 순서가 유지되는 집합입니다. 예를 들어, 우리는 고용 번호로 색인된 고용인의 이름을 담고 있는 emp라는 배열을 만들 수 있습니다. 이 때 emp{{ mediawiki.external(1) }}는 1번 고용인, emp{{ mediawiki.external(2) }} 2번 고용인이 되는 것입니다.

+

 

+

배열 만들기

+

Array 개체는 이렇게 만들 수 있습니다.

+
1. arrayObjectName = new Array(element0, element1, ..., elementN)
+2. arrayObjectName = new Array(arrayLength)
+
+

arrayObjectName은 새 개체의 이름이거나 존재하는 다른 개체의 속성 이름입니다. Array 개체의 속성이나 메소드를 이용할 때는 arrayObjectName은 존재하는 Array 개체 이름이거나 존재하는 다른 개체의 속성입니다.

+

element0, element1, ..., elementN는 배열의 원소(element)가 될 값들입니다. 이런 식으로 지정하면, 나열한 값들을 원소로 가지고, 길이는 값의 개수인 배열이 만들어집니다.

+

arrayLength는 배열의 초기 길이입니다. 다음 코드는 원소 다섯 개를 가지는 배열을 만듭니다.

+
billingMethod = new Array(5)
+
+

배열 상수값 또한 Array 개체입니다. 예를 들어, 다음과 같은 상수값은 Array 개체입니다. 배열 상수값에 대한 자세한 내용은 배열 상수값을 보시기 바랍니다.

+
coffees = ["French Roast", "Columbian", "Kona"]
+
+

배열에 원소 넣기

+

원소에 값을 할당함으로써 배열에 값을 넣을 수 있습니다.

+
emp[1] = "Casey Jones"
+emp[2] = "Phil Lesh"
+emp[3] = "August West"
+
+

배열을 만들 때 값을 넣을 수도 있습니다.

+
myArray = new Array("Hello", myVar, 3.14159)
+
+

배열 원소 참조하기

+

배열 원소의 순서를 나타내는 숫자로 원소를 참조할 수 있습니다. 예를 들어 다음과 같은 배열을 만들었다고 해봅시다.

+
myArray = new Array("Wind","Rain","Fire")
+
+

그러면 첫 번째 원소는 myArray{{ mediawiki.external(0) }}으로 참조할 수 있고, 두 번째 원소는 myArray{{ mediawiki.external(1) }}로 참조할 수 있습니다.

+

원소의 색인은 영(0)부터 시작하지만 배열 길이(예를 들면 myArray.length)는 배열의 원소 개수를 나타냅니다.

+

 

+

Array 개체의 메소드

+

Array 개체는 다음과 같은 메소드들을 가지고 있습니다.

+ +
myArray = new Array("1","2","3")
+myArray = myArray.concat("a", "b", "c"); // myArray는 ["1", "2", "3", "a", "b", "c"]이 되었습니다.
+
+ +
myArray = new Array("Wind","Rain","Fire")
+list = myArray.join(" - "); // list는 "Wind - Rain - Fire"입니다.
+
+ +
myArray = new Array("1", "2", "3");
+last=myArray.pop(); // MyArray는 ["1", "2"], last = "3"이 되었습니다.
+
+ +
myArray = new Array("1", "2");
+myArray.push("3"); // MyArray는 ["1", "2", "3"]이 되었습니다.
+
+ +
myArray = new Array ("1", "2", "3");
+myArray.reverse(); // myArray = [ "3", "2", "1" ]이 되었습니다.
+
+ +
myArray = new Array ("1", "2", "3");
+first=myArray.shift(); // MyArray는 ["2", "3"], first는 "1"이 되었습니다.
+
+ +
myArray = new Array ("a", "b", "c", "d", "e");
+myArray = myArray.slice(1,4); //색인 1부터 색인 4 바로 앞까지의 원소를 추출해서 [ "b", "c", "d" ]를 반환합니다.
+
+ +
myArray = new Array ("1", "2", "3", "4", "5");
+myArray.splice(1,3,"a","b","c", "d"); // MyArray는 ["1", "a", "b", "c", "d", "5"]가 되었습니다.
+// 이 코드는 색인 1(즉 "2")부터 원소 세 개를 제거하고, 그 자리에 원소를 추가합니다.
+
+ +
myArray = new Array("Wind","Rain","Fire")
+myArray.sort(); // 배열을 정렬했으므로 myArrray = [ "Fire", "Rain", "Wind" ]가 되었습니다.
+
+

sort 메소드에 배열을 어떻게 정렬할지 결정하는 콜백 함수를 전해줄 수 있습니다. 그 함수는 두 값을 비교해서 다음 셋 중 하나를 반환해야 합니다.

+ +

예를 들어 다음 코드는 원소의 마지막 글자를 기준으로 배열을 정렬합니다.

+
var sortFn = function(a,b){
+    if (a[a.length - 1] < b[b.length - 1]) return -1;
+    if (a[a.length - 1] > b[b.length - 1]) return 1;
+    if (a[a.length - 1] == b[b.length - 1]) return 0;
+    }
+myArray.sort(sortFn); // 배열을 정렬했으므로 myArray = ["Wind","Fire","Rain"]가 되었습니다.
+
+ +

2차원 배열

+

다음 코드는 2차원 배열을 만듭니다.

+
a = new Array(4)
+for (i=0; i < 4; i++) {
+   a[i] = new Array(4)
+   for (j=0; j < 4; j++) {
+      a[i][j] = "["+i+","+j+"]"
+   }
+}
+
+

바로 위 코드는 이런 배열을 만들어냅니다.

+
Row 0:[0,0][0,1][0,2][0,3]
+Row 1:[1,0][1,1][1,2][1,3]
+Row 2:[2,0][2,1][2,2][2,3]
+Row 3:[3,0][3,1][3,2][3,3]
+
+

배열과 정규 표현식

+

배열이 정규 표현식과 문자열을 매치한 결과로 생성되었을 때, 그 배열은 매치에 대한 정보를 제공하는 속성과 원소를 포함하고 있습니다. RegExp.exec, String.match, String.split의 반환 값은 배열입니다. 정규 표현식과 관련된 배열 사용에 대한 정보를 얻으려면 4장 정규 표현식을 보십시오.

+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Predefined_Core_Objects", "Core_JavaScript_1.5_Guide:Predefined_Core_Objects:Boolean_Object") }}

diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/predefined_core_objects/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/predefined_core_objects/index.html new file mode 100644 index 0000000000..9306e0ea94 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/predefined_core_objects/index.html @@ -0,0 +1,20 @@ +--- +title: Predefined Core Objects +slug: >- + Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Predefined_Core_Objects +translation_of: Web/JavaScript/Guide +--- +

미리 정의된 기본 개체

+

이 절에서는 기본 JavaScrip에 미리 정의된 개체에 대해서 설명하겠습니다. +

+ +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Creating_New_Objects:Deleting_Properties", "Core_JavaScript_1.5_Guide:Predefined_Core_Objects:Array_Object") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Predefined_Core_Objects", "fr": "fr/Guide_JavaScript_1.5/Objets_pr\u00e9d\u00e9finis", "ja": "ja/Core_JavaScript_1.5_Guide/Predefined_Core_Objects", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Obiekty_predefiniowane" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/unicode/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/unicode/index.html new file mode 100644 index 0000000000..562b7a53a0 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/unicode/index.html @@ -0,0 +1,109 @@ +--- +title: Unicode +slug: Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Unicode +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +

유니코드

+

유니코드는 세계의 주요한 문자 언어를 교환하고 표현하기 위한 문자-코딩 표준입니다. 유니코드는 아메리카, 유럽, 중동, 아프리카, 인도, 아시아, 태평양 지역(Pacifica)의 언어를 포함하며 고문자와 기술 분야 기호들도 포함합니다. 유니코드는 공통적인 기술 분야, 수학 분야 기호 뿐만 아니라 여러 언어를 포함한 텍스트의 교환, 처리, 표현을 지원합니다. 유니코드는 나라마다 서로 다른 문자 표준으로 인해서 여러 언어를 포함했을 때 발생하는 국제화 문제를 해결할 수 있기를 희망합니다. 하지만 아직은 모든 현대 문자, 고대 문자를 지원하지는 못합니다. +

유니코드 문자 집합은 알려진 모든 인코딩을 위해 사용될 수 있습니다. 유니코드는 ASCII (American Standard Code for Information Interchange, 정보 교환을 위한 미국 표준 코드) 문자 집합을 본떠 만들어졌습니다. 각각의 문자에 숫자와 이름을 부여한 것입니다. 문자 인코딩은 문자의 정체성(identity)과 숫자 값(코드 위치)와 함께 숫자 값의 비트 표현을 명시합니다. 16비트 숫자 값(코드 값)은 U+0041처럼 접두어 U뒤에 16진수를 붙여서 표시합니다. 이 값의 유일한 이름은 LATIN CAPITAL LETTER A입니다. +

JavaScript 1.3 이전 버전은 유니코드를 지원하지 않습니다. +

+

유니코드와 ASCII 및 ISO 사이의 호환성

+

유니코드는 ISO 10646의 부분집합인 국제 표준 ISO/IEC 10646-1; 1993과 완벽하게 호환됩니다. +

몇몇 인코딩 표준(UTF-8, UTF-16, ISO UCS-2를 포함하는)들이 실제 비트 값으로 유니코드를 표현하기 위해 사용됩니다. +

UTF-8 인코딩은 ASCII 문자와 호환되며 많은 프로그램이 UTF-8을 지원합니다. 앞쪽 128개의 유니코드 문자는 ASCII 문자에 대응되며 같은 바이트 값을 가지고 있습니다. U+0020부터 U+007E 까지의 유니코드 문자는 ASCII 문자 0x20 부터 0x7E 까지와 동일합니다. 라틴 알파벳을 지원하고 7비트 문자 집합을 사용하는 ASCII와는 달리, UTF-8은 한 문자를 위해서 한 개부터 네 개 사이의 8진수(octet)를 사용합니다. ("8진수"는 바이트 또는 8비트를 의미합니다.) 이 방법으로 수백만개의 문자를 표현할 수 있습니다. 다른 인코딩 표준인 UTF-16은 유니코드 문자를 표현하기 위해 2바이트를 사용합니다. 이스케이프 시퀀스를 이용하여 UTF-16은 4바이트를 써서 모든 유니코드 범위를 표현합니다. ISO UCS-2 (Universal Character Set, 세계 문자 집합)은 2바이트를 사용합니다. +

JavaScript와 Navigator가 UTF-8/유니코드를 지원한다는 것은 우리가 비 라틴 문자와 국제화되고 지역화된 문자에다 특수한 기술 분야 기호까지 JavaScript 프로그램에 쓸 수 있다는 것을 의미합니다. 유니코드는 여러 언어를 포함한 텍스트를 인코딩할 수 있는 표준적인 방법을 제공합니다. UTF-8 인코딩이 ASCII와 호환되기 때문에, ASCII 문자를 프로그램에 사용할 수 있습니다. 우리는 JavaScript의 주석, 문자열 리터럴, 식별자(identifier), 정규 표현식에 비 ASCII 유니코드 문자를 쓸 수 있습니다. +

+

유니코드 이스케이프 시퀀스

+

우리는 문자열 리터럴, 정규 표현식, 식별자에 유니코드 이스케이프 시퀀스를 사용할 수 있습니다. 이스케이프 시퀀스는 ASCII 문자 여섯 개로 이루어지는데, \u 뒤에 16진수를 표현하는 숫자 네 개가 붙은 모양입니다. 예를 들어 \u00A9는 저작권 기호를 나타냅니다. JavaScript에서 모든 유니코드 이스케이프 시퀀스는 문자 한 개로 인식됩니다. +

다음의 코드는 저작권 문자와 "Netscape Communications"라는 문자열을 반환합니다. +

+
x="\u00A9 Netscape Communications"
+

다음의 표는 자주 사용되는 특수 문자의 유니코드 값을 모은 것입니다. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
분류유니코드 값이름형식화된 이름(Format name)
공백 문자\u0009Tab<TAB>
 \u000BVertical Tab<VT>
 \u000CForm Feed<FF>
 \u0020Space<SP>
줄 끝 문자\u000ALine Feed<LF>
 \u000DCarriage Return<CR>
그 외 유니코드 이스케이프 시퀀스\u0008Backspace<BS>
 \u0009Horizontal Tab<HT>
 \u0022Double Quote"
 \u0027Single Quote'
 \u005C Backslash\
+

표 2.2: 특수 문자의 유니코드 값 +

JavaScript에서 유니코드 이스케이프 시퀀스는 Java와 다릅니다. JavaScript에서, 이스케이프 시퀀스가 특수 문자로 먼저 해석되지 않습니다. 예를 들어, 줄 끝 이스케이프 시퀀스가 문자열에 포함되어 있어도 함수에 의해 해석되기 전까지는 문자열을 자르지 않습니다. 주석에 포함된 이스케이프 시퀀스는 모두 무시됩니다. Java에서는 한 줄 주석에 이스케이프 시퀀스가 있으면 유니코드 문자로 해석됩니다. 문자열 리터럴에서 Java 컴파일러는 이스케이프 시퀀스를 먼저 해석합니다. 예를 들어 줄 끝 이스케이프 문자(즉 \u000A)가 Java에서 사용되면 문자열 리터럴을 끝나게 합니다. Java에서는 줄 끝 문자가 문자열 리터럴에 포함될 수 없으므로, 에러가 발생합니다. 문자열 리터럴에 개행 문자를 넣으려면 반드시 \n을 사용해야 합니다. JavaScript에서 이스케이프 시퀀스는 \n과 같은 방식으로 동작합니다. +

+
참고: 긴 문자열을 변환하는 웹 프로그램 Hot-Tips' Unicode Converter, by Bob Foley.
+

JavaScript 파일에서 유니코드 문자

+

초기 버전의 Gecko는 XUL에서 로드되는 JavaScript 파일의 인코딩이 Latin-1일 것이라고 가정했습니다. Gecko 1.8부터는 XUL 파일의 인코딩으로 부터 JavaScript 파일의 인코딩을 유추하도록 변경되었습니다. 더 많은 정보는 International characters in XUL JavaScript 페이지를 참고하시기 바랍니다. +

+

유니코드로 문자 표시하기

+

우리는 다른 언어나 기술 분야 기호를 표시하기 위해서 유니코드를 사용할 수 있습니다. 문자를 제대로 표시하기 위해서는 Mozilla Firefox나 Netscape 같은 클라이언트가 유니코드를 지원해야 합니다. 게다가 클라이언트에서 사용할 수 있는 적절한 유니코드 글꼴이 필요하고, 클라이언트 플랫폼이 유니코드를 지원해야 합니다. 종종 유니코드 글꼴이 모든 유니코드 문자를 표시하지 못하는 경우가 있습니다. Windows 95 같은 몇몇 플랫폼은 유니코드를 부분적으로만 지원합니다. +

비 ASCII 문자 입력을 받기 위해서는 클라이언트가 유니코드로 입력을 보내야 합니다. 표준 확장 키보드(standard enhanced keyborad)를 사용하면 클라이언트에서 유니코드가 지원하는 추가적인 문자를 쉽게 입력할 수 없습니다. 때때로 유니코드 문자를 입력하려면 유니코드 이스케이프를 사용하는 방법 밖에 없을 때도 있습니다. +

유니코드에 대한 더 많은 정보를 얻으려면 유니코드 홈페이지나 The Unicode Standard, Version 2.0, published by Addison-Wesley, 1996 를 보시기 바랍니다. +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Literals", "Core_JavaScript_1.5_Guide:Expressions") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Unicode", "fr": "fr/Guide_JavaScript_1.5/Unicode", "ja": "ja/Core_JavaScript_1.5_Guide/Unicode", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Unicode" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/values/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/values/index.html new file mode 100644 index 0000000000..8fcd0070e9 --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/values/index.html @@ -0,0 +1,39 @@ +--- +title: Values +slug: Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Values +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +

+

JavaScript는 다음과 같은 값 형식을 인식합니다. +

+ +

이렇게 조금 적어보이는 값 형식 또는 "자료형"이지만 훌륭한 기능을 작성할 수 있습니다. 정수와 실수 사이에 엄격한 구분은 없습니다. JavaScript에는 명시적인 날짜 자료형은 없습니다. 하지만 Date 개체를 이용하면 됩니다. +Object함수는 언어의 또다른 기초 요소입니다. 개체는 값을 포함할 수 있는 이름 붙은 어떤 것이라고 생각하면 되고, 함수는 프로그램이 수행할 수 있는 실행 절차라고 생각하면 됩니다. +

+

자료형 변환

+

JavaScript는 동적 타입 언어입니다. 이 말은 변수를 선언할 때 타입을 지정하지 않아도 되고, 스크립트 실행중에 필요에 따라 자동으로 자료형이 바뀐다는 말입니다. 예를 들어 다음과 같이 변수를 선언할 수 있습니다. +

+
var answer = 42
+
+

그 후에 이 변수에 문자열 값을 할당할 수 있습니다. +

+
answer = "Thanks for all the fish..."
+
+

JavaScript는 동적 타입 언어이기 때문에, 이렇게 대입하더라도 에러를 내지 않습니다. +

숫자와 문자열 값을 + 연산자로 계산하는 표현식에서, JavaScript는 숫자를 문자열로 변환합니다. 예를 들어 다음과 같은 문장을 생각해봅시다. +

+
x = "The answer is " + 42 // returns "The answer is 42"
+y = 42 + " is the answer" // returns "42 is the answer"
+
+

다른 연산자를 사용하는 문장에서는 숫자를 문자열로 변환하지 않습니다. +

+
"37" - 7 // returns 30
+"37" + 7 // returns "377"
+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:JavaScript_Overview", "Core_JavaScript_1.5_Guide:Variables") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Values", "fr": "fr/Guide_JavaScript_1.5/Valeurs", "ja": "ja/Core_JavaScript_1.5_Guide/Values", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Warto\u015bci" } ) }} diff --git a/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/variables/index.html b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/variables/index.html new file mode 100644 index 0000000000..f31c37bc9c --- /dev/null +++ b/files/ko/web/javascript/guide/obsolete_pages/core_javascript_1.5_guide/variables/index.html @@ -0,0 +1,64 @@ +--- +title: Variables +slug: Web/JavaScript/Guide/Obsolete_Pages/Core_JavaScript_1.5_Guide/Variables +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +

변수

+

우리는 프로그램 내에서 값에 이름을 부여하기 위해서 변수를 사용할 수 있습니다. 변수의 이름은 "식별자(identifier)"라고 불리며, 몇 가지 규칙을 따라야 합니다. +

JavaScript 의 식별자는 문자(letter)나 밑줄(_)이나 달러 기호($)로 시작해야 합니다. 그 뒤에는 숫자(0-9)도 올 수 있습니다. JavaScript는 대소문자를 구별하기 때문에, 문자는 대문자 "A"부터 "Z"까지와 소문자 "a"부터 "z"까지를 사용할 수 있습니다. +

JavaScript 1.5부터, 식별자에 å나 ü같은 ISO 8859-1이나 유니코드 문자를 사용할 수 있습니다. 또한 유니코드 이스케이프 시퀀스 페이지에 나열된 \uXXXX 형식 유니코드 이스케이프 시퀀스를 식별자에 쓸 수도 있습니다. +

규칙에 맞는 이름 몇 가지는 이런 것입니다. Number_hits, temp99, _name. +

+

변수 선언

+

변수를 선언하는 방법에는 두 가지가 있습니다. +

+ +

변수를 평가하기(Evaluating)

+

초기값을 지정하지 않고 var 문장을 이용해서 선언한 변수는 undefined라는 값을 갖습니다. +

선언하지 않은 변수에 접근하려고 하면 ReferenceError 예외가 발생합니다. +

+
var a;
+print("The value of a is " + a); // prints "The value of a is undefined"
+print("The value of b is " + b); // throws ReferenceError exception
+
+

변수가 값을 갖고 있는지 결정하기 위해서 undefined를 사용할 수 있습니다. 다음 코드에서 input에는 값을 할당하지 않아서 if문은 true로 평가됩니다. +

+
var input;
+if(input === undefined){
+   doThis();
+} else {
+   doThat();
+}
+

Not sure how the following is related to "Variables" section +undefined값을 참/거짓을 판별하는 구문에 쓰면 false로 평가됩니다. 예를 들어 다음 코드에서는 myArray의 원소가 정의되지 않았기 때문에 myFunction 함수가 실행됩니다. +

+
myArray=new Array()
+if (!myArray[0])
+   myFunction();
+

숫자가 필요한 문맥에서 null 변수를 평가하면 null 값은 0으로 평가되고, 참/거짓이 필요한 문맥에서는 false로 평가됩니다. +When you evaluate a null variable, the null value behaves as 0 in numeric contexts and as false in boolean contexts. For example: +

+
var n = null;
+n * 32; //0을 반환합니다
+

변수 범위

+

함 수 외부에서 선언한 변수는 "전역(global)" 변수라고 부릅니다. 그 변수는 현재 문서의 모든 코드에서 접근할 수 있기 때문입니다. 함수 안에서 선언한 변수는 "지역(local)" 변수라고 부릅니다. 그 변수는 함수 안에서만 접근할 수 있기 때문입니다. +

JavaScript에는 블록 문장 범위가 없습니다. 대신 그 블록이 포함된 코드의 지역 범위에 포함됩니다. 예를 들어 다음 코드에서는 conditionfalse이면 예외를 발생시키는 대신 0을 출력합니다. +

+
if (condition) {
+  var x = 5;
+}
+print(x ? x : 0);
+
+

JavaScript의 변수와 관련해서 또다른 색다른 점은 나중에 선언될 변수에 예외 발생없이 접근할 수 있다는 것입니다. +

+
print(x === undefined); // prints "true"
+var x = 3;
+
+

전역 변수

+

need links to pages discussing scope chains and the global object +전역 변수는, 실제로는 "전역 개체(global object)"의 속성(property)입니다. 웹 페이지에서 전역 개체는 window이므로, window.variable 문장을 이용해서 전역 변수에 접근할 수 있습니다. +

그러므로, window나 frame 이름을 이용하면 다른 window나 frame에 정의된 전역 변수에 접근할 수 있습니다. 예를 들어 phoneNumber라는 변수를 FRAMESET 문서에 정의했다면, 자식 frame에서 parent.phoneNumber로 그 변수에 접근할 수 있습니다. +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Values", "Core_JavaScript_1.5_Guide:Constants") }} +

{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Variables", "fr": "fr/Guide_JavaScript_1.5/Variables", "ja": "ja/Core_JavaScript_1.5_Guide/Variables", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/Zmienne" } ) }} diff --git a/files/ko/web/javascript/guide/text_formatting/index.html b/files/ko/web/javascript/guide/text_formatting/index.html new file mode 100644 index 0000000000..027e92c262 --- /dev/null +++ b/files/ko/web/javascript/guide/text_formatting/index.html @@ -0,0 +1,275 @@ +--- +title: 텍스트 서식 +slug: Web/JavaScript/Guide/Text_formatting +translation_of: Web/JavaScript/Guide/Text_formatting +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}
+ +

이 장에서는 JavaScript에서 문자열과 텍스트로 작업하는 방법을 소개합니다.

+ +

문자열

+ +

 JavaScript의 {{Glossary("문자열")}} 유형은 원문의 데이터를 나타내는데 사용됩니다. 이는 16비트 부호 없는 정수 값(UTF-16 code units)의 "요소" 집합입니다. String의 각 요소(문자)는 String에서 하나의 위치를 차지합니다. 첫 번째 요소는 인덱스 0 다음은 인덱스 1 등등... 문자열의 길이는 요소의 수와 같습니다. 문자열 리터럴 또는 문자열 객체를 사용하여 문자열을 만들 수 있습니다.

+ +

 

+ +

주의 : 이페이지를 수정한다면 MDN bug 857438이 해결될 때 까지 U+FFFF이상의 문자를 포함하지 마세요. ( https://bugzilla.mozilla.org/show_bug.cgi?id=857438 ).

+ +

문자열 리터럴

+ +

작은따옴표나 큰따옴표를 사용하여 간단한 문자열을 만들 수 있습니다:

+ +
'foo'
+"bar"
+ +

보다 많은 문자열을 이스케이프 시퀀스를 사용하여 만들 수 있습니다

+ +

16진수 이스케이프 시퀀스

+ +

\x 뒤에 수는 16진수로 해석(interpreted)됩니다.

+ +
'\xA9' // "©"
+
+ +

유니코드 이스케이프 시퀀스

+ +

유니코드 이스케이프 시퀀스는 \u 다음에 적어도 네 개의 16진수 숫자(digit)를 필요로 합니다.

+ +
'\u00A9' // "©"
+ +

유니코드 코드 포인트 이스케이프

+ +

ECMAScript 6의 새로운 기능. 유니 코드 포인트 이스케이프를 사용하면 16 진수를 사용하여 모든 문자를 이스케이프 처리 할 수 ​​있으므로 최대 0x10FFFF의 유니 코드 코드 포인트를 사용할 수 있습니다. 간단한 유니 코드 이스케이프를 사용하면 동일한 결과를 얻기 위해서 서로 게이트를 별도로 작성해야하는 경우가 있습니다.

+ +

{{jsxref("String.fromCodePoint()")}} 나 {{jsxref("String.prototype.codePointAt()")}}를 참고하세요.

+ +
'\u{2F804}'
+
+// the same with simple Unicode escapes
+'\uD87E\uDC04'
+ +

문자열 개체

+ +

{{jsxref("문자열")}} 개체는 문자열 기본 데이터 형식의 래퍼입니다.

+ +
var s = new String("foo"); // Creates a String object
+console.log(s); // Displays: { '0': 'f', '1': 'o', '2': 'o'}
+typeof s; // Returns 'object'
+
+ +

여러분은 문자열 리터럴 값에 문자열 개체의 방법 중 하나를 호출 할 수 있습니다.—JavaScript가 자동으로 문자열 리터럴을 임시 문자열 개체로 변환하고, 메서드를 호출하고, 그리고나서 임시 문자열 개체를 삭제합니다. 또한, String.length 속성을 문자열 리터럴과 함께 사용할 수 있습니다.

+ +

특별히 String 개체를 사용할 필요가 없지 않는 한, String 개체는 직관에 반하는 행동을 할 수 있기 때문에 여러분은 string 리터럴을 사용해야합니다. 예를들어:

+ +
var s1 = "2 + 2"; // Creates a string literal value
+var s2 = new String("2 + 2"); // Creates a String object
+eval(s1); // Returns the number 4
+eval(s2); // Returns the string "2 + 2"
+ +

문자열 개체 문자열의 문자 수를 나타내는 하나의 속성, 길이를 갖습니다. 예를 들어, "Hello, World!"가 13자 이므로 다음 코드는 x를 값 13으로 할당합니다. String 객체는 문자열에있는 UTF-16 코드 단위의 수를 나타내는 길이가 하나의 속성을 가집니다. 예를 들어, 다음 코드에서는 "Hello, World!"가 UTF-16 코드 단위로 표현되는 13개의 문자를 가지고 있기 때문에 x 값이 13이 됩니다. 배열 브래킷 스타일을 사용하여 각 코드 단위에 액세스 할 수 있습니다. 문자열은 변경 불가능한 배열과 같은 객체이기 때문에 개별 문자를 변경할 수 없습니다.

+ +
var mystring = 'Hello, World!';
+var x = mystring.length;
+mystring[0] = 'L'; // This has no effect, because strings are immutable
+mystring[0]; // This returns "H"
+ +

유니 코드 스칼라 값이 U + FFFF (희귀 한 중국어 / 일본어 / 한국어 / 베트남어 문자 및 일부 이모티콘)보다 큰 문자는 각각 서로 다른 두 개의 코드 단위로 UTF-16에 저장됩니다. 예를 들어, 단일 문자 U + 1F600 "Emoji grinning face"를 포함하는 문자열은 길이가 2입니다. 대괄호를 사용하여 이러한 문자열의 개별 코드 단위에 액세스하면 일치하지 않는 대리 코드 단위가있는 문자열이 만들어지는 등의 바람직하지 않은 결과가 발생할 수 있습니다. 유니 코드 표준 위반 MDN 버그 857438이 수정 된 후에 예제가 이 페이지에 추가되어야합니다. {{jsxref ( "String.fromCodePoint ()")}} 또는 {{jsxref ( "String.prototype.codePointAt ()")}}도 참조하십시오.

+ +

String 객체는 다양한 메서드가 있습니다: 문자열 자체의 변경된 결과를 반환하는 substringtoUpperCase가 그것!

+ +

다음 표는 {{jsxref("문자열")}} 개체의 메서드를 요약한 것입니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

문자열 메서드

+
MethodDescription
{{jsxref("String.charAt", "charAt")}}, {{jsxref("String.charCodeAt", "charCodeAt")}}, {{jsxref("String.codePointAt", "codePointAt")}} +

문자열에서 지정된 위치에 있는 문자나 문자 코드를 반환합니다.

+
{{jsxref("String.indexOf", "indexOf")}}, {{jsxref("String.lastIndexOf", "lastIndexOf")}} +

문자열에서 지정된 부분 문자열의 위치나 지정된 부분 문자열의 마지막 위치를 각각 반환합니다.

+
{{jsxref("String.startsWith", "startsWith")}}, {{jsxref("String.endsWith", "endsWith")}}, {{jsxref("String.includes", "includes")}} +

문자열 시작하고, 끝나고, 지정된 문자열을 포함하는지의 여부를 반환합니다.

+
{{jsxref("String.concat", "concat")}} +

두 문자열의 텍스트를 결합하고 새로운 문자열을 반환합니다.

+
{{jsxref("String.fromCharCode", "fromCharCode")}}, {{jsxref("String.fromCodePoint", "fromCodePoint")}} +

유니코드 값의 지정된 시퀀스로부터 문자열을 구축합니다. 문자열 인스턴스가 아닌 문자열 클래스의 메서드입니다.

+
{{jsxref("String.split", "split")}} +

부분 문자열로 문자열을 분리하여 문자열 배열로 문자열 개체를 분할합니다.

+
{{jsxref("String.slice", "slice")}} +

문자열의 한 부분을 추출하고 새 문자열을 반환합니다.

+
{{jsxref("String.substring", "substring")}}, {{jsxref("String.substr", "substr")}} +

어느 시작 및 종료 인덱스 또는 시작 인덱스 길이를 지정하여, 문자열의 지정된 일부를 반환합니다.

+
{{jsxref("String.match", "match")}}, {{jsxref("String.replace", "replace")}}, {{jsxref("String.search", "search")}} +

정규 표현식으로 작업합니다.

+
{{jsxref("String.toLowerCase", "toLowerCase")}},
+ {{jsxref("String.toUpperCase", "toUpperCase")}}
+

.모든 소문자 또는 대문자에서 각각 문자열을 반환합니다.

+
{{jsxref("String.normalize", "normalize")}}호출 문자열 값 유니 코드 표준화 양식을 반환합니다.
{{jsxref("String.repeat", "repeat")}} +

주어진 회를 반복하는 개체 요소로 이루어진 문자열을 반환합니다.

+
{{jsxref("String.trim", "trim")}}문자열의 시작과 끝에서 공백을 자릅니다.
+ +

다중 선 템플릿 문자열

+ +

템플릿 문자열은 포함 식을 용납하는 문자열 리터럴입니다. 여러분은 그것들과 함께 다중 선 문자열 및 문자열 보간 기능을 사용할 수 있습니다.

+ +

템플릿 문자열은 작은따옴표나 큰따옴표 대신에 back-tick (` `) (grave accent)문자로 묶습니다. 템플릿 문자열은 자리 표시자를 포함 할 수 있습니다. 이들은 달러 기호 중괄호로 표시됩니다.  (${expression})

+ +

다중 선

+ +

소스에 삽입하는 새로운 선 문자는 템플릿 문자열의 일부입니다. 정상적인 문자열을 사용하면, 여러분은 다중 선 문자열을 얻기 위해 다음과 같은 구문을 사용해야합니다:

+ +
console.log("string text line 1\n\
+string text line 2");
+// "string text line 1
+// string text line 2"
+ +

다중 선 문자열과 같은 효과를 얻기 위해, 여러분은 이제 쓸 수 있습니다:

+ +
console.log(`string text line 1
+string text line 2`);
+// "string text line 1
+// string text line 2"
+ +

포함식

+ +

일반 문자열 내에서 표현식을 포함하기 위해, 다음과 같은 구문을 사용합니다:

+ +
var a = 5;
+var b = 10;
+console.log("Fifteen is " + (a + b) + " and\nnot " + (2 * a + b) + ".");
+// "Fifteen is 15 and
+// not 20."
+ +

이제, 템플릿 문자열을 가지고, 여러분은 읽기와 같이 대체를 만드는 syntactic sugar의 사용을 할 수 있습니다:

+ +
var a = 5;
+var b = 10;
+console.log(`Fifteen is ${a + b} and\nnot ${2 * a + b}.`);
+// "Fifteen is 15 and
+// not 20."
+ +

자세한 내용은 JavaScript 참조에서 템플릿 문자열에 대해 읽어보세요.

+ +

국제화

+ +

{{jsxref("Intl")}} 개체는  ECMA스크립트 국제 API에 언어와 문자열과 숫자서식과 날짜와 시간서식을 제공하는 명칭공간입니다.  {{jsxref("Collator")}}, {{jsxref("NumberFormat")}}, 와 {{jsxref("DateTimeFormat")}} 개체들을 위한 생성자들은  Intl 개체의 특성들입니다.

+ +

날짜와 시간서식

+ +

{{jsxref("DateTimeFormat")}} 개체는 날짜와 시간을 서식하기에 유용합니다. 다음 코드는 미국에서 쓰이는 영어로 날짜를 서식합니다. (결과는 다른 시간대와 다릅니다)

+ +
var msPerDay = 24 * 60 * 60 * 1000;
+
+// July 17, 2014 00:00:00 UTC.
+var july172014 = new Date(msPerDay * (44 * 365 + 11 + 197));
+
+var options = { year: "2-digit", month: "2-digit", day: "2-digit",
+                hour: "2-digit", minute: "2-digit", timeZoneName: "short" };
+var americanDateTime = new Intl.DateTimeFormat("en-US", options).format;
+
+console.log(americanDateTime(july172014)); // 07/16/14, 5:00 PM PDT
+
+ +

숫자 서식

+ +

{{jsxref("NumberFormat")}}개체는 통화를 위해 숫자를 서식하는것에 대해 유용하다.

+ +
var gasPrice = new Intl.NumberFormat("en-US",
+                        { style: "currency", currency: "USD",
+                          minimumFractionDigits: 3 });
+
+console.log(gasPrice.format(5.259)); // $5.259
+
+var hanDecimalRMBInChina = new Intl.NumberFormat("zh-CN-u-nu-hanidec",
+                        { style: "currency", currency: "CNY" });
+
+console.log(hanDecimalRMBInChina.format(1314.25)); // ¥ 一,三一四.二五
+
+ +

조합

+ +

{{jsxref("Collator")}}개체는 문자열을 비교하고 구분하는 것에 대해 유용합니다.

+ +

예를 들어, 실제로 독일에선 phonebook과 dictionary라는 2개의 다른 종류의 명령어들이 있습니다. 전화기록부류는 소리를 강조합니다. 그리고 구분에 앞서 다른것들은 “ä”, “ö”인것처럼 "ae", "oe"로 확장됐습니다. 

+ +
var names = ["Hochberg", "Hönigswald", "Holzman"];
+
+var germanPhonebook = new Intl.Collator("de-DE-u-co-phonebk");
+
+// as if sorting ["Hochberg", "Hoenigswald", "Holzman"]:
+console.log(names.sort(germanPhonebook.compare).join(", "));
+// logs "Hochberg, Hönigswald, Holzman"
+
+ +

어떤 독일말들은 여분의 변모음과 함께 활용한다. 그래서 사전안에서 이것은 변모음을 무시하라고 명령하기에 실용적이다.

+ +
var germanDictionary = new Intl.Collator("de-DE-u-co-dict");
+
+// as if sorting ["Hochberg", "Honigswald", "Holzman"]:
+console.log(names.sort(germanDictionary.compare).join(", "));
+// logs "Hochberg, Holzman, Hönigswald"
+
+ +

{{jsxref("Intl")}}API에 대한 자세한 내용은 Introducing the JavaScript Internationalization API를 참조하세요.

+ +

{{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}

diff --git a/files/ko/web/javascript/guide/using_promises/index.html b/files/ko/web/javascript/guide/using_promises/index.html new file mode 100644 index 0000000000..bc847e561a --- /dev/null +++ b/files/ko/web/javascript/guide/using_promises/index.html @@ -0,0 +1,361 @@ +--- +title: Using promises +slug: Web/JavaScript/Guide/Using_promises +tags: + - Promise + - Promises +translation_of: Web/JavaScript/Guide/Using_promises +--- +
{{jsSidebar("JavaScript Guide")}}{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}}
+ +

{{jsxref("Promise")}}는 비동기 작업의 최종 완료 또는 실패를 나타내는 객체입니다. 대부분 여러분은 이미 만들어진 promise를 사용했었기 때문에 이 가이드에서는 어떻게 promise를 만드는지 설명하기에 앞서 promise의 사용법에 대해 설명합니다.

+ +

기본적으로 promise는 함수에 콜백을 전달하는 대신에, 콜백을 첨부하는 방식의 객체입니다.
+  

+ +

비동기로 음성 파일을 생성해주는  createAudioFileAsync()라는 함수가 있었다고 생각해보세요. 해당 함수는 음성 설정에 대한 정보를 받고, 두 가지 콜백 함수를 받습니다. 하나는 음성 파일이 성공적으로 생성되었을때 실행되는 콜백, 그리고 다른 하나는 에러가 발생했을때 실행되는 콜백입니다.

+ +

createAudioFileAsync()는 함수는 아래와 같이 사용됩니다.  

+ +
function successCallback(result) {
+  console.log("Audio file ready at URL: " + result);
+}
+
+function failureCallback(error) {
+  console.log("Error generating audio file: " + error);
+}
+
+createAudioFileAsync(audioSettings, successCallback, failureCallback);
+ +

…모던한 함수들은 위와 같이 콜백들을 전달지 않고 콜백을 붙여 사용할 수 있게 Promise를 반환해줍니다.

+ +

만약 createAudioFileAsync() 함수가 Promise를 반환해주도록 수정해본다면, 다음과 같이 간단하게 사용되어질 수 있습니다.

+ +
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
+ +

…조금 더 간단하게 써보자면:

+ +
const promise = createAudioFileAsync(audioSettings);
+promise.then(successCallback, failureCallback);
+ +

우리는 이와 같은 것을 비동기 함수 호출이라고 부릅니다. 이런 관례는 몇 가지 장점을 갖고 있습니다. 각각에 대해 한번 살펴보도록 합시다.

+ +

Guarantees

+ +

콜백 함수를 전달해주는 고전적인 방식과는 달리, Promise는 아래와 같은 특징을 보장합니다.

+ + + +

Promise의 가장 뛰어난 장점 중의 하나는 chaining입니다.

+ +

Chaining

+ +

보통 하나나 두 개 이상의 비동기 작업을 순차적으로 실행해야 하는 상황을 흔히 보게 됩니다. 순차적으로 각각의 작업이 이전 단계 비동기 작업이 성공하고 나서 그 결과값을 이용하여 다음 비동기 작업을 실행해야 하는 경우를 의미합니다. 우리는 이런 상황에서 promise chain을 이용하여 해결하기도 합니다.

+ +

then() 함수는 새로운 promise를 반환합니다. 처음에 만들었던 promise와는 다른 새로운 promise입니다.

+ +
const promise = doSomething();
+const promise2 = promise.then(successCallback, failureCallback);
+
+ +

또는

+ +
const promise2 = doSomething().then(successCallback, failureCallback);
+
+ +

두 번째 promise는 doSomething() 뿐만 아니라 successCallback or failureCallback 의 완료를 의미합니다. successCallback or failureCallback 또한 promise를 반환하는 비동기 함수일 수도 있습니다. 이 경우 promise2에 추가 된 콜백은 successCallback또는 failureCallback에 의해 반환된 promise 뒤에 대기합니다.

+ +

기본적으로, 각각의 promise는 체인 안에서 서로 다른 비동기 단계의 완료를 나타냅니다.

+ +

예전에는 여러 비동기 작업을 연속적으로 수행하면 고전적인 '지옥의 콜백 피라미드'가 만들어 졌었습니다.

+ +
doSomething(function(result) {
+  doSomethingElse(result, function(newResult) {
+    doThirdThing(newResult, function(finalResult) {
+      console.log('Got the final result: ' + finalResult);
+    }, failureCallback);
+  }, failureCallback);
+}, failureCallback);
+
+ +

모던한 방식으로 접근한다면, 우리는 콜백 함수들을 반환된 promise에 promise chain을 형성하도록 추가할 수 있습니다:

+ +
doSomething().then(function(result) {
+  return doSomethingElse(result);
+})
+.then(function(newResult) {
+  return doThirdThing(newResult);
+})
+.then(function(finalResult) {
+  console.log('Got the final result: ' + finalResult);
+})
+.catch(failureCallback);
+
+ +

then 에 넘겨지는 인자는 선택적(optional)입니다. 그리고 catch(failureCallback) 는 then(null, failureCallback) 의 축약입니다. 이 표현식을 화살표 함수로 나타내면 다음과 같습니다.

+ +
doSomething()
+.then(result => doSomethingElse(result))
+.then(newResult => doThirdThing(newResult))
+.then(finalResult => {
+  console.log(`Got the final result: ${finalResult}`);
+})
+.catch(failureCallback);
+
+ +

중요: 반환값이 반드시 있어야 합니다, 만약 없다면 콜백 함수가 이전의 promise의 결과를 받지 못합니다.
+ (화살표 함수 () => x는 () => {return x;}와 같습니다).

+ +

Chaining after a catch

+ +

chain에서 작업이 실패한 후에도 새로운 작업을 수행하는 것이 가능하며 매우 유용합니다. (예 : catch) 다음 예를 읽으십시오:

+ +
new Promise((resolve, reject) => {
+    console.log('Initial');
+
+    resolve();
+})
+.then(() => {
+    throw new Error('Something failed');
+
+    console.log('Do this');
+})
+.catch(() => {
+    console.log('Do that');
+})
+.then(() => {
+    console.log('Do this, whatever happened before');
+});
+
+ +

그러면 다음 텍스트가 출력됩니다.

+ +
Initial
+Do that
+Do this, whatever happened before
+
+ +

참고: "Do this" 텍스트가 출력되지 않은 것을 주의깊게 보십시오. "Something failed" 에러가 rejection을 발생시켰기 때문입니다.

+ +

Error propagation

+ +

'콜백 지옥'에서 failureCallback이 3번 발생한 것을 기억 할 것입니다. promise chain에서는 단 한 번만 발생하는것과 비교되죠.

+ +
doSomething()
+.then(result => doSomethingElse(result))
+.then(newResult => doThirdThing(newResult))
+.then(finalResult => console.log(`Got the final result: ${finalResult}`))
+.catch(failureCallback);
+ +

기본적으로 promise chain은 예외가 발생하면 멈추고 chain의 아래에서 catch를 찾습니다. 이것은 동기 코드가 어떻게 동작 하는지 모델링 한 것입니다.

+ +
try {
+  const result = syncDoSomething();
+  const newResult = syncDoSomethingElse(result);
+  const finalResult = syncDoThirdThing(newResult);
+  console.log(`Got the final result: ${finalResult}`);
+} catch(error) {
+  failureCallback(error);
+}
+ +

비동기 코드를 사용한 이러한 대칭성은 ECMAScript 2017에서 async/await 구문(Syntactic sugar) 에서 최고로 느낄 수 있습니다.

+ +
async function foo() {
+  try {
+    const result = await doSomething();
+    const newResult = await doSomethingElse(result);
+    const finalResult = await doThirdThing(newResult);
+    console.log(`Got the final result: ${finalResult}`);
+  } catch(error) {
+    failureCallback(error);
+  }
+}
+ +

이것은 promise를 기반으로 합니다. doSomething()은 이전 함수와 같습니다. 문법은 이곳에서 확인 할 수 있습니다.

+ +

Promise는 모든 오류를 잡아내어, 예외 및 프로그래밍 오류가 발생해도 콜백 지옥의 근본적인 결함을 해결합니다. 이는 비동기 작업의 기능 구성에 필수적입니다.

+ +

Promise rejection events

+ +

Promise가 reject될 때마다 두 가지 이벤트 중 하나가 전역 범위에 발생합니다.(일반적으로, 전역 범위는 {{domxref("window")}}거나, 웹 워커에서 사용되는 경우, {{domxref("Worker")}}, 혹은 워커 기반 인터페이스입니다.) 두 가지 이벤트는 다음과 같습니다.

+ +
+
{{domxref("Window.rejectionhandled_event", "rejectionhandled")}}
+
executor의 reject함수에 의해 reject가 처리 된 후 promise가 reject 될 때 발생합니다.
+
{{domxref("Window.unhandledrejection_event", "unhandledrejection")}}
+
promise가 reject되었지만 사용할 수 있는 reject 핸들러가 없을 때 발생합니다.
+
+ +

({{domxref("PromiseRejectionEvent")}} 유형인) 두 이벤트에는 멤버 변수인 promise와 reason 속성이 있습니다. {{domxref ( "PromiseRejectionEvent.promise", "promise")}}는 reject된 promise를 가리키는 속성이고, {{domxref ( "PromiseRejectionEvent.reason", "reason")}}은 promise가 reject된 이유를 알려 주는 속성입니다.

+ +

이들을 이용해 프로미스에 대한 에러 처리를 대체(fallback)하는 것이 가능해지며, 또한 프로미스 관리시 발생하는 이슈들을 디버깅하는 데 도움을 얻을 수 있습니다. 이 핸들러들은 모든 맥락에서 전역적(global)이기 때문에, 모든 에러는 발생한 지점(source)에 상관없이 동일한 핸들러로 전달됩니다.

+ +

특히 유용한 사례 : {{Glossary("Node.js")}}로 코드를 작성할 때, 흔히 프로젝트에서 사용하는 모듈이 reject된 프로미스를 처리하지 않을 수 있습니다. 이런 경우 노드 실행시 콘솔에 로그가 남습니다. 이를 수집에서 분석하고 직접 처리할 수도 있습니다. 아니면 그냥 콘솔 출력을 어지럽히는 것을 막기 위해 그럴 수도 있죠. 이런 식으로 {{domxref("Window.unhandledrejection_event", "unhandledrejection")}}(영어) 이벤트를 처리하는 핸들러를 추가하면 됩니다.

+ +
window.addEventListener("unhandledrejection", event => {
+  /* You might start here by adding code to examine the
+     promise specified by event.promise and the reason in
+     event.reason */
+
+  event.preventDefault();
+}, false);
+ +

이벤트의 {{domxref("Event.preventDefault", "preventDefault()")}} 메서드를 호출하면 reject 된 프로미스가 처리되지 않았을 때 JavaScript 런타임이 기본 동작을 수행하지 않습니다. 이 기본 동작은 대개 콘솔에 오류를 기록하는 것이기 때문에, 이것은 확실히 NodeJS를 위한 것이죠.

+ +

제대로 하려면, 당연한 말이지만, 이 이벤트를 그냥 무시해버리기 전에 reject된 프로미스 코드에 실제로 버그가 없는지 확실히 검사해야 합니다.

+ +

오래된 콜백 API를 사용하여 Promise만들기

+ +

{{jsxref ( "Promise")}}는 생성자를 사용하여 처음부터 생성 될 수 있습니다. 이것은 오래된 API를 감쌀 때만 필요합니다.

+ +

이상적인 프로그래밍 세계에서는 모든 비동기 함수는 promise을 반환해야 하지만. 불행히도 일부 API는 여전히 success 및 / 또는 failure 콜백을 전달하는 방식일거라 생각합니다.. 예를 들면 {{domxref ( "WindowTimers.setTimeout", "setTimeout ()")}} 함수가 있습니다.

+ +
setTimeout(() => saySomething("10 seconds passed"), 10000);
+
+ +

예전 스타일의 콜백과 Promise를 합치는것 문제가 있습니다. 함수 saySomething()이 실패하거나 프로그래밍 오류가 있으면 아무 것도 잡아 내지 않습니다. setTimeout의 문제점 입니다.

+ +

다행히도 우리는 setTimeout을 Promise로 감쌀 수 있습니다. 가장 좋은 방법은 가능한 가장 낮은 수준에서 문제가되는 함수를 래핑 한 다음 다시는 직접 호출하지 않는 것입니다.

+ +
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback);
+
+ +

기본적으로 promise constructor는 promise를 직접 해결하거나 reject 할 수 있는 실행자 함수를 사용합니다. setTimeout()은 함수에서 fail이 일어나거나 error가 발생하지 않기 때문에 이 경우 reject를 사용하지 않습니다.

+ +

Composition

+ +

{{jsxref ( "Promise.resolve ()")}}와 {{jsxref ( "Promise.reject ()")}}는 각각 이미 resolve되거나 reject 된 promise를 여러분이 직접 생성하기위한 바로 가기입니다. 가끔 유용하게 사용됩니다.

+ +

{{jsxref("Promise.all()")}}와 {{jsxref("Promise.race()")}}는 비동기 작업을 병렬로 실행하기위한 두 가지 구성 도구입니다.

+ +

우리는 병렬로 작업을 시작하고 모든 작업이 다음과 같이 끝날 때까지 기다릴 수 있습니다.

+ +
Promise.all([func1(), func2(), func3()])
+.then(([result1, result2, result3]) => { /* use result1, result2 and result3 */ });
+ +

Sequential composition is possible using some clever JavaScript:

+ +

고급진 JavaScript를 사용하여 순차적 구성이 가능합니다.

+ +
[func1, func2, func3].reduce((p, f) => p.then(f), Promise.resolve())
+.then(result3 => { /* use result3 */ });
+
+ +

기본적으로 Promise.resolve().then(func1).then(func2).then(func3);과 같은 약속 체인으로 비동기 함수 배열을 축소합니다.

+ +

이것은 재사용 가능한 작성 기능으로 만들 수 있는데, 이는 함수형 프로그래밍에서 일반적인 방식입니다.

+ +
const applyAsync = (acc,val) => acc.then(val);
+const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));
+
+ +

composeAsync() 함수는 여러 함수를 인수로 받아들이고 composition 파이프 라인을 통해 전달되는 초기 값을 허용하는 새 함수를 반환합니다.

+ +
const transformData = composeAsync(func1, func2, func3);
+const result3 = transformData(data);
+
+ +

ECMAScript 2017에서는 async / await를 사용하여 순차적 구성을보다 간단하게 수행 할 수 있습니다.

+ +
let result;
+for (const f of [func1, func2, func3]) {
+  result = await f(result);
+}
+/* use last result (i.e. result3) */
+ +

Timing

+ +

To avoid surprises, functions passed to then() will never be called synchronously, even with an already-resolved promise:

+ +

놀라움(역자 주. 에러가 난다거나, 코드가 문제가 생긴다거나..했을때의 그 놀라움..)을 피하기 위해 then()에 전달 된 함수는 already-resolved promise에 있는 경우에도 동기적으로 호출되지 않습니다.

+ +
Promise.resolve().then(() => console.log(2));
+console.log(1); // 1, 2
+
+ +

즉시 실행되는 대신 전달 된 함수는 마이크로 태스크 대기열에 저장됩니다. 즉, 자바 스크립트 이벤트 루프의 현재 실행이 끝날 때 대기열이 비면 나중에 실행됩니다.

+ +
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+wait().then(() => console.log(4));
+Promise.resolve().then(() => console.log(2)).then(() => console.log(3));
+console.log(1); // 1, 2, 3, 4
+ +

Nesting

+ +
+

역자 주. 아래부분에 대한 번역이 미흡합니다. 원문을 참고해 주세요

+
+ +

간단한 promise 체인은 중첩이 부주의 한 구성의 결과 일 수 있으므로 중첩하지 않고 평평하게 유지하는 것이 가장 좋습니다. common mistakes를 참조하십시오.

+ +

(Simple promise chains are best kept flat without nesting, as nesting can be a result of careless composition. See common mistakes.)

+ +

중첩은 catch 문 범위를 제한하는 제어 구조입니다. 특히, 중첩 된 catch는 중첩 된 범위 외부의 체인에있는 오류가 아닌 범위 및 그 이하의 오류 만 잡습니다. 올바르게 사용하면 오류 복구에서보다 정확한 결과를 얻을 수 있습니다.

+ +
doSomethingCritical()
+.then(result => doSomethingOptional(result)
+  .then(optionalResult => doSomethingExtraNice(optionalResult))
+  .catch(e => {})) // Ignore if optional stuff fails; proceed.
+.then(() => moreCriticalStuff())
+.catch(e => console.log("Critical failure: " + e.message));
+
+ +

여기에 있는 선택적 단계는 들여 쓰기가 아닌 중첩되어 있지만 주위의 바깥 쪽 ( 및 ) 의 규칙적이지 않은 배치를 하지않도록 조심하세요.

+ +

inner neutralizing catch 문은 doSomethingOptional()doSomethingExtraNice()에서 발생한 오류를 catch 한 후에 코드가 moreCriticalStuff()로 다시 시작됩니다. 중요하게도 doSomethingCritical()이 실패하면 해당 오류는 최종 (외부) catch에 의해서만 포착됩니다.

+ +

Common mistakes

+ +

promise chains을 작성할 때 주의해야 할 몇 가지 일반적인 실수는 다음과 같습니다. 이러한 실수 중 몇 가지는 다음 예제에서 나타납니다.

+ +
// Bad example! Spot 3 mistakes!
+
+doSomething().then(function(result) {
+  doSomethingElse(result) // Forgot to return promise from inner chain + unnecessary nesting
+  .then(newResult => doThirdThing(newResult));
+}).then(() => doFourthThing());
+// Forgot to terminate chain with a catch!
+
+ +

첫 번째 실수는 제대로 체인을 연결하지 않는 것입니다. 이것은 우리가 새로운 promise를 만들었지 만 그것을 반환하는 것을 잊었을때 일어납니다. 결과적으로 체인이 끊어 지거나 오히려 두 개의 독립적 인 체인이 경쟁하게됩니다. 즉, doFourthThing()doSomethingElse() 또는 doThirdThing()이 완료 될 때까지 기다리지 않고 의도하지 않은 것처럼 병렬로 실행됩니다. 별도의 체인은 별도의 오류 처리 기능을 가지고있어서 잡기 어려운 오류가 발생합니다.

+ +

두 번째 실수는 불필요하게 중첩되어 첫 번째 실수를 가능하게 만드는 것입니다. 중첩은 내부 오류 처리기의 범위를 제한합니다. 의도하지 않은 경우 에러가 캐치되지 않는 오류가 발생할 수 있습니다. 이 변형은 promise constructor anti-pattern입니다.이 패턴은 이미 약속을 사용하는 코드를 감싸기 위해 promise 생성자의 중복 사용과 중첩을 결합합니다.

+ +

세 번째 실수는 catch로 체인을 종료하는 것을 잊는 것입니다. 약속되지 않은 약속 체인은 대부분의 브라우저에서 예상하지 못한 약속 거부를 초래합니다.

+ +

좋은 경험 법칙은 항상 약속의 사슬을 반환하거나 종결하는 것이며, 새로운 약속을 얻 자마자 즉각적으로 돌려서 물건을 평평하게하는 것입니다.

+ +
doSomething()
+.then(function(result) {
+  return doSomethingElse(result);
+})
+.then(newResult => doThirdThing(newResult))
+.then(() => doFourthThing())
+.catch(error => console.log(error));
+ +

() => x 은  () => { return x; }.의 축약형임을 참고하세요

+ +

이제는 적절한 오류 처리 기능을 갖춘 결정성있는 단일 체인이 있습니다.

+ +

async/await를 사용하면 대부분의 문제를 해결할 수 있습니다. 이러한 문법의 가장 흔한 실수는 await키워드를 빼먹는 것입니다.

+ +

See also

+ + + +

{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}}

diff --git a/files/ko/web/javascript/guide/values,_variables,_and_literals/index.html b/files/ko/web/javascript/guide/values,_variables,_and_literals/index.html new file mode 100644 index 0000000000..629cbd069a --- /dev/null +++ b/files/ko/web/javascript/guide/values,_variables,_and_literals/index.html @@ -0,0 +1,708 @@ +--- +title: 문법과 자료형 +slug: 'Web/JavaScript/Guide/Values,_variables,_and_literals' +tags: + - Guide + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/소개", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}
+ +

이 장은 JavaScript의 기본 문법과 변수 선언, 자료형 및 리터럴을 다룹니다.

+ +

기본

+ +

JavaScript는 문법의 대부분을 Java와 C, C++로부터 차용하고 있으며, Awk, Perl, Python의 영향도 받았습니다.

+ +

JavaScript는 대소문자를 구별하며 유니코드 문자셋을 이용합니다. 따라서 다음과 같은 코드도 유효합니다.

+ +
var 갑을 = "병정";
+var Früh = "foobar"; // Früh: 독일어로 "이른"
+
+ +

하지만 Frühfrüh와 다릅니다. 대소문자를 구분하기 때문입니다.

+ +

JavaScript에서는 명령을 {{Glossary("Statement", "명령문(statement)")}}이라고 부르며, 세미콜론(;)으로 구분합니다.

+ +

명령문이 한 줄을 다 차지할 경우에는 세미콜론이 필요하지 않습니다. 그러나 한 줄에 두 개 이상의 명령문이 필요하다면 세미콜론으로 구분해야 합니다. ECMAScript는 세미콜론을 자동으로 삽입해 명령문을 끝내는 규칙(ASI)도 가지고 있습니다. (더 많은 정보는 JavaScript의 어휘 문법 에 대한 자세한 참고서를 참고하세요) 하지만, 세미콜론이 필요하지 않은 경우라도 항상 세미콜론으로 끝마치는 편이 버그 예방 차원에서 더 좋은 습관이라고 여겨집니다.

+ +

JavaScript의 스크립트 소스는 왼쪽에서 오른쪽으로 탐색하면서 토큰, 제어 문자, 줄바꿈 문자, 주석이나 공백으로 이루어진 입력 element의 시퀀스로 변환됩니다. 스페이스, 탭, 줄바꿈 문자는 공백으로 간주됩니다.

+ +

주석

+ +

주석의 구문은 C++ 및 다른 많은 언어와 똑같습니다.

+ +
// 한 줄 주석
+
+/* 이건 더 긴,
+ * 여러 줄 주석입니다.
+ */
+
+/* 그러나, /* 중첩된 주석은 쓸 수 없습니다 */ SyntaxError */
+ +

주석은 공백처럼 행동하며 스크립트 실행 시 버려집니다.

+ +
+

참고: 몇몇 자바스크립트 파일의 시작부에 #!/usr/bin/env node와 같은 형태의 주석 문법이 쓰이는 것을 볼 수 있습니다. 이것은 해시백 주석 문법이라고 하는데, 이 특별한 주석은 스크립트를 실행할 때 쓸 특별한 자바스크립트 인터프리터의 경로를 설정할 때 쓰입니다.  해시백 주석을 참고하여 자세한 내용을 확인할 수 있습니다.

+
+ +

선언

+ +

JavaScript의 선언에는 3가지 방법이 있습니다.

+ +
+
{{jsxref("Statements/var", "var")}}
+
변수를 선언. 추가로 동시에 값을 초기화.
+
{{jsxref("Statements/let", "let")}}
+
블록 범위(scope) 지역 변수를 선언. 추가로 동시에 값을 초기화.
+
{{jsxref("Statements/const", "const")}}
+
블록 범위 읽기 전용 상수를 선언.
+
+ +

변수

+ +

어플리케이션에서 값에 상징적인 이름으로 변수를 사용합니다. 변수명은 {{Glossary("식별자(identifier)")}}라고 불리며 특정 규칙을 따릅니다.

+ +

JavaScript 식별자는 문자, 밑줄(_) 혹은 달러 기호($)로 시작해야 하는 반면 이후는 숫자(0-9)일 수도 있습니다. JavaScript가 대소문자를 구분하기에, 문자는 "A"부터 "Z"(대문자)와 "a"부터 "z"(소문자)까지 모두 포함합니다.

+ +

ISO 8859-1 혹은 Unicode 문자(가령 å 나 ü)도 식별자에 사용할 수 있습니다(좀 더 상세한 내용은 이 블로그 글을 참고). 또한 Unicode escape sequences도 식별자에 문자로 사용할 수 있습니다.

+ +

적절한 이름으로는 Number_hits, temp99, $credit_name등입니다.

+ +

변수 선언

+ +

변수 선언은 아래 3가지 방법으로 가능합니다.

+ + + +

간단히 변수에 값을 할당 할 수도 있습니다. 예를 들어, x = 42 와 같은 구문은 선언되지 않는 전역변수 를 만듭니다. 뿐만 아니라, 자바스크립트의 엄격한 경고를 만들어냅니다. 선언되지 않은 전역변수는 의도되지 않은 동작을 만들어내고는 합니다. 따라서 선언되지 않는 전역변수를 사용하면 안됩니다.

+ +

변수 할당

+ +

지정된 초기값 없이 var 혹은 let 문을 사용해서 선언된 변수는 {{jsxref("undefined")}} 값을 갖습니다.

+ +

선언되지 않은 변수에 접근을 시도하는 경우 {{jsxref("ReferenceError")}} 예외가 발생합니다.

+ +
var a;
+console.log("a 값은 " + a); // "a 값은 undefined"로 로그가 남음.
+
+console.log('b 값은 ' + b); // b 값은 undefined
+var b;
+
+console.log("c 값은 " + c); // ReferenceError 예외 던짐
+
+let x;
+console.log('x 값은 ' + x); // x 값은 undefined
+
+console.oog('y 값은 ' + y); // ReferenceError 예외 던짐
+let y;
+
+ +

undefined를 사용하여 변수값이 있는지 확인할 수 있습니다. 아래 코드에서, input 변수는 값이 할당되지 않았고 if문은 true로 평가합니다.

+ +
var input;
+if(input === undefined) {
+  doThis();
+} else {
+  doThat();
+}
+
+ +

undefined 값은 boolean 문맥(context)에서 사용될 때 false로 동작합니다. 예를 들어, 아래 코드는 myArray 요소가 undefined이므로 myFunction 함수를 실행합니다.

+ +
var myArray = [];
+if (!myArray[0]) myFunction();
+
+ +

undefined 값은 수치 문맥에서 사용될 때 NaN으로 변환됩니다.

+ +
var a;
+a + 2; // NaN으로 평가
+ +

{{jsxref("null")}} 값을 평가할 때, 수치 문맥에서는 0으로, boolean 문맥에서는 false로 동작합니다. 예를 들면,

+ +
var n = null;
+console.log(n * 32); // 콘솔에 0 으로 로그가 남음.
+
+ +

변수 범위

+ +

어떤 함수의 바깥에 변수를 선언하면, 현재 문서의 다른 코드에 해당 변수를 사용할 수 있기에 전역 변수라고 합니다. 만약 함수 내부에 변수를 선언하면, 오직 그 함수 내에서만 사용할 수 있기에 지역 변수라고 부릅니다.

+ +

ECMAScript 6 이전의 JavaScript는 block 문 범위가 없습니다. 그래서 오히려, 블록 내에 선언된 변수는 그 블록 내에 존재하는 함수(혹은 전역 범위)에 지역적입니다. 예를 들어서 아래의 코드는 5라는 로그를 남깁니다. x의 범위가 이 경우 if문 블록이 아니라 x가 선언된 함수(나 전역 문맥)이기 때문입니다.

+ +
if (true) {
+  var x = 5;
+}
+console.log(x); // 5
+
+ +

ECMAScript 6에 도입된 let 선언을 사용했을 때, 이 동작은 바뀌었습니다.

+ +
if (true) {
+  let y = 5;
+}
+console.log(y); // ReferenceError: y is not defined
+ +

변수 호이스팅

+ +

또 다른 JavaScript 변수의 특이한 점은 예외를 받지 않고도, 나중에 선언된 변수를 참조할 수 있다는 것입니다. 이 개념은 호이스팅(hoisting)으로 알려져 있습니다. 즉 JavaScript 변수가 어떤 의미에서 "끌어올려지거"나 함수나 문의 최상단으로 올려지는 것을 말합니다. 하지만, 끌어올려진 변수는 undefined 값을 반환합니다. 그래서 심지어 이 변수를 사용 혹은 참조한 후에 선언 및 초기화하더라도, 여전히 undefined를 반환합니다.

+ +
/**
+ * Example 1
+ */
+console.log(x === undefined); // logs "true"
+var x = 3;
+
+
+/**
+ * Example 2
+ */
+// undefined 값을 반환함.
+var myvar = "my value";
+
+(function() {
+  console.log(myvar); // undefined
+  var myvar = "local value";
+})();
+
+ +

위 예제는 아래 예제와 동일하게 볼 수 있습니다.

+ +
/**
+ * Example 1
+ */
+var x;
+console.log(x === undefined); // logs "true"
+x = 3;
+
+/**
+ * Example 2
+ */
+var myvar = "my value";
+
+(function() {
+  var myvar;
+  console.log(myvar); // undefined
+  myvar = "local value";
+})();
+ +

호이스팅 때문에, 함수 내의 모든 var 문은 가능한 함수 상단 근처에 두는 것이 좋습니다. 이 방법은 코드를 더욱 명확하게 만들어줍니다.

+ +

ECMAScript 2015의 let (const)는 변수를 블록의 상단으로 올리지 않습니다.
+ 변수가 선언되기 전에 블록 안에서 변수를 참조하게 되면 {{jsxref("ReferenceError")}}를 발생시키게 됩니다.
+ 변수는 블록 시작부터 선언이 처리될 때까지 'temporal dead zone'에 위치하게 됩니다.

+ +
console.log(x); // ReferenceError
+let x = 3;
+
+ +

함수 호이스팅

+ +

함수에서는 단지 함수 선언만 상단으로 끌어올려집니다. 함수 표현식은 그렇지 않습니다.

+ +
/* 함수 선언 */
+
+foo(); // "bar"
+
+function foo() {
+  console.log('bar');
+}
+
+
+/* 함수 표현식 */
+
+baz(); // TypeError: baz is not a function
+
+var baz = function() {
+  console.log('bar2');
+};
+ +

전역 변수

+ +

전역 변수는 사실 global 객체의 속성(property)입니다. 웹 페이지에서 global 객체는 {{domxref("window")}} 이므로, windows.variable 구문을 통해 전역 변수를 설정하고 접근할 수 있습니다.

+ +

그 결과, window 혹은 frame의 이름을 지정하여 한 window 혹은 frame에서 다른 window 혹은 frame에 선언된 전역 변수에 접근할 수 있습니다. 예를 들어, phoneNumber 라는 변수가 문서에 선언된 경우, iframe에서 parent.phoneNumber로 이 변수를 참조할 수 있습니다.

+ +

상수

+ +

{{jsxref("Statements/const", "const")}} 키워드로 읽기 전용 상수를 만들 수 있습니다. 상수 식별자의 구문은 변수 식별자와 같습니다. 문자, 밑줄이나 달러 기호로 시작해야 하고 문자, 숫자나 밑줄을 포함할 수 있습니다.

+ +
const PI = 3.14;
+
+ +

상수는 스크립트가 실행 중인 동안 대입을 통해 값을 바꾸거나 재선언될 수 없습니다. 값으로 초기화해야 합니다.

+ +

상수에 대한 범위 규칙은 let 블록 범위 변수와 동일합니다. 만약 const 키워드가 생략된 경우에는, 식별자는 변수를 나타내는 것으로 간주됩니다.

+ +

상수는 같은 범위에 있는 함수나 변수와 동일한 이름으로 선언할 수 없습니다. 예를 들어,

+ +
// 오류가 발생합니다
+function f() {};
+const f = 5;
+
+// 역시 오류가 발생합니다
+function f() {
+  const g = 5;
+  var g;
+
+  //statements
+}
+
+ +

그러나, 상수에 할당된 객체의 속성은 보호되지 않아서 다음의 문은 문제없이 실행됩니다.

+ +
const MY_OBJECT = {'key': 'value'};
+MY_OBJECT.key = 'otherValue';
+
+ +

또한, 배열의 내용도 보호되지 않아서 다음의 문도 문제없이 실행됩니다.

+ +
const MY_ARRAY = ['HTML','CSS'];
+MY_ARRAY.push('JAVASCRIPT');
+console.log(MY_ARRAY); //logs ['HTML','CSS','JAVASCRIPT'];
+
+ +

데이터 구조 및 형

+ +

데이터 형

+ +

최신 ECMAScript 표준은 7가지 데이터 형을 정의합니다.

+ + + +

이 데이터 형이 비교적 많지 않지만, 어플리케이션에 유용한 기능을 수행할 수 있습니다. {{jsxref("Object", "객체")}}와 {{jsxref("Function", "함수")}}는 언어의 다른 기본 요소입니다. 객체는 값을 위한 컨테이너, 함수는 어플리케이션이 수행할 수 있는 절차(procedure)로 생각할 수 있습니다.

+ +

자료형 변환

+ +

JavaScript는 동적 형지정(정형) 언어입니다. 이는 변수를 선언할 때 데이터 형을 지정할 필요가 없음을 의미합니다. 또한 데이터 형이 스크립트 실행 도중 필요에 의해 자동으로 변환됨을 뜻합니다. 그래서, 예를 들어, 다음과 같이 변수를 정의할 수 있습니다.

+ +
var answer = 42;
+ +

그리고 나중에, 동일한 변수에 문자열 값을 할당할 수도 있습니다. 아래와 같이,

+ +
answer = "Thanks for all the fish...";
+
+ +

JavaScript는 동적 형지정 언어이므로, 이 할당은 오류 메시지가 발생하지 않습니다.

+ +

숫자와 문자열 값 사이에 + 연산자를 포함한 식에서, JavaScript는 숫자 값을 문자열로 변환합니다. 예를 들어, 아래와 같은 문이 있습니다.

+ +
x = "The answer is " + 42 // "The answer is 42"
+y = 42 + " is the answer" // "42 is the answer"
+ +

다른 연산자를 포함한 식의 경우, JavaScript는 숫자 값을 문자열로 변환하지 않습니다. 예를 들면,

+ +
"37" - 7 // 30
+"37" + 7 // 377
+
+ +

문자열을 숫자로 변환하기

+ +

숫자를 나타내는 값이 문자열로 메모리에 있는 경우, 변환을 위한 메서드가 있습니다.

+ + + +

parseInt는 오직 정수만 반환하므로, 소수에서는 사용성이 떨어집니다. 게다가 parseInt를 잘 사용하기 위해서는 항상 진법(Radix) 매개변수를 포함해야 합니다. 진법 매개변수는 변환에 사용될 진법을 지정하는데 사용됩니다.

+ +

문자열을 숫자로 변환하는 대안은 +(단항 더하기) 연산자입니다.

+ +
"1.1" + "1.1" = "1.11.1"
+(+"1.1") + (+"1.1") = 2.2
+// 참고: 괄호는 명확성을 위해 추가, 필요한 것은 아닙니다.
+
+ +

리터럴

+ +

JavaScript에서 값을 나타내기 위해 리터럴을 사용합니다. 이는 말 그대로 스크립트에 부여한 고정값으로, 변수가 아닙니다. 이 절에서는 다음과 같은 형태의 리터럴을 설명합니다.

+ + + +

배열 리터럴

+ +

배열 리터럴은 0개 이상의 식(expression) 목록입니다. 각 식은 배열 요소를 나타내고 대괄호([])로 묶입니다. 배열 리터럴을 사용하여 배열을 만들 때, 그 요소로 지정된 값으로 초기화되고, 그 길이는 지정된 인수의 갯수로 설정됩니다.

+ +

아래 예제는 요소가 3개로 길이가 3인 coffees 배열을 만듭니다.

+ +
var coffees = ["French Roast", "Colombian", "Kona"];
+
+ +
+

참고: 배열 리터럴은 일종의 객체 이니셜라이저(initialiizer)입니다. Using Object Initializers 참고.

+
+ +

배열이 최상단 스크립트에서 리터럴을 사용하여 만들어진 경우, JavaScript는 배열 리터럴을 포함한 식을 평가할 때마다 배열로 해석합니다. 게다가, 함수에서 사용되는 리터럴은 함수가 호출될 때마다 생성됩니다.

+ +

배열 리터럴은 배열 객체입니다. 배열 객체에 대한 자세한 내용은 {{jsxref("Array")}}와 Indexed collections 참고.

+ +

배열 리터럴의 추가 쉼표

+ +

배열 리터럴에서 모든 요소를 지정할 필요는 없습니다. 만약 잇달아 두 개의 쉼표를 두면, 배열은 지정되지 않은 요소를 undefined로 만듭니다. 다음 예제는 fish 배열을 만듭니다.

+ +
var fish = ["Lion", , "Angel"];
+
+ +

이 배열은 값이 있는 두 요소와 빈 요소 하나를 가집니다(fish[0]은 "Lion", fish[1]undefined, fish[2]는 "Angel").

+ +

만약 요소 목록을 후행(trailing) 쉼표로 끝낸다면, 그 쉼표는 무시됩니다. 다음 예제에서, 배열의 길이는 3입니다. myList[3]은 없습니다. 목록의 다른 모든 쉼표는 새로운 요소를 나타냅니다.

+ +
+

참고: 후행 쉼표는 구버전 브라우저에서 오류를 유발할 수 있으므로 제거하는게 최선입니다.

+
+ +
var myList = ['home', , 'school', ];
+
+ +

아래 예제에서, 배열의 길이는 4이며, myList[0]myList[2]는 값이 빠졌습니다.

+ +
var myList = [ , 'home', , 'school'];
+
+ +

아래 예제에서, 배열의 길이는 4이며, myList[1]myList[3]은 값이 빠졌습니다. 마지막 쉼표는 무시됩니다.

+ +
var myList = ['home', , 'school', , ];
+
+ +

추가 쉼표의 동작을 이해하는 것은 JavaScript를 언어로서 이해하는데 중요하지만, 코드를 작성할 때는 빠진 요소의 값을 명시적으로 undefined로 선언하는 것이 코드의 명확성과 유지보수성을 높입니다.

+ +

불리언 리터럴

+ +

불리언 형은 truefalse의 리터럴 값을 가집니다.

+ +

원시 불린 값 truefalse와 Boolean 객체의 true 및 false 값을 혼동하지 마세요. Boolean 객체는 원시 불린 데이터 형을 감싸는 래퍼(wrapper)입니다. 더 많은 정보는 {{jsxref("Boolean")}}을 참고하세요.

+ +

정수 리터럴

+ +

정수는 10진, 16진, 8진 및 2진수로 표현될 수 있습니다.

+ + + +

다음은 정수 리터럴 예제입니다.

+ +
0, 117 및 -345 (10진수)
+015, 0001 및 -0o77 (8진수)
+0x1123, 0x00111 및 -0xF1A7 (16진수)
+0b11, 0b0011 및 -0b11 (2진수)
+
+ +

더 많은 정보는 Lexical grammar reference의 Numeric literals를 참고하세요.

+ +

부동 소수점 리터럴

+ +

부동 소수점 리터럴은 아래와 같은 부분으로 이루어집니다.

+ + + +

지수부는 "e"나 "E" 다음에 오며 부호("+"나 "-")가 달릴 수 있는 정수입니다. 부동 소수점 리터럴은 적어도 숫자 하나와 소수점 혹은 "e"(나 "E")가 있어야 합니다.

+ +

더 간결하게 설명하면, 구문은 다음과 같습니다.

+ +
[(+|-)][digits][.digits][(E|e)[(+|-)]digits]
+
+ +

예를 들면,

+ +
3.1415926
+-.123456789
+-3.1E+12
+.1e-23
+
+ +

객체 리터럴

+ +

객체 리터럴은 중괄호({})로 묶인 0개 이상인 객체의 속성명과 관련 값 쌍 목록입니다. 문의 시작에 객체 리터럴을 사용해서는 안됩니다. 이는 {가 블록의 시작으로 해석되기 때문에 오류를 이끌거나 의도한 대로 동작하지 않습니다.

+ +

아래는 객체 리터럴의 예제입니다. car 객체의 첫째 요소는 myCar 속성을 정의하고 문자열 "Saturn"을 할당합니다. 반면 둘째 요소인 getCar 속성은 function (carTypes("Honda"))을 호출한 결과가 즉시 할당됩니다. 셋째 요소 special 속성은 기존 변수 sales를 사용합니다.

+ +
var sales = "Toyota";
+
+function carTypes(name) {
+  if (name === "Honda") {
+    return name;
+  } else {
+
+  }
+    return "Sorry, we don't sell " + name + ".";
+}
+
+var car = { myCar: "Saturn", getCar: carTypes("Honda"), special: sales };
+
+console.log(car.myCar);   // Saturn
+console.log(car.getCar);  // Honda
+console.log(car.special); // Toyota
+
+ +

게다가, 속성명으로 숫자나 문자열 리터럴을 사용하거나 또다른 객체 리터럴 내부에 객체를 중첩할 수도 있습니다. 아래 예제는 이 옵션을 사용합니다.

+ +
var car = { manyCars: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };
+
+console.log(car.manyCars.b); // Jeep
+console.log(car[7]); // Mazda
+
+ +

객체 속성명은 빈 문자열 포함 어떤 문자열도 될 수 있습니다. 속성명이 유효한 JavaScript {{Glossary("식별자")}}나 숫자가 아닌 경우, 따옴표로 묶여야 합니다. 또한 유효한 식별자가 아닌 속성명은 점(.) 속성으로 접근할 수 없습니다. 대신 배열 같은 표기법("[]")으로 접근하고 값을 설정할 수 있습니다.

+ +
var unusualPropertyNames = {
+  "": "An empty string",
+  "!": "Bang!"
+}
+console.log(unusualPropertyNames."");   // SyntaxError: Unexpected string
+console.log(unusualPropertyNames[""]);  // An empty string
+console.log(unusualPropertyNames.!);    // SyntaxError: Unexpected token !
+console.log(unusualPropertyNames["!"]); // Bang!
+
+ +

향상된 객체 리터럴

+ +

ES2015에서, 객체 리터럴은 구성에서 프로토타입 설정, foo: foo 할당을 위한 단축 표기, 메서드 정의, super 클래스 호출 및 식으로 동적인 속성명 계산을 지원하기 위해 확장됐습니다. 그에 따라 객체 리터럴 및 클래스 선언이 함께 더 가까워지고, 객체 기반 설계는 같은 일부 편의기능으로 득을 볼 수 있습니다.

+ +
var obj = {
+    // __proto__
+    __proto__: theProtoObj,
+    // ‘handler: handler’의 단축 표기
+    handler,
+    // Methods
+    toString() {
+     // Super calls
+     return "d " + super.toString();
+    },
+    // Computed (dynamic) property names
+    [ 'prop_' + (() => 42)() ]: 42
+};
+ +

아래를 참고하세요.

+ +
var foo = {a: "alpha", 2: "two"};
+console.log(foo.a);    // alpha
+console.log(foo[2]);   // two
+//console.log(foo.2);  // Error: missing ) after argument list
+//console.log(foo[a]); // Error: a is not defined
+console.log(foo["a"]); // alpha
+console.log(foo["2"]); // two
+
+ +

정규식 리터럴

+ +

정규식 리터럴은 (정규식 상세) 슬래시 사이에 감싸인 패턴입니다. 다음은 정규식 리터럴 예제입니다.

+ +
var re = /ab+c/;
+ +

문자열 리터럴

+ +

문자열 리터럴은 큰 따옴표(") 혹은 작은 따옴표(')로 묶인 0개 이상의 문자입니다. 문자열은 같은 형 따옴표, 즉 큰 따옴표 쌍이나 작은 따옴표 쌍으로 구분되어야 합니다. 아래는 문자열 리터럴의 예제입니다.

+ +
"foo"
+'bar'
+"1234"
+"one line \n another line"
+"John's cat"
+
+ +

문자열 리터럴 값은 문자열 객체의 모든 메서드를 호출할 수 있습니다. JavaScript는 자동으로 문자열 리터럴을 임시 문자열 객체로 변환, 메서드를 호출하고 나서 임시 문자열 객체를 폐기합니다. 또한 문자열 리터럴에서도 String.length 속성을 사용할 수 있습니다.

+ +
console.log("John's cat".length)
+// 공백을 포함한 문자열 내 심볼 갯수가 출력됩니다.
+// 여기서는, 10.
+
+ +

ES2015에서는, 템플릿 리터럴도 사용할 수 있습니다. 템플릿 문자열은 문자열 구성을 위한 달콤한 구문을 제공합니다. 이는 Perl, Python 등에 있는 문자열 삽입(interpolation) 기능과 비슷합니다. 마음대로, 문자열 구성을 사용자 정의하고 인젝션 공격을 피하거나 문자열 콘텐츠로 더 고레벨 데이터 구조를 구성하기 위한 태그가 추가될 수 있습니다.

+ +
// 기본적인 문자열 리터럴 생성
+`In JavaScript '\n' is a line-feed.`
+
+// 여러 줄 문자열
+`In JavaScript this is
+ not legal.`
+
+// 문자열 삽입
+var name = "Bob", time = "today";
+`Hello ${name}, how are you ${time}?`
+
+// Construct an HTTP request prefix is used to interpret the replacements and construction
+POST`http://foo.org/bar?a=${a}&b=${b}
+     Content-Type: application/json
+     X-Credentials: ${credentials}
+     { "foo": ${foo},
+       "bar": ${bar}}`(myOnReadyStateChangeHandler);
+ +

꼭 문자열 객체를 사용할 필요가 없는 경우 문자열 리터럴을 사용해야 합니다. 문자열 객체에 대해 자세한 사항은 {{jsxref("String")}}을 참고하세요.

+ +

문자열에서 특수 문자 사용

+ +

보통 문자에 더해서, 문자열에 아래 예제와 같이 특수 문자도 포함할 수 있습니다.

+ +
"one line \n another line"
+
+ +

다음 표는 JavaScript 문자열에 사용할 수 있는 특수 문자 목록입니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
표: JavaScript 특수 문자
문자
\0Null Byte
\bBackspace
\fForm feed
\nNew line
\rCarriage return
\tTab
\vVertical tab
\'Apostrophe 혹은 작은 따옴표
\"큰 따옴표
\\백슬래시
\XXXLatin-1 인코딩 문자는 0 - 377 사이 8진수 3자리까지 지정될 수 있습니다. 예를 들어, \251은 copyright 심볼을 표현하는 8진수 시퀀스입니다.
\xXXLatin-1 인코딩 문자는 00 - FF 사이의 16진수 2자리로 지정될 수 있습니다. 예를 들어, \xA9는 copyright 심볼을 표현하는 16진수 시퀀스입니다.
\uXXXX유니코드 문자는 16진수 4자리로 지정될 수 있습니다. 예를 들어, \u00A9는 copyright 심볼을 표현하는 유니코드 열입니다. Unicode escape sequences를 참고하세요.
\u{XXXXX}유니코드 코드 포인트 이스케이프. 예를 들어, \u{2F804}는 간단한 유니코드 이스케이프 \uD87E\uDC04와 같습니다.
+ +

문자 이스케이프

+ +

표에 없는 문자의 경우 전행 백슬래시는 무시되지만, 이 용법은 더 이상 사용되지 않으며, 사용을 피해야 합니다.

+ +

전행 백슬래시와 함께 문자열 안에 따옴표를 사용할 수 있습니다. 이것을 따옴표 이스케이프라고 합니다. 예를 들어,

+ +
var quote = "He read \"The Cremation of Sam McGee\" by R.W. Service.";
+console.log(quote);
+
+ +

이 코드의 결과는,

+ +
He read "The Cremation of Sam McGee" by R.W. Service.
+
+ +

백슬래시를 문자열 내에 포함시키기 위해서는, 백슬래시 문자를 이스케이프 해야 합니다. 예를 들어, 파일 경로 c:\temp를 문자열에 할당하기 위해서는 아래와 같이 사용합니다.

+ +
var home = "c:\\temp";
+
+ +

또한 줄바꿈 역시 전행 백슬래시로 이스케이프할 수 있습니다. 백슬래시와 줄바꿈 모두 문자열 값에서는 사라집니다.

+ +
var str = "this string \
+is broken \
+across multiple\
+lines."
+console.log(str);   // this string is broken across multiplelines.
+
+ +

JavaScript에는 "heredoc" 구문은 없지만, 줄바꿈 이스케이프와 각 줄 끝 이스케이프된 줄바꿈을 추가하여 흉내낼 수 있습니다.

+ +
var poem =
+"Roses are red,\n\
+Violets are blue.\n\
+I'm schizophrenic,\n\
+And so am I."
+
+ +

ECMAScript 2015에서는 템플릿 리터럴(template literals)이라는 새로운 리터럴이 소개되었습니다. 이 것은 다중 문자열을 포함한 많은 새로운 기능을 가지고 있습니다!

+ +
var poem =
+`Roses are red,
+Violets are blue.
+Sugar is sweet,
+and so is foo.`
+
+ +

추가 정보

+ +

이 장은 선언과 형에 대한 기본 구문에 초점을 맞춥니다. JavaScript 언어 구조에 대해 더 많이 배우려면, 다음 장을 참고하세요.

+ + + +

다음 장에서는, 흐름 제어 구조와 오류 처리를 살핍니다.

+ +

{{PreviousNext("Web/JavaScript/Guide/소개", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}

diff --git a/files/ko/web/javascript/guide/working_with_objects/index.html b/files/ko/web/javascript/guide/working_with_objects/index.html new file mode 100644 index 0000000000..192e22604c --- /dev/null +++ b/files/ko/web/javascript/guide/working_with_objects/index.html @@ -0,0 +1,500 @@ +--- +title: Working with objects +slug: Web/JavaScript/Guide/Working_with_Objects +translation_of: Web/JavaScript/Guide/Working_with_Objects +--- +

자바스크립트는 간단한 객체기반 패러다임 상에서 만들어졌다. 객체는 프로퍼티의 모음이며, 프로퍼티는 "이름"(name 또는 key)과 "값"(value)의 연결로 이루어진다 . 프로퍼티의 값으로 함수가 될 수 있는데, 이런 프로퍼티는 메소드라고 불린다. 브라우저 안에 미리 정의 된 객체뿐 아니라 사용자들이 직접 자신만의 객체를 정의할 수도 있다.

+ +

이 절에서는 객체, 프로퍼티, 함수, 메소드가 어떻게 사용되는지, 그리고 사용자를 위한 새로운 객체를 생성하는 방법을 설명한다

+ +

개요

+ +

자바스크립트에서의 객체는 다른 프로그래밍 언어에서와 비슷하게 현실 세계에서의 사물(objects)과 비교해 볼 수 있다. 자바스크립트에서의 객체의 개념은 실세계상에서의 인식 가능한 사물로 이해할 수 있다.

+ +

객체는 단독으로 존재 가능한 개체(entity)이며, 프로퍼티(property)과 타입(type)을 가진다. 예를 들어 컵과 비교를 해 본다면 컵은 사물 객체인데 색깔, 모양, 무게, 재료 등의 속성(프로퍼티)을 가지고 있다. 비슷하게 자바스크립트의 객체는 그 특징을 결정짓는 여러 프로퍼티를 가진다.

+ +

객체와 프로퍼티

+ +

자바스크립트의 객체에는 그와 연관된 프로퍼티가 있다. 프로퍼티는 객체에 붙은 변수(variable)라고 설명할 수 있겠다. 객체의 프로퍼티는 일반 자바스크립의 변수와 기본적으로 똑같은데, 다만 객체에 속해있다는 차이만 있을 뿐이다. 객체의 프로퍼티들이 객체의 특징을 규정한다. 프로퍼티에 접근할 때는 도트(점) 표기법을 사용한다.

+ +
objectName.propertyName
+
+ +

자바스크립트의 모든 변수가 그렇듯이, 객체의 이름과 프로퍼티 이름은 모두 대소문자를 구별한다. 프로퍼티를 새로 정의하려면 그냥 이름과 값을 추가하면 된다. 예를 들어 myCar 라는 이름의 객체를 생성하고, 거기에 make, model, and year 라는 프로퍼티들을 추가해보자:

+ +
var myCar = new Object();
+myCar.make = "Ford";
+myCar.model = "Mustang";
+myCar.year = 1969;
+
+ +

대괄호 표기법을 사용하여 객체의 프로퍼티에 접근할 수 있다. 객체는 연관배열(associative arrays)이라고도 불리는데, 각 프로퍼티는 하나의 문자열 이름과 연관되어(associated) 이것을 통해 접근할 수 있기 때문이다. 예를 들면 myCar 객체의 프로퍼티에 다음과 같이 접근할 수 있다.

+ +
myCar["make"] = "Ford";
+myCar["model"] = "Mustang";
+myCar["year"] = 1969;
+
+ +

객체의 프로퍼티 이름은 유효한 자바스크립트 문자열이거나 문자열로 변환이 가능한 것이면 어떤 것이든 가능하며, 심지어 빈 문자열도 된다. 하지만 자바스크립트 식별자(identifier)로 적합하지 않으면 (예 : 하이픈, 빈칸을 포함하거나 숫자로 시작하는 이름), 대괄호를 이용한 표기법으로만 접근이 가능하다. 이 표기법은 프로퍼티 이름이 사전에 미리 결정되지 않고 런타임 시점에 결정되는 경우에 특히 유용하다. 아래의 예를 보자.

+ +
var myObj = new Object(),
+    str = "myString",
+    rand = Math.random(),
+    obj = new Object(); // 변수 4개를 콤마를 사용하여 한번에 생성하고 할당.
+
+myObj.type              = "Dot syntax";
+myObj["date created"]   = "String with space";
+myObj[str]              = "String value";
+myObj[rand]             = "Random Number";
+myObj[obj]              = "Object";
+myObj[""]               = "Even an empty string";
+
+console.log(myObj);
+
+ +

변수에 저장된 문자열을 이용해서도 프로퍼티에 접근할 수 있다.

+ +
+
var propertyName = "make";
+myCar[propertyName] = "Ford";
+
+propertyName = "model";
+myCar[propertyName] = "Mustang";
+
+
+ +

대괄호 표기법을 for...in 과 함께 사용하면 객체의 열거가능한 프로퍼티를 나열할 수 있다. 이것이 어떻게 작동하는지 알기 위해 아래의 함수를 보자. 이 함수는 객체와 객체 이름을 함수의 인자로 전달받아서 객체의 프로퍼티들을 출력해 준다.

+ +
function showProps(obj, objName) {
+  var result = "";
+  for (var i in obj) {
+    if (obj.hasOwnProperty(i)) {
+        result += objName + "." + i + " = " + obj[i] + "\n";
+    }
+  }
+  return result;
+}
+
+ +

showProps(myCar, "myCar") 함수를 호출하면 다음과 같은 문자열을 반환한다.

+ +
myCar.make = Ford
+myCar.model = Mustang
+myCar.year = 1969
+ +

모든 것이 객체

+ +

자바스크립트 세상에서는 거의 모든 것들이 객체이다. null 과 undefined 를 제외한 모든 원시 타입도 객체로 취급된다. 이러한 원시 타입들에도 프로퍼티가 추가될 수 있고 (설명 필요: assigned properties of some types are not persistent), 모두 객체로서의 특징을 갖는다.

+ +

객체의 프로퍼티 나열하기

+ +

ECMAScript 5 를 기준으로 객체의 프로퍼티를 나열/순회하는 방법이 세 가지 있다.

+ + + +

ECMAScript 5 이전 버전에서는 객체의 모든 프로퍼티를 나열하는 자체적인 방법이 제공되지 않았다. 하지만 아래 함수를 이용하면 가능하다.

+ +
function listAllProperties(o){
+	var objectToInspect;
+	var result = [];
+
+	for(objectToInspect = o; objectToInspect !== null; objectToInspect = Object.getPrototypeOf(objectToInspect)){
+		result = result.concat(Object.getOwnPropertyNames(objectToInspect));
+	}
+
+	return result;
+}
+
+ +

이 트릭은 객체의 "숨겨진" 프로퍼티를 알아내는 데 유용하다. (숨겨진 프로퍼티란 프로토타입 체인 상의 프로퍼티 중 객체를 통해 접근이 불가능한 것들을 말하는데 동일 이름의 다른 프로퍼티가 프로퍼티 체인 상에서 먼저 존재하는 경우에 발생한다).  만약 접근 가능한 프로퍼티만 나열하고 싶다면 배열에서 중복되는 프로퍼티들을 제거하면 된다.

+ +

객체 생성하기

+ +

자바스크립트에는 미리 정의된 객체가 몇 개 존재한다. 사용자는 여기에 추가적으로 자신의 객체를 생성할 수 있다. 자바스크립트 1.2 부터는 객체 이니셜라이저(initializer) 를 이용하여 객체를 생성할 수 있다. 또 다른 방법으로는 먼저 생성자 함수를 정의한 후 이 함수와 new 연산자를 이용하여 인스턴스를 만들수 있다.

+ +

객체 이니셜라이저

+ +

생성자 함수를 사용하는 방법 대신, 객체 이니셜라이저를 사용하여 객체를 생성할 수 있다. 이 방식은 때때로 "리터럴 표기에 의한 객체 생성"(creating objects with literal notation) 이라고도 불린다. 객체 이니셜라이저라는 단어는 C++ 에서도 비슷한 의미로 사용된다.

+ +

객체 이니셜라이저를 이용한 객체 생성의 문법은 다음과 같다.

+ +
var obj = { property_1:   value_1,   // property_# may be an identifier...
+            2:            value_2,   // or a number...
+            // ...,
+            "property n": value_n }; // or a string 
+ +

obj는 새로 만들어질 객체 이름이고, property_i는 식별자 (이름, 숫자, 또는 스트링 리터럴), value_i 는 수식인데 이 값이 property_i 에 할당 된다. obj 변수에 할당 (assignment =) 하는 것은 선택 사항이다; 이 생성된 객체를 다른 곳에서 참조할 필요가 없다면 변수에 할당하지 않아도 된다. (만약 이 생성된 객체를 변수를 사용하지 않고 구문 안에서 바로 사용하려면 블럭 구문과 혼돈되지 않도록 리터널을 괄호로 감싸줄 필요가 있다.)

+ +

객체 이니셜라이저는 수식이고, 각각의 이니셜라이저가 포함된 구문이 실행될 때 마다 이니셜라이저 수식에 의해 새로운 객체가 하나씩 생성이 된다. 똑같은 이니셜라이저에 의해 생성된 객체라도 서로 별개이며 비교 결과는 동일하지 않음 (not equal) 이 된다. 객체는 마치 new Object() 호출이 실행된 것 처럼 생성이 된다; 즉, 객체 이니셜라이저 수식에 의해 만들어진 객체들은 Object의 인스턴스들이 된다.

+ +

다음 문장은 수식cond가 참일 경우 객체를 만들어서 변수 x 에 할당한다:

+ +
if (cond) var x = {hi: "there"};
+
+ +

다음 예제는 myHonda을 생성하고 세개의 속성을 추가한다. engine 속성 역시 자신의 속성들을 가지고 있는 객체이다.

+ +
var myHonda = {color: "red", wheels: 4, engine: {cylinders: 4, size: 2.2}};
+
+ +

객체 이니셜라이저를 이용하여 배열을 만들 수 있다. array literals 를 참조하기 바란다.

+ +

JavaScript 1.1 과 그 이전 버전에서는, 객체 이니셜라이저를 사용할 수 없었다. 항상 생성자 함수를 쓰거나 생성 목적으로 제공되는 별도 함수를 사용했어야 했다. Using a constructor function 참고.

+ +

생성자 함수 사용하기

+ +

다른 방법으로는 다음 두 단계에 따라 객체를 생성할 수 있다:

+ +
    +
  1. 생성자 함수를 작성하여 객체 타입을 정의한다. 객체 타입 이름의 첫 글자는 반드시 대문자를 사용하는 좋은 관례가 있으므로 따르기를 권장한다.
  2. +
  3. new를 이용하여 객체의 인스턴스를 생성한다.
  4. +
+ +

객체의 타입을 정의하려면 타입의 이름, 속성(프로퍼티), 메소드 등을 기술하는 함수를 하나 만들어야 한다. 예를 들면, 여러분이 자동차를 위한 객체 타입을 만들기 원한다면, 이 객체의 타입의 이름은 car이고, 이 타입은 제조사, 모델, 생산연도를 위한 속성을 포함하길 원할 것이다. 아마도 다음과 같은 함수를 작성하게 될 것이다:

+ +
function Car(make, model, year) {
+  this.make = make;
+  this.model = model;
+  this.year = year;
+}
+
+ +

함수 인자로 전달 받은 값을 객체의 속성에 할당하기 위해서 this를 사용 한 것에 주목하기 바란다.

+ +

이제 다음과 같이 하여 mycar라는 이름의 객체를 생성할 수 있다:

+ +
var mycar = new Car("Eagle", "Talon TSi", 1993);
+
+ +

이 문장은 mycar를 만들고 특정 값들을 속성으로 할당하고 있다. 이렇게 하면 mycar.make의 값은 문자열 "Eagle" 이 되고, mycar.year는 정수 1993 이 된다.

+ +

new를 이용하면 어떤 갯수의 car 객체도 만들 수 있다. 예를 들면 다음과 같다.

+ +
var kenscar = new Car("Nissan", "300ZX", 1992);
+var vpgscar = new Car("Mazda", "Miata", 1990);
+
+ +

객체는 또 다른 객체를 속성으로 가질 수 있다. 예를 들어 여러분이 person 이라는 객체를 다음과 같이 정의를 했고:

+ +
function Person(name, age, sex) {
+  this.name = name;
+  this.age = age;
+  this.sex = sex;
+}
+
+ +

그리고 두 개의 새 person 객체의 인스턴스를 만들었다고 하면:

+ +
var rand = new Person("Rand McKinnon", 33, "M");
+var ken = new Person("Ken Jones", 39, "M");
+
+ +

car의 정의에 person 객체의 값을 갖는 owner 속성을 추가하도록 수정할 수 있다:

+ +
function Car(make, model, year, owner) {
+  this.make = make;
+  this.model = model;
+  this.year = year;
+  this.owner = owner;
+}
+
+ +

수정된 새 객체의 인스턴스를 만들려면 다음과 같이 하면 된다:

+ +
var car1 = new Car("Eagle", "Talon TSi", 1993, rand);
+var car2 = new Car("Nissan", "300ZX", 1992, ken);
+
+ +

위 문장은 문자열 리터럴이나 정수를 넘기는 대신 객체 randken을 owners를 위한 인자로 전달하고 있다. car2의 소유자 이름을 찾고 싶다면 다음과 같은 속성을 사용할 수 있다.:

+ +
car2.owner.name
+
+ +

이미 정의 된 객체에도 새로운 속성을 추가할 수 있다.

+ +
car1.color = "black";
+
+ +

위 문장은 속성 color를 car1 에 추가하고, 그 값으로는 "black"을 지정하고 있다. 그러나 이것은 다른 객체들에는 영향을 주지 않는다. 새 속성을 해당 타입의 모든 객체들에 다 추가하고 싶다면, 이 속성을 car 객체 타입의 정의에 추가해야 한다.

+ +

Object.create 메서드 사용하기

+ +

객체는 Object.create 메서드를 이용해서 생성될 수 있다. 이 메서드는 사용할 프로토타입 객체를 사용자가 직접 선택할 수 있기 때문에 상당히 유용하다. (객체 생성시 생성자 함수가 없어도 가능하다). 이 메서드에 대한 더 자세한 정보는 {{jsxref("Object.create()")}} 를 참고하도록 하자.

+ +
// Animal properties and method encapsulation
+var Animal = {
+  type: "Invertebrates", // Default value of properties
+  displayType : function(){  // Method which will display type of Animal
+    console.log(this.type);
+  }
+}
+
+// Create new animal type called animal1
+var animal1 = Object.create(Animal);
+animal1.displayType(); // Output:Invertebrates
+
+// Create new animal type called Fishes
+var fish = Object.create(Animal);
+fish.type = "Fishes";
+fish.displayType(); // Output:Fishes
+ +

상속

+ +

JavaScript 에서의 모든 객체들은 최소한 하나의 다른 객체로부터 상속을 받는다. 상속을 제공하는 객체를 프로토타입이라고 부르며, 상속되는 속성들은 prototype 이라는 생성자 객체에서 찾을 수 있다.

+ +

객체 프로퍼티의 인덱싱

+ +

JavaScript 1.0에서는 객체의 속성을 참조할 때 속성 이름을 이용하거나 또는 숫자 인덱스를 이용할 수 있었다. 하지만 JavaScript 1.1과 그 이후 부터는 처음에 프로퍼티를 이름으로 정의하면 항상 이름으로만 참조를 할 수 있고, 처음에 인덱스를 이용하여 정의하면 인덱스를 이용해서만 참조할 수 있다.

+ +

이 제약 사항은 생성자 함수를 이용하여 객체와 프로퍼티를 생성할 때 (앞에서 Car 객체 타입의 예)에도 동일하게 적용되고, 개개의 속성을 명시적으로 지정할 때 (예: myCar.color = "red")에도 마찬가지이다. 만약 처음에 객체 속성을 정의할 때 myCar[5] = "25 mpg" 처럼 인덱스 방식을 사용하면, 그 이후에도 계속 myCar[5] 방식으로만 참조할 수 있다.

+ +

forms 배열과 같이 HTML 로부터 얻어지는 객체들에는 이 규칙이 적용되지 않는다. 숫자를 이용하거나 (이 객체가 문서 상에 존재하는 순서에 따라) 또는 태그의 attribute 이름으로 참조가 가능하다. 예를 들면 HTML 문서에서 두 번째 <FORM> 태그가 "myForm" 이라는 값의 NAME attribute 를 가지고 있다면, 이 form을 document.forms[1] 또는 document.forms["myForm"] 또는 document.myForm 와 같이 접근할 수 있다.

+ +

객체의 프로퍼티 정의

+ +

prototype 프로퍼티를 사용하여 미리 정의된 객체 타입에 속성을 추가할 수 있다. 이렇게 정의된 속성은 해당 객체 타입의 한 인스턴스에만 적용되는 것이 아니라 해당 객체 타입의 모든 인스턴스가 갖게 된다. 다음 코드에서는 car 타입의 객체 전체에 color 프로퍼티를 추가한 후, car1 인스턴스의 color 프로퍼티에 값을 할당하는 것을 보여준다.

+ +
Car.prototype.color = null;
+car1.color = "black";
+
+ +

더 많은 정보는 JavaScript Reference에서 Function 객체의 prototype 속성을 참조

+ +

메소드 정의

+ +

메소드는 한 객체와 연관된(associated) 함수이며, 간단하게 말해 객체의 프로퍼티 중에서 함수인 것을 메소드라고 한다. 메소드를 정의하는 방식은 일반 함수를 정의하는 것과 동일하고, 다만 어떤 객체의 프로퍼티로 할당되어야 한다는 점이 차이가 난다. 자세한 것은 method definitions를 참조하자. 다음은 메소드 정의의 한 예이다.

+ +
objectName.methodname = function_name;
+
+var myObj = {
+  myMethod: function(params) {
+    // ...do something
+  }
+};
+
+ +

첫번째 줄은 이미 존재하는 objectName이라는 객체에 methodname이라는 이름의 메소드를 추가하는 것이다. function_name 은 메소드로 사용될 함수의 이름이다. 두번째 줄부터는 객체를 정의할 때 메소드를 같이 정의하는 예이다.

+ +

그러고 나면 다음과 같이 해당 객체의 문맥(context)에서 메소드를 호출할 수 있다.

+ +
object.methodname(params);
+
+ +

객체 생성자 함수에 메소드 정의를 포함시킴으로써 해당 객체 타입의 메소드를 정의할 수 있다. 한 예로 이전에 정의한 car 객체의 프로퍼티를 형식에 맞춰 출력하는 함수를 정의할 수 있는데, 다음과 같다.

+ +
function displayCar() {
+  var result = "A Beautiful " + this.year + " " + this.make
+    + " " + this.model;
+  pretty_print(result);
+}
+
+ +

위에서 pretty_print는 수평 규칙과 문자열을 나타내 주는 함수이다. 여기서 사용한 this는 해당 메소드가 속한 객체를 가리킨다는 점을 기억하자.

+ +

아래와 같은 코드를 car객체의 정의에 추가함으로써 해당 함수를 car객체의 메소드로 만들 수 있다.

+ +
this.displayCar = displayCar;
+
+ +

따라서 car객체의 전체 정의는 아래와 같이 됩니다.

+ +
function Car(make, model, year, owner) {
+  this.make = make;
+  this.model = model;
+  this.year = year;
+  this.owner = owner;
+  this.displayCar = displayCar;
+}
+
+ +

그리고 각각의 객체(인스턴스)를 가지고 displayCar메서드를 아래와 같이 호출 할 수 있습니다:

+ +
car1.displayCar();
+car2.displayCar();
+
+ +

객체 참조를 위해 this 를 사용하기

+ +

자바스크립트는 특별한 키워드를 가지고 잇습니다. 바로 this라는 키워드이다. 메서드 내부에서 this 키워드를 사용하게 되면 해당 메서드를 포함한 객체를 가리키게 된다. 예를 들어 특정 객체의 속성값의 상한과 하한 값의 범위에 있는지를 확인하는 validate라는 함수를 아래와 같이 작성한다고 했을 때, 

+ +
function validate(obj, lowval, hival) {
+  if ((obj.value < lowval) || (obj.value > hival))
+    alert("Invalid Value!");
+}
+
+ +

validate메서드를 각각의 form 요소들의 onchange 이벤트 핸들러에서 호출할 수 있다. 그 때, 다음 예제처럼 this 키워드를 사용해서 해당 form요소를 인자로 넘길 수 있다. 

+ +
<input type="text" name="age" size="3"
+  onChange="validate(this, 18, 99)">
+
+ +

일반적으로 this는 메서드를 호출하는 객체를 지칭합니다. 

+ +

 myFormform속성과 함께 사용할때, this키워드는 현재 객체의 부모 form을 지칭한다. 다음의 예제에서, myForm form은 텍스트 객체와 버튼 객체를 가지고 있다. 사용자가 해당 버튼을 클릭했을때, myForm form안에 있는 텍스트 객체의 값을 myForm form의 이름으로 설정한다. 해당 버튼의 onclick 이벤트 처리자는 부모 form인 myForm을 지칭하기 위해 this.form를 사용한다. 

+ +
<form name="myForm">
+<p><label>Form name:<input type="text" name="text1" value="Beluga"></label>
+<p><input name="button1" type="button" value="Show Form Name"
+     onclick="this.form.text1.value = this.form.name">
+</p>
+</form>
+ +

getters 와 setters 정의

+ +

getter 메서드는 특정 속성의 값을 받아 오기 위한 메서드 입니다. setter메서드는 특정 속성의 값을 설정하기 위한 메서드 입니다. 새로운 속성을 추가 하기 위해 getter와 setter 메서드들을 미리 정의된 객체 혹은 사용자 정의 객체에 정의 하 수 있습니다.  getter와 setter메서드들을 정의 하기 위한 문법은 객체 구문 문법을 사용합니다.

+ +

자바스크립트 1.8.1버전부터, 객체와 배열 초기화에서 속성들을 설정하고자 할 경우 setter메서드들은 더이상 사용이 불가합니다.

+ +

다음의 JS 쉘은 getter와 setter메서드들이 사용자 정의객체인 o에서 어떻게 작동하는지를 보여 줍니다. JS쉘은 개발자가 배치 모드 혹은 대화형 모드에서 자바스크립트 코드를 테스트하기위한 하나의 어플리케이션입니다. 

+ +
js> var o = {a: 7, get b() {return this.a + 1;}, set c(x) {this.a = x / 2}};
+[object Object]
+js> o.a;
+7
+js> o.b;
+8
+js> o.c = 50;
+js> o.a;
+25
+
+ +

o 객체의 속성이 다음과 같을 때,

+ + + +

[gs]et 속성명()  문법이 실제 사용되는 메서드명이라고 생각이 될지라도, "[gs]et 속성명()" 문법(__define[GS]etter__와는 반대로)을 사용한 객체 구문 문법으로 정의된 getter와 setter메서드들의 이름들은 실제 getter 메서드들의 이름이 아니라는 점에 유의 하세요.  "[gs]et 속성명()" 문법을 사용하여 getter, setter메서드내의 함수명을 작성하기 위해서는, Object.defineProperty (혹은 Object.prototype.__defineGetter__ 레거시 콜백)을 사용하여 프로그램적으로 분명한 이름의 함수명을 사용하세요. 

+ +

아래의 자바스크립트 쉡은 이미 정의된 Date 클래스의 모든 인스턴스들에 년도 속성을 추가 하기 위해 getter와 setter 메서드들이 Date 프로토타입을 확장하는 방법을 보여 줍니다. 

+ +

아래의 구문들은 년도 속성 추가를 위한 getter와 setter메서드를 정의합니다:

+ +
js> var d = Date.prototype;
+js> Object.defineProperty(d, "year", {
+    get: function() {return this.getFullYear() },
+    set: function(y) { this.setFullYear(y) }
+});
+
+ +

아래의 구문들은 Date객체에서 getter와 setter메서드를 사용하는 법을 보여 줍니다:

+ +
js> var now = new Date;
+js> print(now.year);
+2000
+js> now.year = 2001;
+987617605170
+js> print(now);
+Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
+
+
+ +

원칙적으로, getter와 setter는 둘 중 하나가 될 수 있다.

+ + + +

object initializers를 사용해서 getter와 setter메서드들을 정의할 경우, getter메서드는 get, setter메서드는 set이라는 접두사만 추가하면 됩니다. 물론 getter메서드는 인자를 받지 않는 반면, setter 메서드는 정확히 하나의 인자(설정할 새로운 값)만을 받습니다. 

+ +
var o = {
+  a: 7,
+  get b() { return this.a + 1; },
+  set c(x) { this.a = x / 2; }
+};
+
+ +

Object.defineProperties 메서드를 사용하면 객체 생성이후라도 언제든지 getter and setter메서드들을 객체에 추가할 수 있습니다. Object.defineProperties 메서드의 첫번째 인자는 getter and setter메서드들을 추가할 객체이고, 두번째 인자는 getter and setter메서드들의 이름과 getter and setter메서드들의 정의를 가지고 있는 객체가 되어야 합니다. 이전 예제와 동일하게 사용된 getter and setter메서드들을 정의하고 있는 예제는 아래와 같습니다:

+ +
var o = { a:0 }
+
+Object.defineProperties(o, {
+    "b": { get: function () { return this.a + 1; } },
+    "c": { set: function (x) { this.a = x / 2; } }
+});
+
+o.c = 10 // Runs the setter, which assigns 10 / 2 (5) to the 'a' property
+console.log(o.b) // Runs the getter, which yields a + 1 or 6
+
+ +

당신의 프로그래밍 스타일과 현재 진행 중인 작업에 따라 getter and setter메서드들을 정의할 수 있는 두가지 양식 중 하나를 선택하여 사용할 수 있습니다. prototype을 정의 할때 object initializer를 사용했다면 앞으로도 대부분 첫번째 양식을 선택 하여 작성을 할 것입니다. 이 양식이 보다 간결하고 자연스럽기 때문입니다. 하지만 prototype 혹은 특정 객체를 작성하지 않고서 나중에 getter and setter 메서드를 추가하고자 한다면 두번째 양식만이 가능한 선택입니다.  두번째 양식은 아마도 자바스크립트의 동적 속성을 가장 잘 나타내고 있습니다. 하지만 코드 작성과 읽고 이해하는 부분에 어려움이 있습니다. 

+ +
+

Firefox 3.0 이전 버전의 경우, getter and setter 메서드들은 DOM 요소들에는 지원되지 않습니다. 이전 버전의 Firefox에서는 아무런 에러 없이 작동하지 않을 것입니다. 이것에 대한 예외가 필요하다면, HTMLElement의 prototype(HTMLElement.prototype.__define[SG]etter__)을 변경하고 예외를 던지는 것이 하나의 방법입니다.

+ +

Firefox 3.0 버전에서는 이미 정의된 속서에 대해 getter or setter를 정의 할 경우 예외가 발생됩니다. 이전 버전의 Firefox에서는 아니지만 해당 속성을 반드시 사전에 제거해야만 합니다. 

+
+ +

추가로 볼 것들 

+ + + +

프로퍼티의 삭제

+ +

상속 받지 않은 속성은 delete 연산자를 이용하여 제거 할 수 있다. 다음 코드는 어떻게 속성을 제거하는지 보여준다.

+ +
// 새 객체 myobj를 두 개의 속성 a, b 와 함께 생성
+var myobj = new Object;
+myobj.a = 5;
+myobj.b = 12;
+
+// 속성을 삭제. myobj 에는 속성 b 만 남게 됨.
+delete myobj.a;
+console.log ("a" in myobj) // "false"를 출력
+
+ +

var 키워드로 선언하지 않은 전역 변수도 delete를 이용하여 삭제를 할 수 있다:

+ +
g = 17;
+delete g;
+
+ +

더 자세한 정보는 delete를 보면 된다.

+ +

객체 간의 비교

+ +

JavaScript 에서는 객체들은 레퍼런스 타입이다. 두 개의 별개 객체들은, 설령 그 속성 값들이 모두 다 동일하다고 하더라도, 절대로 동일하다고 비교(equal)될 수 없다. In JavaScript objects are a reference type. Two distinct objects are never equal, even if they have the same properties. Only comparing the same object reference with itself yields true.

+ +
// 속성은 같지만 서로 별개인 두 변수와 두 객체
+var fruit = {name: "apple"};
+var fruitbear = {name: "apple"};
+
+fruit == fruitbear // false 리턴
+fruit === fruitbear // false 리턴
+ +
// 두 개의 변수이지만 하나의 객체
+var fruit = {name: "apple"};
+var fruitbear = fruit;  // fruit 객체 레퍼런스를 fruitbear 에 할당
+
+// here fruit and fruitbear are pointing to same object
+fruit == fruitbear // true 리턴
+fruit === fruitbear // true 리턴
+
+ +

비교 연산자에 대한 상세한 정보는 Comparison operators를 참고하기 바란다.

+ +

추가 검토

+ + + +
{{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Details_of_the_Object_Model")}}
diff --git "a/files/ko/web/javascript/guide/\352\260\235\354\262\264_\353\252\250\353\215\270\354\235\230_\354\204\270\353\266\200\354\202\254\355\225\255/index.html" "b/files/ko/web/javascript/guide/\352\260\235\354\262\264_\353\252\250\353\215\270\354\235\230_\354\204\270\353\266\200\354\202\254\355\225\255/index.html" new file mode 100644 index 0000000000..230d5cb9e1 --- /dev/null +++ "b/files/ko/web/javascript/guide/\352\260\235\354\262\264_\353\252\250\353\215\270\354\235\230_\354\204\270\353\266\200\354\202\254\355\225\255/index.html" @@ -0,0 +1,714 @@ +--- +title: 객체 모델의 세부 사항 +slug: Web/JavaScript/Guide/객체_모델의_세부사항 +translation_of: Web/JavaScript/Guide/Details_of_the_Object_Model +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Iterators_and_Generators")}}
+ +

자바스크립트는 클래스 기반이 아닌 prototype에 기초한 객체 기반 언어 입니다. 이런 차이점으로 인해, 객체들의 계층 구조의 생성과 속성 및 속성 값의 상속을 어떻게 구현해야 하는지에 대한 부분이 덜 분명할 수 있습니다. 이번 장에서는 이런 상황을 명확하게 하고자 합니다. 

+ +

이번 장에선 이미 자바스크립트를 어느 정도 알고 있고, 간단한 객체를 생성하는 함수들을 사용해보았다는 가정하에 진행합니다.

+ +

클래스 기반 언어 대 프로토타입 기반 언어

+ +

Java와 C++같은 클래스 기반의 언어들은 두개의 구별되는 개념에 기반을 두고 있습니다: 그건 바로 클래스와 인스턴스입니다.

+ + + +

자바스크립트같은 프로토타입기반의 언어들은 위와 같은 클래스와 인스턴스의 차이를 두지 않습니다. 간단하게 객체들을 가질 뿐입니다. prototype기반의 언어는 원형(프로토타입)의 객체 개념을 가지고 있습니다. 하나의 객체는 새로운 객체를 생성했을 때 초기 속성을 가질 수 있도록 하는 형판(template)으로 사용됩니다. 객체는 생성될 때 혹은 실행 시에 자기 자신의 속성을 명시할 수 있습니다. 추가적으로, 객체들은 또 다른 객체를 생성하기 위한 프로토타입으로 연관지어 질 수 있으며 프로토타입으로부터 생성된 두번째 객체가 프로토타입인 첫번째 객체의 속성을 공유(혹은 접근)하는 것을 허용합니다. 

+ +

클래스 정의

+ +

클래스 기반의 언어들에서, 별도의 클래스를 생성하고 그 안에서 해당 클래스를 정의 할 수 있습니다. 해당 정의에서 클래스의 인스턴스를 생성할 수 있는 생성자라고하는 특별한 메서드를 명시할 수 있습니다. 생성자는 해당 인스턴스의 초기 속성 값을 지정할 수 있고, 생성 시점에, 다른 적절한 처리를 수행 할 수 있습니다. 클래스의 인스턴스를 생성하기 위해서 new 연산자와 함께 생성자를 호출해야 합니다. 

+ +

자바스크립트는 위와 비슷한 방법을 취합니다. 하지만 생성자이외에 따로 클래스 정의를 가지고 있지는 않습니다. 대신, 특정 속성및 속성값들을 가지고 객체를 생성하는 생성자 함수를 정의할 수 있습니다. 특정 자바스크립트 함수는 생성자로 사용 될 수 있습니다. 새로운 객체를 생성할려면 new연산자와 함께 생성자 함수를 사용해야 합니다.

+ +
+

ECMAScript 2015에 클래스 선언이 새롭게 소개되었습니다.

+ +
+

ECMAScript 2015에서 소개된 자바스크립트 클래스는 주로 문법적 설탕으로 기존 자바스크립트 프로토타입 기반 상속에  읽기 좋은 형식으로 바뀌었습니다. 이 클래스 문법이 자바스크립트에 새로운 객체 중심 상속 모델을 소개한 것은 아닙니다.

+
+
+ +

하위 클래스와 상속

+ +

클래스 기반 언어에서는 클래스 정의를 통해 클래스 계층구조를 생성합니다. 클래스를 정의할 때 이미 존재하는 클래스의 하위 클래스를 새로운 클래스로 지정할 수 있습니다. 이 하위 클래스는 부모 클래스의 모든 속성을 상속받으며 추가로 새로운 속성을 추가하거나 상속받은 속성을 수정할 수 있습니다. 예를 들어  이름(name)과 부서(dept)을 가진 직원(Employee) 클래스와 그 하위 클래스에 보고(reports) 속성을 추가한 관리자(Manager) 클래스가 있다고 해봅시다. 이 경우 관리자(Manager)의 인스턴스는 다음과 같이 세가지 속성을 모두 가질 수 있습니다 - 이름(name),  부서(dept),  보고(reports).

+ +

자바스크립트는 생성자 함수와 프로토타입 객체를 연결해 상속을 구현합니다. 이런 식으로 직원(Employee) — 관리자(Manager) 예제를 똑같이 구현할 수 있지만 조금 다른 * 사용합니다. 먼저, 이름(name),  부서(dept) 속성을 명시하여 직원(Employee) 생성자 함수를 정의합니다. 그런 다음, 직원(Employee)의 생성자를 호출한 후 보고(reports) 속성을 명시해 관리자(Manager) 생성자 함수를 정의합니다. 마지막으로 Employee.prototype 에서 파생된 새로운 객체를  관리자(Manager) 생성자 함수의 프로토타입으로 지정합니다. 그런 다음 새로운 관리자(Manager)를 만들면 관리자(Manager) 객체를 직원(Employee) 객체로부터 이름(name),  부서(dept) 속성을 상속받습니다. 

+ +

속성의 추가 삭제

+ +

클래스 기반의 언어들에서는, 일반적으로 컴파일 시점에 클래스를 생성한 후에 컴파일 시점 혹은 실행 시에 해당 클래스의 인스턴스를 생성합니다. 클래스가 한번 정의된 후에 클래스를 다시 컴파일 하지 않는다면, 속성의 갯수나 형식을 변경할 수 없습니다. 하지만 자바스크립트에서느 실행 시에 객체의 속성을 추가 혹은 삭제 할 수 있습니다.  만약 객체군의 프로토타입으로 사용되는 객체에 속성을 추가하면, 프로토타입이 되는 객체들에도 새로운 속성이 추가가 됩니다.

+ +

차이점들에 대한 정리

+ +

다음 표는 이런 차이점들에 대한 간략한 요약을 포함하고 있습니다. 이번 장의 다음 내용들은 객체의 계층 구조를 생성하기 위한 자바스크립트 생성자와 프로토타입들의 사용에 대한 세부 사항에 대해 기술합니다. 그리고 동일한 작업을 자바에서 어떻게 처리해야 하는지도 비교해서 살펴보겠습니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
클래스 기반(자바)과 프로토타입(prototype)기반(자바스크립트) 객체 시스템의 비교
클래스 기반(자바)원형 기반(자바스크립트)
클래스와 인스턴스는 별개입니다.모든 객체는 다른 객체로부터 상속을 받습니다.
클래스 정의를 가지고 클래스를 생성하고 생성자 메서드로 인스턴스를 생성합니다.생성자 함수를 가지고 객체군을 정의 및 생성합니다.
new 연산자로 하나의 객체(인스턴스)를 생성합니다.동일합니다.
이미 존재하는 클래스에 대한 하위 클래스를 정의함으로써 객체의 계층구조를 생성합니다.하나의 객체를 생성자 함수와 결합된 프로토타입에 할당함으로써 객체의 계층구조를 생성 합니다.
클래스의 상속 구조에 따라 속성을 상속 받습니다.프로토타입 체인에 따라  속성을 상속 받습니다.
클래스 정의는 모든 인스턴스의 모든 속성을 명시합니다. 실행시에 동적으로 속성을 추가할 수 없습니다.생성자 함수 혹은 프로토타입은 초기 속성들을 명시합니다. 개별 객체 혹은 전체 객체군에 동적으로 속성을 추가 삭제할 수 있습니다.
+ +

직원 예제

+ +

이장의 나머지 부분에서는 다음과 같은 직원 객체의 계층구조를 사용합니다. 

+ +
+

직원 객체의 계층 구조.

+ +

+ + +
+ +

계층 구조 생성

+ +

직원 계층 구조를 구현하기 위한 적절한 생성자 함수를 정의하는 방법에는 여러가지가 있습니다. 개발하려고 하는 어플리케이션에 따라 생성자 함수를 정의 하는 방법은 달라질 수 있습니다. 

+ +

이번 절에서는 상속을 구현하기 위한 간단한 (비교적 유연하지는 않은) 정의 방법을 보여 줄 것입니다. 이런 정의 방법을 사용하게되면, 객체를 생성할 때 어떤 속성 값도 지정을 할 수 없습니다. 새로이 생성된 객체들은 기본값들을 가지고 있으며, 나중에 해당 속성 값들을 변경할 수 있습니다.

+ +

실제 어플리케이션에서는, 객체를 생성할때, 해당 객체가 가져야할 속성을 인자로 받는 생성자를 정의 할수 있습니다.(보다 자세한 사항은 다음을 참조하세요. More flexible constructors). 지금 당장은, 상속이 어떻게 작동하는지를 보여주기 위한 간단한 예제를 사용합니다. 

+ +

다음의 자바와 자바스크립트로 작성된 직원 정의는 비슷합니다. 차이점은 자바언어에서는 개별 속성에 대한 타입(type)을 일일이 지정을 해야 하지만  자바스크립트에서는 일일이 개별 속성에 대한 타입(type)을 지정할 필요가 없다는 것입니다.(이런 이유로 자바스크립트가 약하게 형식화된 언어로 불리는 반면 자바는 강력하게 형식화된 언어로 불립니다.)

+ + + + + + + + +
+

자바스크립트

+ +
+function Employee() {
+  this.name = "";
+  this.dept = "general";
+}
+
+

자바

+ +
+public class Employee {
+   public String name = "";
+   public String dept = "general";
+}
+
+
+ +

관리자와 근로자 정의는 계층 구조상에서 상위에 위치하는 객체를 어떻게 표시하는지에 대한 차이점을 보여 줍니다. 자바스크립트에서는 생성자 함수 정의 이후에 언제든 생성자 함수의 프로토타입(prototype) 속성의 값으로 프로토타입 인스턴스를 추가할 수 있습니다.  자바에서는 클래스 정의에 상위 클래스를 명시해야 합니다. 클래스 정의 이후에는 상위 클래스를 변경할 수 없습니다.

+ +
+

자바스크립트

+ +
function Manager() {
+  Employee.call(this);
+  this.reports = [];
+}
+Manager.prototype = Object.create(Employee.prototype);
+
+function WorkerBee() {
+  Employee.call(this);
+  this.projects = [];
+}
+WorkerBee.prototype = Object.create(Employee.prototype);
+
+ +

자바

+ +
public class Manager extends Employee {
+   public Employee[] reports = new Employee[0];
+}
+
+
+
+public class WorkerBee extends Employee {
+   public String[] projects = new String[0];
+}
+
+
+
+
+ +

엔지니어와 영업사원 정의들은 객체들을 생성합니다. 생성된 객체는 근로자 객체의 하위 객체이고 따라서 직원 객체의 하위 객체가 됩니다. 상속 관계에 따라 엔지니어와 영업사원 객체들은 근로자와 직원객체의 속성을 가지게 됩니다. 게다가, 상속받은 부서 속성은 엔지니어와 영업사원에서 재정되어 새로운 값을 가지게 됩니다. 

+ +
+

자바스크립트

+ +
function SalesPerson() {
+   WorkerBee.call(this);
+   this.dept = "sales";
+   this.quota = 100;
+}
+SalesPerson.prototype = Object.create(WorkerBee.prototype);
+
+function Engineer() {
+   WorkerBee.call(this);
+   this.dept = "engineering";
+   this.machine = "";
+}
+Engineer.prototype = Object.create(WorkerBee.prototype);
+
+ +

Java

+ +
public class SalesPerson extends WorkerBee {
+   public double quota;
+   public dept = "sales";
+   public quota = 100.0;
+}
+
+
+public class Engineer extends WorkerBee {
+   public String machine;
+   public dept = "engineering";
+   public machine = "";
+}
+
+
+ +

이런 정의 방법을 통해, 기본값을 가지는 각각의 속성을 포함하는 객체의 인스턴스를 생성할 수 있습니다. 다음 그림은 새로운 객체를 생성하고 새로운 객체에 대한 속성값들을 보여 표시하기 위한 자바스크립트의 정의들을 보여 줍니다.

+ +
+

유의사항: 클래스 기반 언어들에서 인스턴스라는 용어는 특정한 기술적 의미를 가지고 있습니다. 이러한 언어들에서,  하나의 인스턴스란 하나의 클래스의 개별적인  실체이며 클래스와는 근본적으로 다릅니다. 자바스크립트에서는 클래스와 인스턴스 간의 차이가 없기 때문에, "인스턴스"가 이런 기술적 의미를 갖지 않습니다. 하지만, 자바스크립트에 대해서 얘기하자면, 비공식적으로 "인스턴스"는 특정한 생성자 함수를 이용하여 생성된 오브젝트를  의미합니다. 그래서 이번 예제에서는 jane Engineer 의 인스턴스라고 할 수 있습니다. 이와 유사하게, 부모, 자식, 상위, 하위의 용어들은 자바스크립트에서 공식적인 의미를 갖지 않습니다; 다만 프로토타입 체인 상의 상위 또는 하위 객체를 지칭하기 위해서 비공식적으로 사용할 수 있습니다.

+
+ +

간단한 정의로 객체 생성

+ +
+

객체의 계층구조

+ +

오른쪽에 보이는 코드로 생성된 객체의 계층 구조는 아래와 같습니다.

+ +

+ +

개별 객체들

+ +
var jim = new Employee;
+// jim.name is ''
+// jim.dept is 'general'
+
+var sally = new Manager;
+// sally.name is ''
+// sally.dept is 'general'
+// sally.reports is []
+
+var mark = new WorkerBee;
+// mark.name is ''
+// mark.dept is 'general'
+// mark.projects is []
+
+var fred = new SalesPerson;
+// fred.name is ''
+// fred.dept is 'sales'
+// fred.projects is []
+// fred.quota is 100
+
+var jane = new Engineer;
+// jane.name is ''
+// jane.dept is 'engineering'
+// jane.projects is []
+// jane.machine is ''
+
+
+ +

객체 속성들

+ +

이번 장에서는 객체가 프로토타입체인 상의 다른 객체로부터 특성을 상속받는 방법과 런타임 상에서 프로퍼티를 추가하면 무슨 일이 일어나는 지 살펴봅니다.

+ +

속성 상속

+ +

아래 구문처럼 WorkerBee 생성자로 mark 객체를 생성했다고 가정합니다.

+ +
var mark = new WorkerBee;
+
+ +

new 연산자를 만나면, 자바스크립트는 새로운 일반 객체를 생성하고 암묵적으로 내부의 [[Prototype]](__proto__) 속성의 값을 WorkerBee.prototype 의 값으로 할당하며, 해당 객체를 this 키워드의 값으로써 생성자 함수 WorkerBee에 전달합니다. 내부의 [[Prototype]] 속성은 속성값을 반환하기 위해 사용할 프로토타입 체인을 결정합니다. 이런 속성들이 할당되면, 자바스크립트는 새 객체를 반환하고, 할당 구문에 의해 변수 mark를 객체에 할당합니다.

+ +

이러한 절차는 mark가 프로토타입 체인으로부터 상속받는  속성의 값을 mark 객체 내부에(local values) 명시적으로 부여하진 않습니다. 당신이 속성의 값을 요청하면, 자바스크립트는 먼저 해당 객체에 값이 존재하는지 확인합니다. 존재한다면, 해당 값이 반환됩니다. 만약 해당 객체에 값이 없다면, 프로토타입 체인을 (내장 [[Prototype]] 속성;__proto__을 이용하여)확인합니다. 체인 상의 어떤 객체가 해당 속성의 값을 가지고 있다면 그 값이 반환됩니다. 그런 속성이 발견되지 않는다면, 자바스크립트는 객체가 속성을 가지고있지 않다고 할 것입니다. 이런 식으로, mark 객체는 다음의 속성과 값을 가집니다.

+ +
mark.name = "";
+mark.dept = "general";
+mark.projects = [];
+ +

mark 객체는 mark.__proto__로 연결되어 있는 원형의 객체로부터 이름(name)과 부서(dept)에 대한 값을 상속 받습니다. 근로자(WorkerBee) 생성자로부터 projects속성에 대한 값을 할당을 받습니다.이것들이 자바스크립트내에서 속성과 속성 값의 상속입니다. 이런 과정의 몇몇 세부 사항들은 Property inheritance revisited에서 다룹니다. 

+ +

이런 생성자들은 당신이 직접 인스턴스에만 해당 하는 값을 설정하도록 하지 않기때문에, 객체에 대한 이런 정보들은 일반적으로 적용됩니다. 근로자(WorkerBee)로부터 생성된 모든 새로운 객체들은 기본값이 적용된 속성 값들을 가지게 됩니다. 물론, 속성 값들을 변경할 수 있습니다. 아래처럼 특정 인스턴스에만 해당하는 값을 설정할 수 있습니다. 

+ +
mark.name = "Doe, Mark";
+mark.dept = "admin";
+mark.projects = ["navigator"];
+ +

속성 추가

+ +

자바스크립트에선, 실행 시점에 특정 객체에 속성들을 추가 할 수 있습니다.생성자 함수가 제공하는 속성외에 다른 속성을 추가할 수 있습니다. 특정 단일 객체에 속성을 추가하기 위해선, 다음과 같이 해당 객체에 값을 할당 하면 됩니다:

+ +
mark.bonus = 3000;
+
+ +

이렇게 하면 mark객체는 보너스(bonus)속성을 가지게 됩니다. 하지만 mark객체를 제외한 나머지 근로자(WorkerBee)객체들은 보너스 속성을 가지지 않습니다. 

+ +

만약 생성자 함수의 원형으로 사용되는 객체에 새로운 속성을 추가한다면,  해당 프로토타입 객체(prototype)의 속성을 상속받는 모든 객체에 해당 속성이 추가됩니다. 예를 들면, 전문분야(specialty)속성을 모든 직원 객체에 다음과 같은 구문으로 추가할 수 있습니다:

+ +
Employee.prototype.specialty = "none";
+
+ +

위의 구문을 실행한 직후, mark객체는 "none"이라는 값을 가지는 전문분야(specialty)속성을 가지게 됩니다.아래의 그림들은 해당 속성을 추가한 후 엔지니어(Engineer) 프로토타입에 대해 해당 속성을 재정의 했을 경우 각 객체에 미치는 영향을 보여줍니다.

+ +


+ 속성의 추가

+ +

좀 더 유연한 생성자들

+ +

지금까지 살펴 본 생성자 함수들은 인스턴스를 생성하면서 동시에 속성값을 지정할 수 없었습니다. 자바의 경우, 인스턴스를 생성 시 생성자에 인자들을 넘겨주어 인스턴스의 속성들을 초기화 할 수 있습니다. 다음의 예제 그림들은 자바처럼 인스턴스 생성 시 속성값을 설정하는 방법을 보여줍니다.

+ +


+ Specifying properties in a constructor, take 1

+ +

다음의 표는 자바와 자바스크립트 각각의 생성자와 객체에 대한 정의를 보여 줍니다. 

+ +
+

자바스크립트

+ +

자바

+
+ +
+
function Employee (name, dept) {
+  this.name = name || "";
+  this.dept = dept || "general";
+}
+
+ +
public class Employee {
+   public String name;
+   public String dept;
+   public Employee () {
+      this("", "general");
+   }
+   public Employee (String name) {
+      this(name, "general");
+   }
+   public Employee (String name, String dept) {
+      this.name = name;
+      this.dept = dept;
+   }
+}
+
+
+ +
+
function WorkerBee (projs) {
+
+ this.projects = projs || [];
+}
+WorkerBee.prototype = new Employee;
+
+ +
public class WorkerBee extends Employee {
+   public String[] projects;
+   public WorkerBee () {
+      this(new String[0]);
+   }
+   public WorkerBee (String[] projs) {
+      projects = projs;
+   }
+}
+
+
+ +
+
+function Engineer (mach) {
+   this.dept = "engineering";
+   this.machine = mach || "";
+}
+Engineer.prototype = new WorkerBee;
+
+ +
public class Engineer extends WorkerBee {
+   public String machine;
+   public Engineer () {
+      dept = "engineering";
+      machine = "";
+   }
+   public Engineer (String mach) {
+      dept = "engineering";
+      machine = mach;
+   }
+}
+
+
+ +

자바스크립트의 속성값을 설정하는 방법은 기본값을 설정하기 위한 관용구를 사용합니다.

+ +
this.name = name || "";
+
+ +

자바스크립트의 OR 논리 연산자(||) 첫번째 인자를 평가합니다. 첫번째 인자가 참이면 첫번째 인자를 반환하고 그렇지 않은 경우는 두번째 인자를 반환합니다. 그러므로, 위의 코드는 name인자가 name 속성에 사용 가능한 값을 가지고 있는지 확인합니다. 확인 결과 name속성에 사용가능한 값을 가지고 있을 경우, 해당 값을 this.name에 설정하게 됩니다. 반대로 그렇지 않은 경우는 빈 문자열을 this.name에 설정합니다.얼핏 보면 헛갈리지만 보다 짧은 관용구를 사용하였습니다.

+ +
+

주의: 만약 인자로 false와 빈 문자열 값을 줄 경우 해당 구문은 예상한 대로 작동하지 않을 수 있습니다.

+
+ +

이런 정의들을 가지고, 객체의 인스턴스를 생성할때, 객체 자신만의 속성에 대한 값을 지정할 수 있습니다. 새로운 Engineer를 생성하기 위해서 다음과 같은 구문을 사용할 수 있습니다:

+ +
var jane = new Engineer("belau");
+
+ +

Jane의 속성들은 다음과 같습니다:

+ +
jane.name == "";
+jane.dept == "engineering";
+jane.projects == [];
+jane.machine == "belau"
+
+ +

위와 같은 코드 구문으로는 name과 같이 상속받은 속성에 대한 초기값을 지정할 수 없습니다.만약 상속 받은 속성의 초기값을 설정하고자 한다면, 생성자 함수의 코드를 변경해야 합니다.

+ +

지금까지, 원형 객체를 생성한 후, 그 새로운 객체 자신의 속성과 속성 값을 지정하는 것을 살펴 보았습니다. 프로토타입 체인상에서 해당 생성자가 상위 객체에 대한 생성자를 직접 호출 함으로써 더 많은 속성을 추가하도록 할 수 있습니다. 다음의 그림은 새로운 정의 방법을 보여 줍니다.

+ +


+ 생성자내에서 속성들 정의, 그림 2

+ +

그럼 좀 더 상세하게 생성자 내에서 속성들을 정의하는 것을 살펴 보겠습니다. 다음은 엔지니어(Engineer) 생성자의 새로운 정의입니다:

+ +
function Engineer (name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, "engineering", projs);
+  this.machine = mach || "";
+}
+
+ +

다음과 같이 새로운 엔지니어(Engineer)객체를 생성할 수 있습니다:

+ +
var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
+
+ +

다음과 같은 순서에 따라 객체를 생성하고 속성을 정의하게 됩니다:

+ +
    +
  1. new 연산자는 프로토타입 객체를 생성하고 생성된 객체의 __proto__속성을 Engineer.prototype으로 설정합니다.
  2. +
  3. new 연산자는 새로이 생성된 객체를 엔지니어(Engineer)생성자에 this 키워드의 값으로 전달합니다.
  4. +
  5. 생성자는 생성한 객체에 대한 base라는 새로운 속성을 생성하고 근로자(WorkerBee) 생성자의 값을 base 속성에 할당합니다. 이런 과정은 근로자(WorkerBee) 생성자를 엔지니어(Engineer)객체의 메서드로 만듭니다. base 속성의 이름은 그리 특별하지 않습니다. 다른 어떤 속성명을 사용해도 무방합니다. base 속성명은 단지 해당 속성의 목적을 환기시키기 위한 것입니다.
  6. +
  7. +

    생성자는 base 메서드에 필요한 인자들 ("Doe, Jane" and ["navigator", "javascript"])을 주어 호출합니다.명시적으로 생성자에서 사용한 "engineering"은 모든 엔지니어(Engineer)객체들이 상속받은 부서 속성에 대한 동일한 값을 가지며, 직원(Employee)으로부터 상속받은 값을 재정의 하는 것을 나타냅니다.

    +
  8. +
  9. base가 엔지니어(Engineer)의 메서드이기때문에 base메서드 내에서 this키워드를 스텝1에서 생성한 객체를 지칭하도록 해줍니다. 따라서, 근로자(WorkerBee) 함수는 차례대로 "Doe, Jane""engineering" 인자를 직원(Employee)생성자에 전달합니다. 직원(Employee)생성자로부터 반환 시, 근로자(WorkerBee)함수는 남은 인자들을 프로젝트(projects)속성을 설정하기 위해 사용합니다. 
  10. +
  11. base메서드로부터 반환 시, 엔지니어(Engineer) 생성자는 해당 객체의 장비(machine)속성을 "belau"로 초기화 합니다.
  12. +
  13. 생성자로부터 반환 시, 새롭게 생성된 객체를 jane변수에 할당 합니다.
  14. +
+ +

엔지니어(Engineer) 생성자내에서 근로자(WorkerBee)생성자를 호출하면, 엔지니어(Engineer)에 대한 상송을 적절하게 설정할 수 도 있을 것이라고 생각할 수 있을 것입니다.하지만 그렇지 않습니다. 근로자(WorkerBee)생성자를 호출하는 것은 엔지니어(Engineer)객체로 하여금 호출되는 모든 생성자 함수내에서 열거된 속성들을 가지고도록 보장합니다.그러나, 나중에 직원(Employee)혹은 근로자(WorkerBee) 원형에 속성을 추가한다면, 엔지니어(Engineer)객체에 의해 추가된 속성들은 상속이 되지 않습니다. 예를 들어, 아래와 같은 구문을 작성하였다고 가정합니다:

+ +
function Engineer (name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, "engineering", projs);
+  this.machine = mach || "";
+}
+var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
+Employee.prototype.specialty = "none";
+
+ +

jane객체는 전문분야(specialty)속성을 상속받지 않습니다.

+ +
function Engineer (name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, "engineering", projs);
+  this.machine = mach || "";
+}
+Engineer.prototype = new WorkerBee;
+var jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
+Employee.prototype.specialty = "none";
+
+ +

이제 jane객체의 전문분야(specialty)속성은 "none"이 되었습니다.

+ +

call() 혹은 apply() 메서드를 사용는 것은 상속을 구현하는 또 다른 방법입니다. 다음의 두 예제는 동일한 결과를 보여줍니다. 

+ +
+
function Engineer (name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, "engineering", projs);
+  this.machine = mach || "";
+}
+
+ +
function Engineer (name, projs, mach) {
+  WorkerBee.call(this, name, "engineering", projs);
+  this.machine = mach || "";
+}
+
+
+ +

base를 사용하지 않고 구현을 하기 때문에, call() 메서드를 사용하여 상속을 구현하는 것이 보다 깔끔합니다.

+ +

속성 상속의 재고

+ +

이전 절에서 자바스크립트의 생성자와 원형(prototype)이 어떤 방식으로 상속과 객체의 계층 구조를 제공하는지를 살펴 보았습니다. 이번장에서는 이전 절에서 반드시 명백하게 짚고 넘어가지 않은 일부 미묘한 점들에 대해 살펴보겠습니다.

+ +

객체 자신의 값과 상속받은 값

+ +

이번 장에서 이미 설명된 것 처럼, 객체의 속성에 접근할 때, 자바스크립트는 아래와 같은 절차를 따릅니다.

+ +
    +
  1. 해당 속성에 대한 객체 자신의 값이 있는지 확인하고 있으면 그 값을 반환한다.
  2. +
  3. 객체 자신의 값이 없으면 __proto__ 속성을 사용하여 프로토타입 체인을 확인한다.
  4. +
  5. 프로토타입 체인상의 특정 객체가 해당 속성에 대한 값을 가지고 있다면 해당 객체의 값을 반환한다.
  6. +
  7. 해당 속성을 가진 어떤 객체도 발견하지 못하면 해당 객체는 그 속성을 가지고 있지 않은 것으로 판단한다.
  8. +
+ +

이런 단계들의 결과는 생성자 및 프로토타입 체인등의 것들을 어떻게 정의 하느냐에 따라 달라집니다. 아래와 같은 원래의 예제는 이런 정의들을 가지고 있습니다:

+ +
function Employee () {
+  this.name = "";
+  this.dept = "general";
+}
+
+function WorkerBee () {
+  this.projects = [];
+}
+WorkerBee.prototype = new Employee;
+
+ +

이런 정의들을 가지고, amy라는 근로자(WorkerBee)인스턴스를 아래와 같이 생성하였다고 가정합니다.

+ +
var amy = new WorkerBee;
+
+ +

amy객체는 프로젝트라는 자신만의 속성을 가집니다.이름과 부서 속성들은 amy 자신의 속성이 아닌 amy객체의 __proto__속성을 통해 가지고 온 속성들입니다. 따라서 amy는 이런 속성들의 값을 가지게 됩니다.

+ +
amy.name == "";
+amy.dept == "general";
+amy.projects == [];
+
+ +

직원(Employee)과 연관되어 있는 프로토타입내의 이름 속성의 값을 아래와 같이 변경하였다고 가정합니다.

+ +
Employee.prototype.name = "Unknown"
+
+ +

얼핏보기에, 새로운 값이 모든 직원 인스턴스에 적용이 될것으로 예상하겠지만 그렇지 않습니다. 

+ +

직원 객체의 인스턴스를 생성할때, 해당 인스턴스는 이름 속성에 대해 자신이 가지고 있는 값(빈 문자열)을 취하게 됩니다.이것이 의미하는 것은 새로운 직원 객체를 생성하여 근로자(WorkerBee)의 프로토타입에 설정을 할때, WorkerBee.prototype이 이름 속성에 대한 자신만의 값을 가지고 있다는 것입니다.그러므로, amy객체(근로자 인스턴스)의 이름 속성에 대해 검색할때, WorkerBee.prototype내에서 이름 속성에 대한 amy 객체 자신의 값을 찾게됩니다. 그렇기때문에 Employee.prototype까지의 프로토타입 체인을 검색하지 않게 됩니다.

+ +

실행시에 객체의 속성 값을 변경하고 새로운 값이 모든 하위 객체들에게도 적용되도록 할려면, 객체의 생성자함수에서는 속성을 정의할 수 없습니다. 대신에, 생성자와 연결된 프로토타입에 추가할 수 있습니다. 예를 들어, 이전의 코드를 아래와 같이 변경하였다고 가정합니다:

+ +
function Employee () {
+  this.dept = "general";
+}
+Employee.prototype.name = "";
+
+function WorkerBee () {
+  this.projects = [];
+}
+WorkerBee.prototype = new Employee;
+
+var amy = new WorkerBee;
+
+Employee.prototype.name = "Unknown";
+
+ +

이 경우 amy 객체의 이름 속성의 값은 "Unknown"이 됩니다.

+ +

위의 예제에서처럼, 객체 생성 시에 객체의 속성에 대한 기본 값을 설정하고 실행 시에 해당 속성의 값을 변경하기를 원한다면, 해당 속성들을 생성자 함수 자체안에가 아닌 생성자의 프로토타입에 설정 하여야 합니다.

+ +

인스턴스 관계 결정

+ +

자바스크립트에서의 속성 검색은 객체 자신의 속성들을 먼저 살펴보고 해당 속성명을 찾지 못할 경우, 객체의 특별한 속성인 __proto__내에서 찾게 됩니다. 이런 검색은 재귀적으로 진행되며, 이런 과정을 "프로토타입 체인에서의 검색"이라고 합니다.

+ +

특별한 속성인 __proto__객체가 생성이 될때 설정이 됩니다. __proto__속성은 생성자의 프로토타입 속성의 값으로 설정이 됩니다. 따라서 new Foo() 표현식은 __proto__ == Foo.prototype인 객체를 생성합니다. 결과적으로 Foo.prototype의 속성들에 대한 변경은 new Foo() 표현식으로 생성한 모든 객체에 대한 속성 검색을 변경하게 됩니다.

+ +

모든 객체는 __proto__라는 객체 속성을 가집니다.(예외: Object). 모든 함수들은 prototype이라는 객체 속성을 가집니다. 따라서 객체들은 '프로토타입 상속'에 의해 다른 객체들과의 관계를 가지게 됩니다.객체의 __proto__속성과 함수의 prototype 객체를 비교하여 상속을 테스트 해볼 수 있습니다. 자바스크립트는 특정 객체가 함수 prototype으로부터 상속 받는 객체일 경우 참(true)를 반환하는  instanceof라는 연산자를 제공합니다. 예를 들면,

+ +
var f = new Foo();
+var isTrue = (f instanceof Foo);
+ +

Inheriting properties에 나오는 예제와 동일한 정의들을 작성해 놓았을 경우, 보다 상세한 예제는 아래와 같습니다.엔지니어(Engineer)객체를 아래와 같이 생성합니다:

+ +
var chris = new Engineer("Pigman, Chris", ["jsd"], "fiji");
+
+ +

생성된 객체를 가지고 아래와 같은 구문을 실행할 경우 각 구문에 대한 결과는 모두 참(true)입니다.

+ +
chris.__proto__ == Engineer.prototype;
+chris.__proto__.__proto__ == WorkerBee.prototype;
+chris.__proto__.__proto__.__proto__ == Employee.prototype;
+chris.__proto__.__proto__.__proto__.__proto__ == Object.prototype;
+chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;
+
+ +

주어진 이런 상황에서, instanceOf를 다음과 같이 직접 작성할 수 있을 것입니다:

+ +
function instanceOf(object, constructor) {
+   object = object.__proto__;
+   while (object != null) {
+      if (object == constructor.prototype)
+         return true;
+      if (typeof object == 'xml') {
+        return constructor.prototype == XML.prototype;
+      }
+      object = object.__proto__;
+   }
+   return false;
+}
+
+ +
+

주의: 위의 구현내용은 최신 버전의 자바스크립트에서 XML객체들이 표현되는 방법의 특질을 해결하기 위해 해당 객체의 타입이 "xml"인지 확인합니다. 핵심적인 세부 사항을 확인하려면 {{ bug(634150) }}를 참조하세요.

+
+ +

위의 instanceOf함수를 사용하면 아래의 표현들은 모두 참(true)입니다:

+ +
instanceOf (chris, Engineer)
+instanceOf (chris, WorkerBee)
+instanceOf (chris, Employee)
+instanceOf (chris, Object)
+
+ +

하지만 아래의 표현식은 거짓(false)가 됩니다:

+ +
instanceOf (chris, SalesPerson)
+
+ +

생성자내에서의 전역 정보

+ +

생성자를 생성할때, 생성자내에서 전역 정보를 설정할 경우, 주의를 해야 합니다. 예를 들어, 각각의 새로운 직원에게 자동으로 고유한 ID값을 할당하기를 원한다고 했을 때, 다음과 같은 직원(Employee) 정의를 사용할 수 있을 것입니다:

+ +
var idCounter = 1;
+
+function Employee (name, dept) {
+   this.name = name || "";
+   this.dept = dept || "general";
+   this.id = idCounter++;
+}
+
+ +

이런 정의 내용을 가지고, 새로운 직원을 생성했을 때, 생성자는 다음의 고유한 ID값을 새로운 직원객체에 할당하고 전역 ID 카운터를 증가 시킵니다. 따라서 다음과 같은 구문으로 각각의 객체를 생성한다면, 결과는 victoria.id는 1 그리고 harry.id는 2가 됩니다:

+ +
var victoria = new Employee("Pigbert, Victoria", "pubs")
+var harry = new Employee("Tschopik, Harry", "sales")
+
+ +

얼핏보면 괜찮아 보입니다. 하지만 이유를 불문하고 직원 객체가 생성될때마다 idCounter는 증가분을 가지게 됩니다.이번장에서 나온 예제에서처럼 전체 직원(Employee) 객체의 계층 구조를 생성하였다면, 프로토타입을 설정할때마다 직원 생성자는 매번 호출 됩니다.다음과 같은 코드를 작성하였다고 가정합니다:

+ +
var idCounter = 1;
+
+function Employee (name, dept) {
+   this.name = name || "";
+   this.dept = dept || "general";
+   this.id = idCounter++;
+}
+
+function Manager (name, dept, reports) {...}
+Manager.prototype = new Employee;
+
+function WorkerBee (name, dept, projs) {...}
+WorkerBee.prototype = new Employee;
+
+function Engineer (name, projs, mach) {...}
+Engineer.prototype = new WorkerBee;
+
+function SalesPerson (name, projs, quota) {...}
+SalesPerson.prototype = new WorkerBee;
+
+var mac = new Engineer("Wood, Mac");
+
+ +

여기서 생략된 정의가 base속성을 가지고 해당 생성자를 프로토타입 체인내의 상위 생성자들을 호출한닥고 좀 더 가정하면, 이런 경우, 생성된 mac객체의 id값은 5가 됩니다.

+ +

어플리케이셔네 따라, 카운터가 이렇게 추가적으로 증가된 것은 문제가 될 수도 그렇지 않을 수 도 있습니다. 카운터에 정확한 값이 설정되기를 원한다면, 사용가능한 해결적은 아래와 같은 생성자를 대신 사용하는 것입니다:

+ +
function Employee (name, dept) {
+   this.name = name || "";
+   this.dept = dept || "general";
+   if (name)
+      this.id = idCounter++;
+}
+
+ +

prototype으로 사용할 직원 인스턴스를 생성할 때, 생성자에 인자들을 주어선 안됩니다. 이 생성자 정의를 사용하여, 인자들을 주지 않을 경우, 생성자는 id에 값을 할당하지 않으며 카운터를 갱신하지 않습니다. 따라서, id값을 가지는 직원 객체에 대해, 반드시 해당 직원의 이름을 명시해야 합니다. 이 예제의 경우 mac인스턴스의 id값은 1이 됩니다.

+ +

다중상속 금지

+ +

몇몇 객체 지향언어들은 다중 상속을 허용합니다. 그것은, 관련이 없는 부모 객체들로 부터 속성들과 값들을 상속 받을 수 있는 것을 말합니다. 자바스크립트는 다중 상속을 지원하지 않습니다.

+ +

속성 값의 상속은 속성에 대한 값을 찾기 위한 프로토타입 체인을 검색에 의해 실행 시점에 이루어 집니다. 하나의 객체는 오로지 하나의 결합된 prototype만을 가지기 때문에, 자바스크립트는 동적으로 하나 이상의 프로토타입 체인으로 부터 상속을 할 수 없습니다. 

+ +

자바스크립트에서, 하나 이상의 다른 생성자 함수를 호출하는 생성자를 사용할 수 있습니다. 이것은 다중 상속처럼 보여질 수 있습니다. 예를 들어, 다음과 같은 구문들을 살펴보세요:

+ +
function Hobbyist (hobby) {
+   this.hobby = hobby || "scuba";
+}
+
+function Engineer (name, projs, mach, hobby) {
+   this.base1 = WorkerBee;
+   this.base1(name, "engineering", projs);
+   this.base2 = Hobbyist;
+   this.base2(hobby);
+   this.machine = mach || "";
+}
+Engineer.prototype = new WorkerBee;
+
+var dennis = new Engineer("Doe, Dennis", ["collabra"], "hugo")
+
+ +

WorkerBee의 정의는 이번 장의 이전에 사용된 것과 동일하다고 가정합니다.이런 경우, dennis객체는 다음과 같은 속성들을 가지게 됩니다:

+ +
dennis.name == "Doe, Dennis"
+dennis.dept == "engineering"
+dennis.projects == ["collabra"]
+dennis.machine == "hugo"
+dennis.hobby == "scuba"
+
+ +

 따라서 dennis객체는 Hobbyist 생성자로부터 취미(hobby)속성을 받아 오지 않습니다. 그런데 Hobbyist생성자의 프로토타입에 속성을 추가 했다고 가정하면 

+ +
Hobbyist.prototype.equipment = ["mask", "fins", "regulator", "bcd"]
+
+ +

dennis객체는 새로이 추가된 속성을 상속받지 않습니다.

+ +
{{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Iterators_and_Generators")}}
diff --git "a/files/ko/web/javascript/guide/\353\251\224\355\203\200_\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/index.html" "b/files/ko/web/javascript/guide/\353\251\224\355\203\200_\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/index.html" new file mode 100644 index 0000000000..fe4fa13f83 --- /dev/null +++ "b/files/ko/web/javascript/guide/\353\251\224\355\203\200_\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/index.html" @@ -0,0 +1,258 @@ +--- +title: 메타 프로그래밍 +slug: Web/JavaScript/Guide/메타_프로그래밍 +translation_of: Web/JavaScript/Guide/Meta_programming +--- +
{{jsSidebar("JavaScript Guide")}} {{Previous("Web/JavaScript/Guide/Iterators_and_Generators")}}
+ +

Starting with ECMAScript 2015, JavaScript gains support for the {{jsxref("Proxy")}} and {{jsxref("Reflect")}} objects allowing you to intercept and define custom behavior for fundamental language operations (e.g. property lookup, assignment, enumeration, function invocation, etc). With the help of these two objects you are able to program at the meta level of JavaScript.

+ +

Proxies

+ +

 ECMAScript 6에서 소개되었습니다, {{jsxref("Proxy")}} 객체는  특정 작업을 가로막는것과  사용자 정의 행위를 시행하는것을 허용합니다.예를 들면 객체가 속성을 가지는 것입니다:

+ +
var handler = {
+  get: function(target, name){
+    return name in target ? target[name] : 42;
+  }
+};
+var p = new Proxy({}, handler);
+p.a = 1;
+console.log(p.a, p.b); // 1, 42
+
+ +

The Proxy object defines a target (an empty object here) and a handler object in which a get trap is implemented. Here, an object that is proxied will not return undefined when getting undefined properties, but will instead return the number 42.

+ +

Additional examples are available on the {{jsxref("Proxy")}} reference page.

+ +

Terminology

+ +

The following terms are used when talking about the functionality of proxies.

+ +
+
{{jsxref("Global_Objects/Proxy/handler","handler","","true")}}
+
Placeholder object which contains traps.
+
traps
+
The methods that provide property access. This is analogous to the concept of traps in operating systems.
+
target
+
Object which the proxy virtualizes. It is often used as storage backend for the proxy. Invariants (semantics that remain unchanged) regarding object non-extensibility or non-configurable properties are verified against the target.
+
invariants
+
Semantics that remain unchanged when implementing custom operations are called invariants. If you violate the invariants of a handler, a {{jsxref("TypeError")}} will be thrown.
+
+ +

Handlers and traps

+ +

The following table summarizes the available traps available to Proxy objects. See the reference pages for detailed explanations and examples.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Handler / trapInterceptionsInvariants
{{jsxref("Global_Objects/Proxy/handler/getPrototypeOf", "handler.getPrototypeOf()")}}{{jsxref("Object.getPrototypeOf()")}}
+ {{jsxref("Reflect.getPrototypeOf()")}}
+ {{jsxref("Object/proto", "__proto__")}}
+ {{jsxref("Object.prototype.isPrototypeOf()")}}
+ {{jsxref("Operators/instanceof", "instanceof")}}
+
    +
  • getPrototypeOf method must return an object or null.
  • +
  • If target is not extensible, Object.getPrototypeOf(proxy) method must return the same value as Object.getPrototypeOf(target).
  • +
+
{{jsxref("Global_Objects/Proxy/handler/setPrototypeOf", "handler.setPrototypeOf()")}}{{jsxref("Object.setPrototypeOf()")}}
+ {{jsxref("Reflect.setPrototypeOf()")}}
If target is not extensible, the prototype parameter must be the same value as Object.getPrototypeOf(target).
{{jsxref("Global_Objects/Proxy/handler/isExtensible", "handler.isExtensible()")}}{{jsxref("Object.isExtensible()")}}
+ {{jsxref("Reflect.isExtensible()")}}
Object.isExtensible(proxy) must return the same value as Object.isExtensible(target).
{{jsxref("Global_Objects/Proxy/handler/preventExtensions", "handler.preventExtensions()")}}{{jsxref("Object.preventExtensions()")}}
+ {{jsxref("Reflect.preventExtensions()")}}
Object.preventExtensions(proxy) only returns true if Object.isExtensible(proxy) is false.
{{jsxref("Global_Objects/Proxy/handler/getOwnPropertyDescriptor", "handler.getOwnPropertyDescriptor()")}}{{jsxref("Object.getOwnPropertyDescriptor()")}}
+ {{jsxref("Reflect.getOwnPropertyDescriptor()")}}
+
    +
  • getOwnPropertyDescriptor must return an object or undefined.
  • +
  • A property cannot be reported as non-existent, if it exists as a non-configurable own property of the target object.
  • +
  • A property cannot be reported as non-existent, if it exists as an own property of the target object and the target object is not extensible.
  • +
  • A property cannot be reported as existent, if it does not exists as an own property of the target object and the target object is not extensible.
  • +
  • A property cannot be reported as non-configurable, if it does not exists as an own property of the target object or if it exists as a configurable own property of the target object.
  • +
  • The result of Object.getOwnPropertyDescriptor(target)can be applied to the target object using Object.defineProperty and will not throw an exception.
  • +
+
{{jsxref("Global_Objects/Proxy/handler/defineProperty", "handler.defineProperty()")}}{{jsxref("Object.defineProperty()")}}
+ {{jsxref("Reflect.defineProperty()")}}
+
    +
  • A property cannot be added, if the target object is not extensible.
  • +
  • A property cannot be added as or modified to be non-configurable, if it does not exists as a non-configurable own property of the target object.
  • +
  • A property may not be non-configurable, if a corresponding configurable property of the target object exists.
  • +
  • If a property has a corresponding target object property then Object.defineProperty(target, prop, descriptor) will not throw an exception.
  • +
  • In strict mode, a false return value from the defineProperty handler will throw a {{jsxref("TypeError")}} exception.
  • +
+
{{jsxref("Global_Objects/Proxy/handler/has", "handler.has()")}}Property query: foo in proxy
+ Inherited property query: foo in Object.create(proxy)
+ {{jsxref("Reflect.has()")}}
+
    +
  • A property cannot be reported as non-existent, if it exists as a non-configurable own property of the target object.
  • +
  • A property cannot be reported as non-existent, if it exists as an own property of the target object and the target object is not extensible.
  • +
+
{{jsxref("Global_Objects/Proxy/handler/get", "handler.get()")}}Property access: proxy[foo]and proxy.bar
+ Inherited property access: Object.create(proxy)[foo]
+ {{jsxref("Reflect.get()")}}
+
    +
  • The value reported for a property must be the same as the value of the corresponding target object property if the target object property is a non-writable, non-configurable data property.
  • +
  • The value reported for a property must be undefined if the corresponding target object property is non-configurable accessor property that has undefined as its [[Get]] attribute.
  • +
+
{{jsxref("Global_Objects/Proxy/handler/set", "handler.set()")}}Property assignment: proxy[foo] = barand proxy.foo = bar
+ Inherited property assignment: Object.create(proxy)[foo] = bar
+ {{jsxref("Reflect.set()")}}
+
    +
  • Cannot change the value of a property to be different from the value of the corresponding target object property if the corresponding target object property is a non-writable, non-configurable data property.
  • +
  • Cannot set the value of a property if the corresponding target object property is a non-configurable accessor property that has undefined as its [[Set]] attribute.
  • +
  • In strict mode, a false return value from the sethandler will throw a {{jsxref("TypeError")}} exception.
  • +
+
{{jsxref("Global_Objects/Proxy/handler/deleteProperty", "handler.deleteProperty()")}}Property deletion: delete proxy[foo] and delete proxy.foo
+ {{jsxref("Reflect.deleteProperty()")}}
A property cannot be deleted, if it exists as a non-configurable own property of the target object.
{{jsxref("Global_Objects/Proxy/handler/enumerate", "handler.enumerate()")}}Property enumeration / for...in: for (var name in proxy) {...}
+ {{jsxref("Reflect.enumerate()")}}
The enumerate method must return an object.
{{jsxref("Global_Objects/Proxy/handler/ownKeys", "handler.ownKeys()")}}{{jsxref("Object.getOwnPropertyNames()")}}
+ {{jsxref("Object.getOwnPropertySymbols()")}}
+ {{jsxref("Object.keys()")}}
+ {{jsxref("Reflect.ownKeys()")}}
+
    +
  • The result of ownKeys is a List.
  • +
  • The Type of each result List element is either {{jsxref("String")}} or {{jsxref("Symbol")}}.
  • +
  • The result List must contain the keys of all non-configurable own properties of the target object.
  • +
  • If the target object is not extensible, then the result List must contain all the keys of the own properties of the target object and no other values.
  • +
+
{{jsxref("Global_Objects/Proxy/handler/apply", "handler.apply()")}}proxy(..args)
+ {{jsxref("Function.prototype.apply()")}} and {{jsxref("Function.prototype.call()")}}
+ {{jsxref("Reflect.apply()")}}
There are no invariants for the handler.applymethod.
{{jsxref("Global_Objects/Proxy/handler/construct", "handler.construct()")}}new proxy(...args)
+ {{jsxref("Reflect.construct()")}}
The result must be an Object.
+ +

Revocable Proxy

+ +

The {{jsxref("Proxy.revocable()")}} method is used to create a revocable Proxy object. This means that the proxy can be revoked via the function revoke and switches the proxy off. Afterwards, any operation on the proxy leads to a {{jsxref("TypeError")}}

+ +
var revocable = Proxy.revocable({}, {
+  get: function(target, name) {
+    return '[[' + name + ']]';
+  }
+});
+var proxy = revocable.proxy;
+console.log(proxy.foo); // "[[foo]]"
+
+revocable.revoke();
+
+console.log(proxy.foo);  // TypeError is thrown
+proxy.foo = 1;           // TypeError again
+delete proxy.foo;        // still TypeError
+typeof proxy;            // "object", typeof doesn't trigger any trap
+ +

Reflection

+ +

{{jsxref("Reflect")}} is a built-in object that provides methods for interceptable JavaScript operations. The methods are the same as those of the {{jsxref("Global_Objects/Proxy/handler","proxy handlers","","true")}}. Reflect is not a function object.

+ +

Reflect helps with forwarding default operations from the handler to the target.

+ +

With {{jsxref("Reflect.has()")}} for example, you get the in operator as a function:

+ +
Reflect.has(Object, 'assign'); // true
+ +

A better apply function

+ +

In ES5, you typically use the {{jsxref("Function.prototype.apply()")}} method to call a function with a given this value and arguments provided as an array (or an array-like object).

+ +
Function.prototype.apply.call(Math.floor, undefined, [1.75]);
+ +

With {{jsxref("Reflect.apply")}} this becomes less verbose and easier to understand:

+ +
Reflect.apply(Math.floor, undefined, [1.75]);
+// 1;
+
+Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]);
+// "hello"
+
+Reflect.apply(RegExp.prototype.exec, /ab/, ['confabulation']).index;
+// 4
+
+Reflect.apply(''.charAt, 'ponies', [3]);
+// "i"
+ +

Checking if property definition has been successful

+ +

With {{jsxref("Object.defineProperty")}}, which returns an object if successful, or throws a {{jsxref("TypeError")}} otherwise, you would use a {{jsxref("Statements/try...catch","try...catch")}} block to catch any error that occurred while defining a property. Because {{jsxref("Reflect.defineProperty")}} returns a Boolean success status, you can just use an {{jsxref("Statements/if...else","if...else")}} block here:

+ +
if (Reflect.defineProperty(target, property, attributes)) {
+  // success
+} else {
+  // failure
+}
+ +

{{Previous("Web/JavaScript/Guide/Iterators_and_Generators")}}

+ +

 

diff --git "a/files/ko/web/javascript/guide/\354\206\214\352\260\234/index.html" "b/files/ko/web/javascript/guide/\354\206\214\352\260\234/index.html" new file mode 100644 index 0000000000..cac0779ee0 --- /dev/null +++ "b/files/ko/web/javascript/guide/\354\206\214\352\260\234/index.html" @@ -0,0 +1,153 @@ +--- +title: Introduction +slug: Web/JavaScript/Guide/소개 +tags: + - JavaScript + - 가이드 + - 안내서 + - 자바스크립트 +translation_of: Web/JavaScript/Guide/Introduction +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Grammar_and_types")}}
+ +

이 장은 JavaScript를 소개하고 그 일부 기초 개념을 다룹니다.

+ +

무엇을 미리 알고 있어야 하나요?

+ +

이 안내서는 당신이 다음의 기본적인 배경지식이 있다고 가정합니다.

+ + + +

어디서 JavaScript 정보를 찾을 수 있을까

+ +

MDN에 있는 JavaScript 문서는 다음 세가지 파트로 되어있습니다.

+ + + +

JavaScript가 처음이라면, learning areaJavaScript Guide에 있는 문서를 먼저 보세요. 일단 기초를 확실히 파악한 후에는, 각 객체와 문(statement)에 대한 더 자세한 정보를 JavaScript Reference에서 확인할 수 있습니다.

+ +

JavaScript는 무엇인가?

+ +

JavaScript는 크로스-플랫폼, 객체지향 스크립트 언어입니다. 작고 가벼운 언어입니다. 호스트 환경(가령, 웹 브라우저) 내에서, JavaScript는 프로그램 제어를 제공하기 위해 그 환경의 객체에 연결될 수 있습니다. Node.Js와 같은 자바 스크립트의 고급 서버언어로 사용 할 수도 있습니다.이것을 사용하면 단순히 파일을 다운로드하는 것 (예 : 여러 컴퓨터 간의 실시간 공동 작업)보다 웹 사이트에 더 많은 기능을 추가 할 수 있습니다. 호스트 환경 (예 : 웹 브라우저) 내에서 JavaScript는 해당 환경의 객체에 연결되어 프로그래밍 방식으로 제어 할 수 있습니다.

+ +

JavaScript는 Array, Date, Math와 같은 객체에 대한 표준 라이브러리와 연산자(operator), 제어 구조, 문과 같은 언어 요소의 코어 집합을 포함합니다. 코어 JavaScript는 거기에 추가 객체를 보충하여 다양한 목적으로 확장될 수 있습니다. 예를 들면:

+ + + +

이것은 브라우저에서 JavaScript가 웹 페이지 (DOM)의 모양을 바꿀 수 있음을 의미합니다. 또한 서버의 Node.js JavaScript는 브라우저에 작성된 코드의 사용자 정의 요청에 응답 할 수 있습니다.

+ +

JavaScript 와 Java

+ +

JavaScript 와 Java는 여러 면에서 비슷하지만 어떤 면에서는 근본적으로 다릅니다. JavaScript 언어는 Java를 닮았지만 Java의 정적 형지정(static typing)과 강한 형 검사(strong type checking)가 없습니다. JavaScript는 대부분의 Java 식 구문, 명명 규칙 및 기본적인 흐름 제어 구조를 따릅니다. 그것이 LiveScript에서 JavaScript로 이름이 바뀐 이유였습니다.

+ +

Java의 선언에 의해 생성되는 클래스의 컴파일-타임 시스템과는 달리, JavaScript는 숫자, 불리언, 그리고 문자열 값을 표현하는 적은 수의 자료 형을 기반으로 한 런타임 시스템을 지원합니다. JavaScript 는 더 일반적인 클래스 기반 객체 모델 대신에 프로토타입 기반 객체 모델을 갖습니다. 프로토타입 기반 모델은 동적 상속을 제공합니다. 즉, 상속된 대상은 각각의 객체에 따라 다양할 수 있습니다. JavaScript는 또한 어떤 특정한 선언을 요구하지 않는 함수도 지원합니다. 함수는 객체의 속성이나, 타입이 느슨하게 형지정된 채 실행되는 메소드가 될 수 있습니다.

+ +

JavaScript는 Java에 비해 매우 자유로운 형태의 언어입니다. 여러분은 모든 변수, 클래스, 및 메소드를 선언하지 않아도 됩니다. 여러분은 메소드가 public, private, 또는 protected 인지 염려할 필요가 없고 인터페이스를 구현하지 않아도 됩니다. 변수, 매개변수(parameter), 및 함수의 반환 형은 명시적으로 지정되지 않습니다.

+ +

Java는 빠른 실행과 형 안전성(type safety)을 위해 설계된 클래스 기반 프로그래밍 언어입니다. 형 안전성은, 예를 들어, 여러분이 Java 정수를 객체의 레퍼런스로 형변환(cast)하거나 Java 바이트코드를 변경하여 private 메모리에 접근할 수 없음을 의미합니다. Java의 클래스 기반 모델은 프로그램이 오로지 클래스와 그 메소드로만 구성된다는 것을 뜻합니다. Java의 클래스 상속과 강한 형지정은 보통 단단하게 결합된 객체 계층구조를 요구합니다. 이러한 요구는 Java 프로그래밍을 JavaScript 프로그래밍보다 더 복잡하게 만듭니다.

+ +

반면에, JavaScript는 HyperTalk 과 dBASE 같은 더 작고 동적 형지정이 가능한 언어들의 정신을 계승했습니다. 이러한 스크립팅 언어는 더 쉬운 구문과 특별한 내장(built-in) 기능 및 객체 생성을 위한 최소 요구사항으로 인해 훨씬 더 많은 사람들에게 프로그래밍 도구를 제공합니다.

+ + + + + + + + + + + + + + + + + + + + + + + +
Java와 비교한 JavaScript
JavaScriptJava
객체 지향. 객체의 형 간에 차이 없음. 프로토타입 메커니즘을 통한 상속, 그리고 속성과 메서드는 어떤 객체든 동적으로 추가될 수 있음.클래스 기반. 객체는 클래스 계층구조를 통한 모든 상속과 함께 클래스와 인스턴스로 나뉨. 클래스와 인스턴스는 동적으로 추가된 속성이나 메소드를 가질 수 없음.
변수 자료형이 선언되지 않음(dynamic typing, loosely typed).변수 자료형은 반드시 선언되어야 함(정적 형지정, static typing).
하드 디스크에 자동으로 작성 불가.하드 디스크에 자동으로 작성 가능.
+ +

JavaScript와 Java의 차이에 대한 더 많은 정보는, 객체 모델의 세부사항 장을 보세요.

+ +

JavaScript 와 ECMAScript 명세

+ +

JavaScript는 JavaScript에 기반한 표준화된 국제 프로그래밍 언어를 제공하기 위해Ecma International 에서 표준화 됩니다 — European association for standardizing information and communication systems (ECMA는 이전에 European Computer Manufacturers Association의 두문자어였습니다). ECMAScript라 불리는 이 JavaScript의 표준화 버전은 표준을 지원하는 모든 어플리케이션에서 같은 방식으로 동작합니다. 회사들은 그들의 JavaScript 구현을 개발하기 위해 공개 표준 언어를 사용할 수 있습니다. ECMAScript 표준은 ECMA-262 명세(specification)에서 문서화되었습니다. JavaScript와 ECMAScript 명세 판의 여러 버전에 대한 더 많은 것을 배우려면 New in JavaScript 을 보세요.

+ +

ECMA-262 표준은 또한 IOS-16262로서 ISO (국제 표준화 기구) 에 의해 승인되었습니다. Ecma International website 에서 그 명세를 찾을 수 있습니다. ECMAScript 명세는 World Wide Web Consortium (W3C) 나  WHATWG (Web Hypertext Application Technology Working Group)에 의해 표준화된 Document Object Model (DOM)을 설명하지 않습니다. DOM은 여러분의 스크립트에 HTML 문서 객체를 드러내는 방법을 정의합니다. JavaScript로 프로그래밍을 할 때 사용되는 여러 기술들에 대한 정보를 얻으 시려면, JavaScript technologies overview 를 참고하세요.

+ +

JavaScript 문서 vs ECMAScript 명세

+ +

ECMAScript 명세는 ECMAScript 구현을 위한 요구사항의 집합입니다; 여러분이 여러분의 ECMAScript 구현이나 엔진(가령 Firefox의 SpiderMonkey, 또는 Chrome의 v8)에서 표준을 따르는 언어의 기능을 구현하길 원할 때 유용합니다.

+ +

ECMAScript 문서는 스크립트 프로그래머를 돕기 위함이 아닙니다; 스크립트 작성을 위한 정보는 JavaScript 문서를 사용하세요.

+ +

ECMAScript 명세는 JavaScript 프로그래머에게 익숙하지 않을 수 있는 용어와 문법을 사용합니다. 언어의 기술이 ECMAScript 에서 다를 수 있지만, 언어 그 자체는 같습니다. JavaScript는 ECMAScript 명세에 서술된 모든 기능을 지원합니다.

+ +

JavaScript 문서는 JavaScript 프로그래머에게 적합한 언어의 측면을 설명합니다.

+ +

JavaScript 시작하기

+ +

JavaScript 시작은 쉽습니다: 최신 웹 브라우저만 있으면 됩니다. 이 안내서는 현재 Firefox의 최신 버전에서만 사용 가능한 약간의 JavaScript 기능을 포함하므로, 가장 최신 버전의 Firefox를 사용하기를 권합니다.

+ +

JavaScript를 실험하기 유용한 두 도구가 Firefox에 내장되어 있습니다: Web Console과 Scratchpad.

+ +

웹 콘솔

+ +

웹 콘솔은 현재 로드된 페이지에 대한 정보를 보이고, 또한 여러분이 현재 페이지에서 JavaScript 식을 실행해볼 수 있는 명령어 입력줄(command line)을 제공합니다.

+ +

웹 콘솔을 열기 위해서는, Firefox의 "도구" 메뉴 하위에 있는 "개발자" 메뉴의 "웹 콘솔"을 선택(윈도우와 리눅스에서는 Ctrl+Shift+I, 맥에서는  Cmd-Option-K)합니다. 브라우저 창의 아래에 웹 콘솔이 나타납니다. 콘솔의 바닥을 따라 나온 것이 여러분이 JavaScript를 입력할 수 있는 명령어 입력줄이고, 실행 결과는 바로 위 공간에 표시됩니다:

+ +

+ +

이 콘솔은 eval과 완전히 동일하게 동작합니다:마지막 입력된 표현식이 반환되죠. 간단하게 생각해서, 콘솔에 뭔가 입력할 때마다 eval로 감싼 console.log로 둘러싸인 형태라고 보시면 됩니다.

+ +
function greetMe(yourName) { alert('Hello ' + yourName); } console.log(eval('3 + 5'));
+ +

Scratchpad

+ +

Web Console은 한 줄 JavaScript를 실행하기에 훌륭합니다. 하지만 비록 여러 줄을 실행할 수 있지만, 아주 불편하고 Web Console을 사용해 여러분의 샘플 코드를 저장할 수도 없습니다. 그러므로 좀 더 복잡한 예제를 위해서는 Scratchpad가 더 나은 도구입니다.

+ +

Scratchpad를 열기 위해, Firefox의 메뉴 "Tools" 의 하위에 있는 "Web Developer" 메뉴의 "Scratchpad" 를 선택합니다(단축키: Shift+F4). 이것은 분리된 창에서 열리고 브라우저에서 JavaScript를 작성하고 실행하기 위해 사용할 수 있는 에디터입니다. 여러분은 또한 디스크로부터 스크립트를 부르거나 저장할 수도 있습니다.

+ +

+ +

Hello world

+ +

JavaScript 작성을 시작하기 위해서, Scratchpad를 열고 첫 JavaScript 코드 "Hello World" 를 작성하세요.

+ +
(function(){
+  "use strict";
+  /* Start of your code */
+  function greetMe(yourName) {
+    alert('Hello ' + yourName);
+  }
+
+  greetMe('World');
+  /* End of your code */
+})();
+ +

패드에서 코드를 선택하고 Ctrl + R 키를 눌러 브라우저에서 펼쳐지는 것을 지켜보십시오! 다음 페이지에서 이 가이드는 JavaScript 구문 및 언어 기능을 소개하므로보다 복잡한 응용 프로그램을 작성할 수 있습니다. 그러나 당분간은 (function () { "use strict"를 코드 앞에 추가하고}}) ();를 코드마지막에 추가하세요. 아직은 이코드가 뭔지 잘 모르겠지만 나중에 이 코드가 의미하는 것을 배울 것입니다, 지금은 간단히 다음과 같다고 생각하세요.

+ +
    +
  1. 성능을 크게 개선합니다.
  2. +
  3. 초보자가 실수하게 만드는 Javascript의 일부 시맨틱을 막습니다.
  4. +
  5. 콘솔에서 실행되는 코드 스니펫이 서로 상호 작용하지 못하도록합니다 (예 : 한 콘솔 실행에서 생성 된 내용을 다른 콘솔 실행에 사용하는 경우).
  6. +
+ +

{{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Grammar_and_types")}}

diff --git "a/files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/assertions/index.html" "b/files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/assertions/index.html" new file mode 100644 index 0000000000..350c50f8f9 --- /dev/null +++ "b/files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/assertions/index.html" @@ -0,0 +1,244 @@ +--- +title: Assertions +slug: Web/JavaScript/Guide/정규식/Assertions +translation_of: Web/JavaScript/Guide/Regular_Expressions/Assertions +--- +

{{jsSidebar("JavaScript Guide")}}

+ +

Assertions에는 행이나 단어의 시작 · 끝을 나타내는 경계와 (앞, 뒤 읽고 조건식을 포함한) 어떤 식 으로든 매치가 가능한 것을 나타내는 다른 패턴이 포함됩니다.

+ +
{{EmbedInteractiveExample("pages/js/regexp-assertions.html", "taller")}}
+ +

Types

+ +

Boundary-type assertions

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CharactersMeaning
^ +

Matches the beginning of input. If the multiline flag is set to true, also matches immediately after a line break character. For example, /^A/ does not match the "A" in "an A", but does match the first "A" in "An A".

+ +
+

This character has a different meaning when it appears at the start of a group.

+
+
$ +

Matches the end of input. If the multiline flag is set to true, also matches immediately before a line break character. For example, /t$/ does not match the "t" in "eater", but does match it in "eat".

+
\b +

Matches a word boundary. This is the position where a word character is not followed or preceded by another word-character, such as between a letter and a space. Note that a matched word boundary is not included in the match. In other words, the length of a matched word boundary is zero.

+ +

Examples:

+ +
    +
  • /\bm/ matches the "m" in "moon".
  • +
  • /oo\b/ does not match the "oo" in "moon", because "oo" is followed by "n" which is a word character.
  • +
  • /oon\b/ matches the "oon" in "moon", because "oon" is the end of the string, thus not followed by a word character.
  • +
  • /\w\b\w/ will never match anything, because a word character can never be followed by both a non-word and a word character.
  • +
+ +

To match a backspace character ([\b]), see Character Classes.

+
\B +

Matches a non-word boundary. This is a position where the previous and next character are of the same type: Either both must be words, or both must be non-words, for example between two letters or between two spaces. The beginning and end of a string are considered non-words. Same as the matched word boundary, the matched non-word boundary is also not included in the match. For example, /\Bon/ matches "on" in "at noon", and /ye\B/ matches "ye" in "possibly yesterday".

+
+ +

Other assertions

+ +
+

Note: The ? character may also be used as a quantifier.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CharactersMeaning
x(?=y) +

Lookahead assertion: Matches "x" only if "x" is followed by "y". For example, /Jack(?=Sprat)/ matches "Jack" only if it is followed by "Sprat".
+ /Jack(?=Sprat|Frost)/ matches "Jack" only if it is followed by "Sprat" or "Frost". However, neither "Sprat" nor "Frost" is part of the match results.

+
x(?!y) +

Negative lookahead assertion: Matches "x" only if "x" is not followed by "y". For example, /\d+(?!\.)/ matches a number only if it is not followed by a decimal point. /\d+(?!\.)/.exec('3.141') matches "141" but not "3.

+
(?<=y)x +

Lookbehind assertion: Matches "x" only if "x" is preceded by "y". For example, /(?<=Jack)Sprat/ matches "Sprat" only if it is preceded by "Jack". /(?<=Jack|Tom)Sprat/ matches "Sprat" only if it is preceded by "Jack" or "Tom". However, neither "Jack" nor "Tom" is part of the match results.

+
(?<!y)x +

Negative lookbehind assertion: Matches "x" only if "x" is not preceded by "y". For example, /(?<!-)\d+/ matches a number only if it is not preceded by a minus sign. /(?<!-)\d+/.exec('3') matches "3". /(?<!-)\d+/.exec('-3')  match is not found because the number is preceded by the minus sign.

+
+ +

Examples

+ +

General boundary-type overview example

+ +
// Using Regex boundaries to fix buggy string.
+buggyMultiline = `tey, ihe light-greon apple
+tangs on ihe greon traa`;
+
+// 1) Use ^ to fix the matching at the begining of the string, and right after newline.
+buggyMultiline = buggyMultiline.replace(/^t/gim,'h');
+console.log(1, buggyMultiline); // fix 'tey', 'tangs' => 'hey', 'hangs'. Avoid 'traa'.
+
+// 2) Use $ to fix matching at the end of the text.
+buggyMultiline = buggyMultiline.replace(/aa$/gim,'ee.');
+console.log(2, buggyMultiline); // fix  'traa' => 'tree'.
+
+// 3) Use \b to match characters right on border between a word and a space.
+buggyMultiline = buggyMultiline.replace(/\bi/gim,'t');
+console.log(3, buggyMultiline); // fix  'ihe' but does not touch 'light'.
+
+// 4) Use \B to match characters inside borders of an entity.
+fixedMultiline = buggyMultiline.replace(/\Bo/gim,'e');
+console.log(4, fixedMultiline); // fix  'greon' but does not touch 'on'.
+
+ +

Matching the beginning of an input using a ^ control character

+ +

입력 시작시 일치를 위해 ^를 사용하십시오. 이 예에서는 /^A/ regex로 'A'로 시작하는 결과를 얻습니다. 여기서 ^는 한 가지 역할 만합니다. 적절한 결과를 보기위해 화살표 함수가있는 필터 메소드를 사용합니다.

+ +
let fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];
+
+// Select fruits started with 'A' by /^A/ Regex.
+// Here '^' control symbol used only in one role: Matching begining of an input.
+
+let fruitsStartsWithA = fruits.filter(fruit => /^A/.test(fruit));
+console.log(fruitsStartsWithA); // [ 'Apple', 'Avocado' ]
+
+ +

두 번째 예제에서 ^는 두 가지 모두에 사용됩니다 : 입력의 일치 시작점, 그룹에서 사용될 때 부정 또는 보완 문자 세트.

+ +
let fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];
+
+// Selecting fruits that dose not start by 'A' by a /^[^A]/ regex.
+// In this example, two meanings of '^' control symbol are represented:
+// 1) Matching begining of the input
+// 2) A negated or complemented character set: [^A]
+// That is, it matches anything that is not enclosed in the brackets.
+
+let fruitsStartsWithNotA = fruits.filter(fruit => /^[^A]/.test(fruit));
+
+console.log(fruitsStartsWithNotA); // [ 'Watermelon', 'Orange', 'Strawberry' ]
+ +

Matching a word boundary

+ +
let fruitsWithDescription = ["Red apple", "Orange orange", "Green Avocado"];
+
+// Select descriptions that contains 'en' or 'ed' words endings:
+let enEdSelection = fruitsWithDescription.filter(descr => /(en|ed)\b/.test(descr));
+
+console.log(enEdSelection); // [ 'Red apple', 'Green Avocado' ]
+ +

Lookahead assertion

+ +
// JS Lookahead assertion x(?=y)
+
+let regex = /First(?= test)/g;
+
+console.log('First test'.match(regex)); // [ 'First' ]
+console.log('First peach'.match(regex)); // null
+console.log('This is a First test in a year.'.match(regex)); // [ 'First' ]
+console.log('This is a First peach in a month.'.match(regex)); // null
+
+ +

Basic negative lookahead assertion

+ +

For example, /\d+(?!\.)/ matches a number only if it is not followed by a decimal point. /\d+(?!\.)/.exec('3.141') matches "141" but not "3.

+ +
console.log(/\d+(?!\.)/g.exec('3.141')); // [ '141', index: 2, input: '3.141' ]
+
+ +

Different meaning of '?!' combination usage in Assertions and  Ranges 

+ +

Different meaning of ?! combination usage in Assertions /x(?!y)/ and Ranges [^?!].

+ +
let orangeNotLemon = "Do you want to have an orange? Yes, I do not want to have a lemon!";
+
+// Different meaning of '?!' combination usage in Assertions /x(?!y)/ and  Ranges /[^?!]/
+let selectNotLemonRegex = /[^?!]+have(?! a lemon)[^?!]+[?!]/gi
+console.log(orangeNotLemon.match(selectNotLemonRegex)); // [ 'Do you want to have an orange?' ]
+
+let selectNotOrangeRegex = /[^?!]+have(?! an orange)[^?!]+[?!]/gi
+console.log(orangeNotLemon.match(selectNotOrangeRegex)); // [ ' Yes, I do not want to have a lemon!' ]
+
+ +

Lookbehind assertion

+ +
let oranges = ['ripe orange A ', 'green orange B', 'ripe orange C',];
+
+let ripe_oranges = oranges.filter( fruit => fruit.match(/(?<=ripe )orange/));
+console.log(ripe_oranges); // [ 'ripe orange A ', 'ripe orange C' ]
+
+ +

Specifications

+ + + + + + + + + + + + + + +
SpecificationStatusComment
{{SpecName('ESDraft', '#sec-assertion', 'RegExp: Assertions')}}{{Spec2('ESDraft')}}
+ +

Browser compatibility

+ +

For browser compatibility information, check out the main Regular Expressions compatibility table.

+ +

See also

+ + diff --git "a/files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/groups_and_ranges/index.html" "b/files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/groups_and_ranges/index.html" new file mode 100644 index 0000000000..2e2109b4ed --- /dev/null +++ "b/files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/groups_and_ranges/index.html" @@ -0,0 +1,91 @@ +--- +title: Groups and Ranges +slug: Web/JavaScript/Guide/정규식/Groups_and_Ranges +translation_of: Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

그룹(Groups)과 범위(ranges)는 표현 문자의 그룹과 범위를 나타냅니다.

+ +

Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CharactersMeaning
x|y +

x또는 y와 매칭되는 경우. 예를들면 /green|red/ 은 "green apple"의 "green"과 매치되고 "red apple"의 "red"와 매치됩니다.

+
[xyz]
+ [a-c]
+

A character set. Matches any one of the enclosed characters. You can specify a range of characters by using a hyphen, but if the hyphen appears as the first or last character enclosed in the square brackets it is taken as a literal hyphen to be included in the character set as a normal character. It is also possible to include a character class in a character set.

+ +

For example, [abcd] is the same as [a-d]. They match the "b" in "brisket" and the "c" in "chop".

+ +

For example, [abcd-] and [-abcd] match the "b" in "brisket", the "c" in "chop" and the "-" (hyphen) in "non-profit".

+ +

For example, [\w-] is the same as [A-Za-z0-9_-]. They match the "b" in "brisket", the "c" in "chop" and the "n" in "non-profit".

+
+

[^xyz]
+ [^a-c]

+
+

A negated or complemented character set. That is, it matches anything that is not enclosed in the brackets. You can specify a range of characters by using a hyphen, but if the hyphen appears as the first or last character enclosed in the square brackets it is taken as a literal hyphen to be included in the character set as a normal character. For example, [^abc] is the same as [^a-c]. They initially match "o" in "bacon" and "h" in "chop".

+ +
+

The ^ character may also indicate the beginning of input.

+
+
(x) +

Capturing group: Matches x and remembers the match. For example, /(foo)/ matches and remembers "foo" in "foo bar". 

+ +

A regular expression may have multiple capturing groups. In results, matches to capturing groups typically in an array whose members are in the same order as the left parentheses in the capturing group. This is usually just the order of the capturing groups themselves. This becomes important when capturing groups are nested. Matches are accessed using the index of the the result's elements ([1], ..., [n]) or from the predefined RegExp object's properties ($1, ..., $9).

+ +

Capturing groups have a performance penalty. If you don't need the matched substring to be recalled, prefer non-capturing parentheses (see below).

+ +

String.match() won't return groups if the /.../g flag is set. However, you can still use String.matchAll() to get all matches.

+
\n +

Where n is a positive integer. A back reference to the last substring matching the n parenthetical in the regular expression (counting left parentheses). For example, /apple(,)\sorange\1/ matches "apple, orange," in "apple, orange, cherry, peach". A complete example follows this table.

+
(?<Name>x) +

Named capturing group: Matches x and stores it on the groups property of the returned matches under the name specified by <Name>. The angle brackets ('<' and '>') are required for group name.

+ +

For example, to extract the United States area code from a phone number, I could use /\((?<area>\d\d\d)\)/. The resulting number would appear under matches.groups.area.

+
(?:x)Non-capturing group: Matches x but does not remember the match. The matched substring cannot be recalled from the resulting array's elements ([1], ..., [n]) or from the predefined RegExp object's properties ($1, ..., $9).
+ +

Examples

+ +

Browser support

+ +

Firefox currently doesn't support named groups. See corresponding issue.

+ +

See also

diff --git "a/files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/index.html" "b/files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/index.html" new file mode 100644 index 0000000000..5fbbcef0a0 --- /dev/null +++ "b/files/ko/web/javascript/guide/\354\240\225\352\267\234\354\213\235/index.html" @@ -0,0 +1,666 @@ +--- +title: 정규 표현식 +slug: Web/JavaScript/Guide/정규식 +tags: + - 자바스크립트 + - 정규식 +translation_of: Web/JavaScript/Guide/Regular_Expressions +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Text_formatting", "Web/JavaScript/Guide/Indexed_collections")}}
+ +

정규 표현식은 문자열에 나타는 특정 문자 조합과 대응시키기 위해 사용되는 패턴입니다. 자바스크립트에서, 정규 표현식 또한 객체입니다.  이 패턴들은 {{jsxref("RegExp")}}의 {{jsxref("RegExp.exec", "exec")}} 메소드와 {{jsxref("RegExp.test", "test")}} 메소드  ,그리고 {{jsxref("String")}}의  {{jsxref("String.match", "match")}}메소드 , {{jsxref("String.replace", "replace")}}메소드 , {{jsxref("String.search", "search")}}메소드 ,  {{jsxref("String.split", "split")}} 메소드와 함께 쓰입니다 . 이 장에서는 자바스크립트의 정규식에 대하여 설명합니다.

+ +

정규 표현식 만들기

+ +

(역주: 정규 표현식을 줄여서 '정규식'이라고 하기도 합니다. 아래 부분부터 '정규식'이라는 용어를 사용하겠습니다.)

+ +

정규식을 만드는 방법에는 두 가지가 있습니다.

+ +

정규식 리터럴(슬래쉬"/"로 감싸는 패턴)을 사용하는 방법은 다음과 같습니다.

+ +
var re = /ab+c/;
+
+ +

정규식 리터럴은 스크립트가 불러와질 때 컴파일됩니다. 만약 정규식이 상수라면, 이렇게 사용하는 것이 성능을 향상시킬 수 있습니다.

+ +

다른 방법으로는,  {{jsxref("RegExp")}} 객체의 생성자 함수를 호출하는 방법도 있습니다:

+ +
var re = new RegExp("ab+c");
+
+ +

생성자 함수를 사용하면 정규식이 실행 시점에 컴파일됩니다. 정규식의 패턴이 변경될 수 있는 경우, 혹은 사용자 입력과 같이 다른 출처로부터 패턴을 가져와야 하는 경우에는 생성자 함수를 사용하세요.

+ +

정규식 패턴 작성하기

+ +

정규식 패턴은 /abc/ 같이 단순 문자로 구성될 수도 있고, /ab*c/ 또는 /Chapter (\d+)\.\d*/와 같이 단순 문자와 특수 문자의 조합으로 구성될 수도 있습니다. 마지막 예제는 기억장치처럼 쓰이는 괄호를 포함하고 있습니다. {{web.link("#.ED.8C.A8.ED.84.B4.ED.99.94.EB.90.9C_.EB.B6.80.EB.B6.84_.EB.AC.B8.EC.9E.90.EC.97.B4_.EC.9D.BC.EC.B9.98_.EC.82.AC.EC.9A.A9.ED.95.98.EA.B8.B0", "패턴화된 부분 문자열 일치 사용하기") }}에서 설명하는것 처럼 패턴에서 괄호를 포함한 부분은 나중에 사용하기 위하여 저장됩니다.

+ +

단순 패턴 사용하기

+ +

단순 패턴은 문자열을 있는 그대로 대응시키고자 할 때 사용됩니다. 예를 들어, /abc/라는 패턴은 문자열에서 정확히 'abc' 라는 문자들이 모두 함께 순서대로 나타나야 대응됩니다. 위의 패턴은 "Hi, do you know your abc's?" 와 "The latest airplane designs evolved from slabcraft." 두가지 예에서 부분 문자열 'abc'에 대응될 것입니다.  'Grab crab' 이라는 문자열에서 'ab c' 라는 부분 문자열을 포함하고 있지만, 'abc'를 정확하게 포함하고 있지 않기 때문에 대응되지 않습니다.

+ +

특수 문자 사용하기

+ +

검색에서 하나 이상의 b들을 찾거나, 혹은 공백을 찾는 것과 같이 '있는 그대로의 대응' 이상의 대응을 필요로 할 경우, 패턴에 특수한 문자를 포함시킵니다. 예를 들어, /ab*c/ 패턴은  'a' 문자 뒤에 0개 이상의 'b' 문자(* 문자는 바로 앞의 문자가 0개 이상이라는 것을 의미합니다)가 나타나고 바로 뒤에 'c' 문자가 나타나는 문자 조합에 대응됩니다. 문자열 "cbbabbbbcdebc," 에서 위의 패턴은 부분 문자열 'abbbbc' 와 대응됩니다.

+ +

아래 표는 정규식에서 사용되는 모든 특수문자 목록 및 그에 대한 설명입니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
정규식에서의 특수문자
CharacterMeaning
\ +

다음의 규칙에 따라 일치합니다:
+
+ 특수 문자가 아닌 문자(non-special character) 앞에서 사용된 백슬래시는 '해당 문자는 특별하고, 문자 그대로 해석되면 안된다'는 사실을 가리킵니다. 예를 들어, 앞에 \가 없는 'b'는 보통 소문자 b가 나오는 패턴과 대응됩니다. 그러나 '\b' 자체는 어떤 문자와도 대응되지 않습니다; 이 문자는 특별한 단어 경계 문자를 형성합니다.
+
+ 특수 문자 앞에 위치한 백슬래시는 '다음에 나오는 문자는 특별하지않고, 문자 그대로 해석되어야 한다'는 사실을 가리킵니다. 예를 들어, 패턴 /a*/ 에서의 특수문자 '*'는 0개 이상의 'a' 문자가 등장함을 나타냅니다. 이와는 다르게, 패턴 /a\*/ 는 '*'이 특별하지 않다는 것을 나타내며, 'a*'와 같은 문자열과 대응될 수 있습니다.
+
+ RegExp("pattern") 표기를 쓰면서 \ 자체를 이스케이프 하는 것을 잊지 마세요. 왜냐하면 \ 는 문자열에서도 이스케이프 문자이기 때문입니다. (역주: /a\*/ 와 같은 패턴을 생성자로 만들려면 new RegExp('a\\*')와 같이 백슬래시 자체를 이스케이프 시켜주어야 합니다.)

+
^입력의 시작 부분에 대응됩니다. 만약 다중행 플래그가 참으로 설정되어 있다면, 줄 바꿈 문자 바로 다음 부분과도 대응됩니다.
+
+ 예를 들어, /^A/ 는 "an A" 의 'A'와는 대응되지 않습니다, 그러나 "An E" 의 'A'와는 대응됩니다.
+
+ '^' 가 문자셋([abc]) 패턴의 첫 글자로 쓰인다면, 그 때는 전혀 다른 의미를 가집니다. 자세한 내용은 역 문자셋을 참고하세요.
$ +

입력의 끝 부분과 대응됩니다. 만약 다중행 플래그가 참으로 설정되어 있다면, 줄 바꿈 문자의 바로 앞 부분과도 대응됩니다.

+ +

예를 들어, /t$/ 는 "eater" 의 't'에는 대응되지 않습니다, 그러나 "eat" 과는 대응됩니다.

+
* +

앞의 표현식이 0회 이상 연속으로 반복되는 부분과 대응됩니다. {0,} 와 같은 의미입니다.

+ +

예를 들어, /bo*/ 는 "A ghost booooed" 의 'boooo' 와 대응되고, "A bird warbled" 의 'b'에 대응되지만 "A goat grunted" 내의 어느 부분과도 대응되지 않습니다.

+
+ +

앞의 표현식이 1회 이상 연속으로 반복되는 부분과 대응됩니다. {1,} 와 같은 의미입니다.

+ +

예를 들어, /a+/ 는 "candy"의 'a'에 대응되고 "caaaaaaandy" 의 모든 'a'들에 대응되지만, "cndy" 내의 어느 부분과도 대응되지 않습니다.

+
?앞의 표현식이 0 또는 1회 등장하는 부분과 대응됩니다. {0,1} 와 같은 의미입니다.
+
+ 예를 들어, /e?le?/ 는 "angel"의 'el' 에 대응되고, "angle"의 'le' 에 대응되고 또한 "oslo" 의 'l'에도 대응됩니다.
+
+ 만약 수량자 *, +, ?, {} 바로 뒤에 사용하면, 기본적으로 탐욕스럽던(가능한 한 많이 대응시킴) 수량자를 탐욕스럽지 않게(가능한 가장 적은 문자들에 대응시킴) 만듭니다. 예를 들어, /\d+/를 "123abc"에 적용시키면 "123"과 대응됩니다. 그러나 /\d+?/를 같은 문자열에 적용시키면 오직 "1"과만 대응됩니다.
+
+ 또한 이 문자는 x(?=y)x(?!y) 항목에서 설명하는 바와 같이 사전 검증(lookahead assertion)을 위해서도 쓰입니다.
+  
. +

개행 문자를 제외한 모든 단일 문자와 대응됩니다.

+ +

예를 들어, /.n/는 "nay, an apple is on the tree"에서 'an'과 'on'에 대응되지만, 'nay' 에는 대응되지 않습니다.

+
(x) +

다음의 예제가 보여주는것 처럼 'x'에 대응되고, 그것을 기억합니다. 괄호는 포획 괄호(capturing parentheses)라 불립니다.
+
+ 패턴 /(foo) (bar) \1 \2/ 안의 '(foo)' 와 '(bar)'는 문자열"foo bar foo bar"에서 처음의 두 단어에 대응되고 이를 기억합니다. 패턴 내부의 \1\2는 문자열의 마지막 두 단어에 대응됩니다. (역주: \n 패턴은 앞의 n번째 포획괄호에 대응된 문자열과 똑같은 문자열에 대응됩니다.) \1, \2, \n과 같은 문법은 정규식의 패턴 부분에서 사용됩니다. 정규식의 치환 부분에서는 $1, $2, $n과 같은 문법이 사용되어야 합니다. 예를 들어, 'bar foo'.replace( /(...) (...)/, '$2 $1')와 같이 사용되어야 합니다. $& 패턴은 앞에서 대응된 전체 문자열을 가리킵니다.

+
(?:x)'x'에 대응되지만 대응된 것을 기억하지 않습니다. 괄호는 비포획 괄호(non-capturing parentheses)라고 불리우고, 정규식 연산자가 같이 동작할 수 있게 하위 표현을 정의할 수 있습니다. 정규식 예제 /(?:foo){1,2}/을 생각해보세요. 만약 정규식이 /foo{1,2}/라면, {1,2}는 'foo'의 마지막 'o' 에만 적용됩니다. 비포획 괄호과 같이 쓰인다면, {1,2}는 단어 'foo' 전체에 적용됩니다.
x(?=y) +

오직 'y'가 뒤따라오는 'x'에만 대응됩니다. 이것은 lookahead 라고 불립니다.

+ +

예를 들어, /Jack(?=Sprat)/ 는 'Sprat'가 뒤따라오는 'Jack' 에만 대응됩니다. /Jack(?=Sprat|Frost)/는 'Sprat' 또는 'Frost'가 뒤따라오는 'Jack'에만 대응됩니다. 그러나, 'Sprat' 및 'Frost' 는 대응 결과의 일부가 아닙니다.

+
x(?!y) +

'x'뒤에  'y'가 없는경우에만 'x'에 일치합니다. 이것은 negated lookahead 라고 불립니다.

+ +

예를 들어, /\d+(?!\.)/는 소숫점이 뒤따라오지 않는 숫자에 일치합니다. 정규식 /\d+(?!\.)/.exec("3.141")는 '3.141' 이 아닌 '141'에 일치합니다.

+
x|y +

'x' 또는 'y'에 대응됩니다.

+ +

예를 들어, /green|red/는 "green apple"의 'green'에 대응되고, "red apple."의 'red'에 대응됩니다.

+
{n}앞 표현식이 n번 나타나는 부분에 대응됩니다. n은 반드시 양의 정수여야 합니다.
+
+ 예를 들어, /a{2}/는 "candy,"의 'a'에는 대응되지 않지만, "caandy,"의 모든 a 와, "caaandy."의 첫 두 a 에는 대응됩니다.
{n,m} +

nm은 양의 정수이고, n <= m를 만족해야 합니다. 앞 문자가 최소 n개, 최대 m개가 나타나는 부분에 대응됩니다. m이 생략된다면, m은 ∞로 취급됩니다.

+ +

예를 들어, /a{1,3}/는 "cndy"에서 아무것에도 대응되지 않지만, "caandy,"의 첫 두 a 와 "caaaaaaandy"의 첫 세 a 에 대응됩니다. "caaaaaaandy"에서 더 많은 a 들이 있지만, "aaa"에만 대응된다는 점에 주목하세요.

+
[xyz]문자셋(Character set) 입니다. 이 패턴 타입은 괄호 안의 어떤 문자(이스케이프 시퀀스까지 포함)와도 대응됩니다. 점(.) 이나 별표 (*) 같은 특수 문자는 문자셋 내부에서는 특수 문자가 아닙니다. 따라서 이스케이프시킬 필요가 없습니다. 하이픈을 이용하여 문자의 범위를 지정해줄 수 있습니다.
+
+ 예를 들어, 패턴 [a-d] 는 패턴 [abcd] 와 똑같이 동작하며, "brisket"의 'b' 에 일치하고, "city"의 'c' 에 일치합니다. 패턴 /[a-z.]+/ /[\w.]+/ 는 "test.i.ng" 전체 문자열이 일치합니다.
[^xyz] +

부정 문자셋(negated character set) 또는 보충 문자셋(complemented character set)입니다. 괄호 내부에 등장하지 않는 어떤 문자와도 대응됩니다. 하이픈을 이용하여 문자의 범위를 지정할 수 있습니다. 일반적인 문자셋에서 작동하는 모든 것은 여기에서도 작동합니다.

+ +

예를 들어, 패턴[^abc]는 패턴[^a-c]와 동일합니다. 두 패턴은 "brisket"의 'r', "chop."의 'h' 에 대응됩니다.

+
[\b]백스페이스(U+0008)에 대응됩니다. 이와 같이, 백스페이스 문자 리터럴에 대응시키려면, 대괄호("[]")를 이용해야만 합니다. (\b와 혼동하지 마세요.)
\b +

단어 경계에 대응됩니다. 단어 경계는 다른 '단어 문자'가 앞이나 뒤에 등장하지 않는 위치에 대응됩니다. 단어의 경계는 대응 결과에 포함되지 않는다는 사실에 주의하세요. 다른 말로는, 단어의 경계에 대응되는 문자열의 길이는 항상 0입니다. (패턴 [\b]와 혼동하지 마세요.)

+ +

예제:
+ /\bm/는 "moon"의 'm'에 대응됩니다;
+ /oo\b/ 는 "moon"의 'oo' 부분에 대응되지 않는데, 왜냐하면 'oo'를 뒤따라오는 'n'이 단어 문자이기 때문입니다;
+ /oon\b/는 "moon"의 'oon'에 대응됩니다. 왜냐하면, 'oon'은 문자열의 끝이라서, 뒤따라오는 단어 문자가 없기 때문입니다 ;
+ /\w\b\w/는 어떤 것에도 일치하지 않습니다. 왜냐하면, 단어 문자는 절대로 비 단어 문자와 단어 문자 두개가 뒤따라올수 없기 때문입니다.

+ +
+

숙지하세요: 자바스크립트의 정규식 엔진은 특정 문자 집합을 '단어 문자'로 정의합니다. 이 집단에 속하지 않는 모든 문자는 단어 분리(word break) 로 여겨집니다. 단어 문자로 간주되는 문자들은 얼마 없습니다: 오로지 로마자 소문자와 대문자, 10진수 숫자, 밑줄 문자로 구성되어 있습니다. "é" 또는 "ü" 같이, 강세 표시 문자들은 안타깝게도 단어 분리(word breaks) 로 취급됩니다.

+
+
\B +

단어 경계가 아닌 부분에 대응됩니다. 아래와 같은 경우들이 있습니다:

+ +
    +
  • 문자열의 첫 번째 문자가 단어 문자가 아닌 경우, 해당 문자의 앞 부분에 대응됩니다.
  • +
  • 문자열의 마지막 문자가 단어 문자가 아닌 경우, 해당 문자의 뒷 부분에 대응됩니다.
  • +
  • 두 단어 문자의 사이에 대응됩니다.
  • +
  • 단어 문자가 아닌 두 문자 사이에 대응됩니다.
  • +
  • 빈 문자열에 대응됩니다.
  • +
+ +

문자열의 시작 부분과 끝 부분은 단어가 아닌 것으로 간주됩니다.

+ +

예를 들어, /\B../ 는 "noonday"의 'oo'와 대응되며, /y\B./ 는 "possibly yesterday."의 'ye'와 대응됩니다.

+
\cX +

문자열 내부의 제어 문자에 대응됩니다. 여기서 X는 A에서 Z까지의 문자 중 하나입니다.

+ +

예를 들어, /\cM/는 문자열에서 control-M (U+000D)에 대응됩니다.

+
\d +

숫자 문자에 대응됩니다. [0-9]와 동일합니다.

+ +

예를 들어, /\d/ 또는 /[0-9]/는 "B2 is the suite number."에서 '2'에 대응됩니다.

+
\D +

숫자 문자가 아닌 문자에 대응됩니다. [^0-9]와 동일합니다.

+ +

예를 들어, /\D/ 또는 /[^0-9]/는 "B2 is the suite number."의 'B'에 대응됩니다.

+
\f폼피드 (U+000C) 문자에 대응됩니다.
\n줄 바꿈 (U+000A) 문자에 대응됩니다.
\r캐리지 리턴(U+000D) 문자에 대응됩니다.
\s +

스페이스, 탭, 폼피드, 줄 바꿈 문자등을 포함한 하나의 공백 문자에 대응됩니다. [ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff].와 동일합니다.

+ +

예를 들어, /\s\w*/는 "foo bar."의 ' bar'에 대응됩니다.

+
\S +

공백 문자가 아닌 하나의 문자에 대응됩니다. [^ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]. 와 동일합니다.

+ +

예를 들어, /\S\w*/는 "foo bar."의 'foo' 에 대응됩니다.

+
\t탭 (U+0009) 문자에 대응됩니다.
\v수직 탭(U+000B) 문자에 대응됩니다.
\w +

밑줄 문자를 포함한 영숫자 문자에 대응됩니다. [A-Za-z0-9_] 와 동일합니다. (역주: 여기에 대응되는 문자를 단어 문자라고 합니다.)

+ +

예를 들어, /\w/는 "apple,"의 'a' 에 대응되고, "$5.28,"의 '5'에 대응되고,"3D."의 '3'에 대응됩니다.

+
\W +

단어 문자가 아닌 문자에 대응됩니다. [^A-Za-z0-9_] 와 동일합니다.

+ +

예를 들어, /\W/ 또는 /[^A-Za-z0-9_]/는 "50%."의 '%' 에 대응됩니다.

+
\n +

정규식 내부의 n번째 괄호에서 대응된 부분에 대한 역참조 입니다. 여기서, n은 양의 정수입니다.

+ +

예를 들어, /apple(,)\sorange\1/는 "apple, orange, cherry, peach."의 'apple, orange,' 에 일치합니다.

+
\0널 (U+0000)문자에 대응합니다. 이 때 다른 숫자를 뒤에 쓰지 마세요. 왜냐하면 \0<digits>는 8진 이스케이프 시퀀스이기 때문입니다.
\xhh코드가 hh(두 16진 숫자)인 문자에 일치합니다.
\uhhhh코드가 hhhh(네개의 16진 숫자)인 문자에 일치합니다.
+ +

사용자 입력을 이스케이프해서 정규식 내부에서 문자 그대로 취급해야 하는 경우, 간단히 치환을 하면 됩니다:

+ +
function escapeRegExp(string){
+  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $&는 일치한 전체 문자열을 의미합니다.
+}
+ +

괄호를 사용하기

+ +

정규식 내부의 일부를 둘러싼 괄호는, 해당 부분에서 대응된 문자열을 기억하는 효과를 갖습니다. 기억된 문자열은 이후 {{ web.link("#.ED.8C.A8.ED.84.B4.ED.99.94.EB.90.9C_.EB.B6.80.EB.B6.84_.EB.AC.B8.EC.9E.90.EC.97.B4_.EC.9D.BC.EC.B9.98_.EC.82.AC.EC.9A.A9.ED.95.98.EA.B8.B0", "패턴화된 부분 문자열 일치 사용하기") }}에서 설명한 것처럼 다른 곳에서 사용하기 위하여 불러와질 수 있습니다.

+ +

예를 들면, 패턴 /Chapter (\d+)\.\d*/는 패턴의 일부분이 기억될 거라는 사실을 나타냅니다. 이 패턴은 하나 이상의 숫자(\d는 숫자를 의미하고 +는 1개 이상을 의미합니다.) 이후에 하나의 소숫점(\가 앞에 붙은 소숫점은 문자 그대로의 문자 '.' 에 대응됨을 나타냅니다), 그뒤 0개 이상의 숫자(\d 는 숫자, * 는 0개 이상을 의미합니다.)가 뒤따라오는 'Chapter ' 문자열에 대응됩니다. 더해서, 괄호는 처음으로 일치하는 숫자 문자들을 기억하기 위하여 사용되었습니다.

+ +

이 패턴은 "Open Chapter 4.3, paragraph 6"에 나타나며, '4'가 기억됩니다. 이 패턴은 "Chapter 3 and 4"에는 나타나지 않습니다. 왜냐하면 문자열이 '3'이후에 마침표를 가지고 있지 않기 때문입니다.

+ +

부분 문자열을 대응시키면서도 해당 부분을 기억하지 않으려면, 괄호의 첫머리에 ?:패턴을 사용하세요. 예를 들어, (?:\d+)는 1개 이상의 숫자에 대응되지만 해당 문자들을 기억하지 않습니다.

+ +

정규식 사용하기

+ +

정규식은 RegExp, test, exec, String, match, replace, search, split 메소드와 함께 쓰입니다. 이 메소드는 JavaScript reference에서 잘 설명되어 있습니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
정규식에서 쓰이는 메소드
MethodDescription
{{jsxref("RegExp.exec", "exec")}}대응되는 문자열을 찾는 RegExp 메소드입니다. 정보를 가지고 있는 배열을 반환합니다. 대응되는 문자열을 찾지 못했다면 null을 반환합니다.
{{jsxref("RegExp.test", "test")}}대응되는 문자열이 있는지 검사하는 RegExp 메소드 입니다. true 나 false를 반환합니다.
{{jsxref("String.match", "match")}}대응되는 문자열을 찾는 RegExp 메소드입니다. 정보를 가지고 있는 배열을 반환합니다. 대응되는 문자열을 찾지 못했다면 null을 반환합니다.
{{jsxref("String.search", "search")}} +

대응되는 문자열이 있는지 검사하는 String 메소드 입니다. 대응된 부분의 인덱스를 반환합니다. 대응되는 문자열을 찾지 못했다면 -1을 반환합니다.

+
{{jsxref("String.replace", "replace")}}대응되는 문자열을 찾아 다른 문자열로 치환하는 String 메소드입니다.
{{jsxref("String.split", "split")}}정규식 혹은 문자열로 대상 문자열을 나누어 배열로 반환하는 String 메소드입니다.
+ +

문자열 내부에 패턴과 대응되는 부분이 있는지 알고 싶다면, test 나 search 메소드를 사용하세요; 좀 더 많은 정보를 원하면 (대신 실행이 느림)  exec 나 match 메소드를 사용하세요. 만약 exec 나 match 메소드를 사용했는데 대응되는 부분이 있다면, 이 메소드는 배열을 반환하고 정규식 객체의 속성을 업데이트 합니다. 만약 대응되는 부분이 없다면, exec 메소드는 null 을 반환합니다. (즉, false와 같은 의미로 사용될 수 있습니다.).

+ +

아래의 예에서는, 문자열 내부에서 대응되는 부분을 찾기 위해 exec 메소드를 사용했습니다.

+ +
var myRe = /d(b+)d/g;
+var myArray = myRe.exec("cdbbdbsbz");
+
+ +

만약 정규식 속성에 접근할 필요가 없다면, 아래와 같이 myArray를 만드는 다른 방법도 있습니다:

+ +
var myArray = /d(b+)d/g.exec("cdbbdbsbz");
+
+ +

문자열로부터 정규식을 만들고 싶다면, 이런 방법도 있습니다:

+ +
var myRe = new RegExp("d(b+)d", "g");
+var myArray = myRe.exec("cdbbdbsbz");
+
+ +

위의 스크립트에서는, 대응되는 부분이 발견되었고 아래의 표에서 설명하는 대로 배열을 반환하며 속성을 갱신합니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
정규식 실행결과
ObjectProperty or indexDescriptionIn this example
myArray대응된 문자열 및 기억한 모든 부분 문자열['dbbd', 'bb', index: 1, input: 'cdbbdbsbz']
index입력된 문자열에서 대응된 부분에 해당하는 인덱스 (0부터 시작)1
input입력된 원본 문자열"cdbbdbsbz"
[0]마지막으로 대응된 문자열"dbbd"
myRelastIndex다음 검색 시 검색을 시작할 인덱스 (이 속성은 g 옵션을 설정한 정규식에 대해서만 설정됩니다. 자세한 사항은 {{ web.link("#Advanced_searching_with_flags", "Advanced Searching With Flags") }} 부분을 참고하세요.)5
source패턴 문자열. 정규식이 생성될 때 갱신됩니다. 실행 시점에는 갱신되지 않습니다."d(b+)d"
+ +

위 예제에서의 두 번째 형태처럼, 정규식 객체를 변수에 대입하지 않고도 사용할 수 있습니다. 하지만, 이렇게 하면 정규식 객체가 매번 새로 생성됩니다. 이러한 이유로, 만약 변수에 대입하지 않는 형태를 사용하는 경우 나중에 그 정규식의 속성에 접근할 수 없게 됩니다. 예를 들어, 이러한 스크립트가 있을 수 있습니다:

+ +
var myRe = /d(b+)d/g;
+var myArray = myRe.exec("cdbbdbsbz");
+console.log("The value of lastIndex is " + myRe.lastIndex);
+
+// "The value of lastIndex is 5"
+
+ +

그러나, 만약 이러한 스크립트가 있으면:

+ +
var myArray = /d(b+)d/g.exec("cdbbdbsbz");
+console.log("The value of lastIndex is " + /d(b+)d/g.lastIndex);
+
+// "The value of lastIndex is 0"
+
+ +

두 구문에서의 /d(b+)d/g 는 서로 다른  정규식 객체이고, 따라서 별개의 lastIndex 속성을 갖게 됩니다. 정규식 객체의 속성을 사용해야 하는 경우라면, 먼저 변수에 대입하세요.

+ +

괄호로 둘러싼 패턴 사용하기

+ +

정규식 패턴에 괄호를 사용하면, 그 부분을 별도로 대응시키면서 대응된 부분을 기억합니다. 예를 들면, /a(b)c/ 는 'abc' 와 대응되면서 'b'를 기억합니다. 괄호로 감싸진 문자열을 불러오려면, 배열 요소 [1], ..., [n] 를 사용하세요.

+ +

괄호로 감쌀 수 있는 문자의 개수에는 제한이 없습니다. 반환된 배열은 찾아낸 모든 것들을 갖고 있습니다. 다음의 예는 괄호로 둘러싸진 부분이 어떻게 대응되는지 보여줍니다.

+ +

다음의 예는 문자열 내부의 단어를 바꾸기 위해 {{jsxref("String.replace", "replace()")}} 메소드를 이용하고 있습니다. 치환 문자열로는 $1$2 를 사용하고 있는데, 이는 각각 첫 번째와 두 번째 괄호가 쳐진 부분에 대응된 문자열을 가리킵니다.

+ +
var re = /(\w+)\s(\w+)/;
+var str = "John Smith";
+var newstr = str.replace(re, "$2, $1");
+console.log(newstr);
+
+// "Smith, John"
+
+ +

플래그를 사용한 고급검색

+ +

정규식은 여섯 개의 플래그를 설정해줄 수 있으며, 이를 통해 전역 검색 또는 대소문자 구분 없는 검색을 수행할 수 있습니다. 이 플래그들은 각기 사용될 수도 있고 함께 사용될 수도 있고 순서에 구분이 없습니다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Regular expression flags
FlagDescription
g전역 검색
i대소문자 구분 없는 검색
m다중행(multi-line) 검색
s.에 개행 문자도 매칭(ES2018)
u유니코드; 패턴을 유니코드 코드 포인트의 나열로 취급합니다.
y"sticky" 검색을 수행. 문자열의 현재 위치부터 검색을 수행합니다. {{jsxref("RegExp.sticky", "sticky")}} 문서를 확인하세요.
+ +

정규식에 플래그를 포함시키려면, 아래 문법을 사용하세요:

+ +
var re = /pattern/flags;
+
+ +

혹은 아래와 같이 할 수도 있습니다:

+ +
var re = new RegExp("pattern", "flags");
+
+ +

이 플래그는 정규식에 합쳐지는 정보임을 기억하는게 좋습니다. 이것들은 나중에 추가되거나 제거될 수 없습니다.

+ +

예를 들어, re = /\w+\s/g 는 한 개 이상의 문자열 뒤에 공백이 하나 있는 패턴을 찾는 정규식을 생성합니다. 그리고 문자열 전체에 걸쳐 이 조합을 검색합니다.

+ +
var re = /\w+\s/g;
+var str = "fee fi fo fum";
+var myArray = str.match(re);
+console.log(myArray);
+
+// ["fee ", "fi ", "fo "]
+
+ +

아래 코드는:

+ +
var re = /\w+\s/g;
+
+ +

이렇게 바꿔쓸 수 있습니다:

+ +
var re = new RegExp("\\w+\\s", "g");
+
+ +

그리고 똑같은 결과를 얻습니다.

+ +

 .exec() 메소드를 사용할 때에는 'g' 플래그에 대한 동작이 다릅니다.  ("클래스"와 "인수"의 역할이 뒤바뀝니다:  .match()를 사용할 때는, string 클래스가 메소드를 갖고 정규식은 인수였던 것에 반해, .exec()를 사용할 때는 정규식이 메소드를 갖고 문자열이 인수가 됩니다. str.match(re) 과 re.exec(str)를 비교해보세요.)  'g' 플래그와  .exec() 메소드가 함께 사용되면 진행상황에 대한 정보가 반환됩니다.

+ +
var xArray; while(xArray = re.exec(str)) console.log(xArray);
+// 다음과 같이 출력됩니다:
+// ["fee ", index: 0, input: "fee fi fo fum"]
+// ["fi ", index: 4, input: "fee fi fo fum"]
+// ["fo ", index: 7, input: "fee fi fo fum"]
+ +

m 플래그는 여러 줄의 입력 문자열이 실제로 여러 줄로서 다뤄져야 하는 경우에 쓰입니다. 만약 m 플래그가 사용되면, ^$ 문자는 전체 문자열의 시작과 끝에 대응되는 것이 아니라 각 라인의 시작과 끝에 대응됩니다.

+ +

예시

+ +

다음의 예는 정규 표현식의 몇 가지 사용법을 보여줍니다.

+ +

입력 문자열에서 순서를 변경하기

+ +

다음 예는 정규식의 , string.split()과 string.replace()의 사용을 설명합니다. 그것은 공백, 탭과 정확히 하나의 세미콜론의 구분으로 이름(이름을 먼저)이 포함된 대략 형식의 입력 문자열을 정리합니다. 마지막으로, 순서(성을 먼저)를 뒤바꾸고 목록을 정렬합니다.

+ +
// The name string contains multiple spaces and tabs,
+// and may have multiple spaces between first and last names.
+var names = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ";
+
+var output = ["---------- Original String\n", names + "\n"];
+
+// Prepare two regular expression patterns and array storage.
+// Split the string into array elements.
+
+// pattern: possible white space then semicolon then possible white space
+var pattern = /\s*;\s*/;
+
+// Break the string into pieces separated by the pattern above and
+// store the pieces in an array called nameList
+var nameList = names.split(pattern);
+
+// new pattern: one or more characters then spaces then characters.
+// Use parentheses to "memorize" portions of the pattern.
+// The memorized portions are referred to later.
+pattern = /(\w+)\s+(\w+)/;
+
+// New array for holding names being processed.
+var bySurnameList = [];
+
+// Display the name array and populate the new array
+// with comma-separated names, last first.
+//
+// The replace method removes anything matching the pattern
+// and replaces it with the memorized string—second memorized portion
+// followed by comma space followed by first memorized portion.
+//
+// The variables $1 and $2 refer to the portions
+// memorized while matching the pattern.
+
+output.push("---------- After Split by Regular Expression");
+
+var i, len;
+for (i = 0, len = nameList.length; i < len; i++){
+  output.push(nameList[i]);
+  bySurnameList[i] = nameList[i].replace(pattern, "$2, $1");
+}
+
+// Display the new array.
+output.push("---------- Names Reversed");
+for (i = 0, len = bySurnameList.length; i < len; i++){
+  output.push(bySurnameList[i]);
+}
+
+// Sort by last name, then display the sorted array.
+bySurnameList.sort();
+output.push("---------- Sorted");
+for (i = 0, len = bySurnameList.length; i < len; i++){
+  output.push(bySurnameList[i]);
+}
+
+output.push("---------- End");
+
+console.log(output.join("\n"));
+
+ +

입력을 확인하기 위해 특수 문자를 사용하기

+ +

다음 예에서, 사용자는 전화번호를 입력 할 것으로 예상됩니다. 사용자가 "Check" 버튼을 누를 때, 스크립트는 번호의 유효성을 검사합니다. 번호가 유효한 경우(정규식에 의해 지정된 문자 시퀀스와 일치합니다), 스크립트는 사용자에게 감사하는 메시지와 번호를 확인하는 메시지를 나타냅니다. 번호가 유효하지 않은 경우, 스크립트는 전화번호가 유효하지 않다는 것을 사용자에게 알립니다.

+ +

비 캡처링 괄호 (?: , 정규식은 세 자리 숫자를 찾습니다 \d{3} OR | 왼쪽 괄호\( 세 자리 숫자 다음에 \d{3}, 닫는 괄호 다음에 \), (비 캡처링 괄호를 종료)) 안에, 하나의 대시, 슬래시, 또는 소수점을 다음과 같이 발견했을 때,  세 자리 숫자 다음에 d{3}, 대시의 기억 매치, 슬래시, 또는 소수점 다음에 \1, 네 자리 숫자 다음에 \d{4} 문자를 기억합니다([-\/\.]).

+ +

사용자가 <Enter> 키를 누를 때 활성화 변경 이벤트는 RegExp.input의 값을 설정합니다.

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+    <meta http-equiv="Content-Script-Type" content="text/javascript">
+    <script type="text/javascript">
+      var re = /(?:\d{3}|\(\d{3}\))([-\/\.])\d{3}\1\d{4}/;
+      function testInfo(phoneInput){
+        var OK = re.exec(phoneInput.value);
+        if (!OK)
+          window.alert(OK.input + " isn't a phone number with area code!");
+        else
+          window.alert("Thanks, your phone number is " + OK[0]);
+      }
+    </script>
+  </head>
+  <body>
+    <p>Enter your phone number (with area code) and then click "Check".
+        <br>The expected format is like ###-###-####.</p>
+    <form action="#">
+      <input id="phone"><button onclick="testInfo(document.getElementById('phone'));">Check</button>
+    </form>
+  </body>
+</html>
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Text_formatting", "Web/JavaScript/Guide/Indexed_collections")}}

diff --git "a/files/ko/web/javascript/guide/\355\225\250\354\210\230/index.html" "b/files/ko/web/javascript/guide/\355\225\250\354\210\230/index.html" new file mode 100644 index 0000000000..cf9d928eb3 --- /dev/null +++ "b/files/ko/web/javascript/guide/\355\225\250\354\210\230/index.html" @@ -0,0 +1,658 @@ +--- +title: 함수 +slug: Web/JavaScript/Guide/함수 +translation_of: Web/JavaScript/Guide/Functions +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}
+ +

함수는 JavaScript에서 기본적인 구성 블록 중의 하나입니다. 함수는 작업을 수행하거나 값을 계산하는 문장 집합 같은 자바스크립트 절차입니다. 함수를 사용하려면 함수를 호출하고자 하는 범위 내에서 함수를 정의해야만 합니다.

+ +

세부 사항에 대해서는 exhaustive reference chapter about JavaScript functions를 참조하세요.

+ +

함수 정의

+ +

함수 선언

+ +

함수 정의(또는 함수 선언)는 다음과 같은 함수 키워드로 구성되어 있습니다:

+ + + +

예를 들어, 다음의 코드는 square라는 간단한 함수를 정의하였습니다:

+ +
function square(number) {
+  return number * number;
+}
+ +

함수 squarenumber라는 하나의 매개변수를 가집니다. 이 함수는 인수 (즉, number) 자체를 곱하여 반환하는 하나의 문장으로 구성되어 있습니다. return 문은 함수에 의해 반환된 값을 지정합니다.

+ +
return number * number;
+ +

기본 자료형인 매개변수(number와 같은)는 값으로 함수에 전달됩니다; 즉, 값이 함수로 전달됩니다. 그러나 함수가 매개변수의 값을 바꾸더라도 이는 전역적으로 또는 함수를 호출하는 곳에는 반영되지 않습니다.

+ +

만약 여러분이 매개변수로 (예: {{jsxref("Array")}}이나 사용자가 정의한 객체와 같이 기본 자료형이 아닌 경우)를 전달하거나 함수가 객체의 속성을 변하게 하는 경우, 다음의 예처럼 그 변화는 함수 외부에서 볼 수 있습니다:

+ +
function myFunc(theObject) {
+  theObject.make = "Toyota";
+}
+
+var mycar = {make: "Honda", model: "Accord", year: 1998};
+var x, y;
+
+x = mycar.make; // x 의 값은 "Honda" 입니다.
+
+myFunc(mycar);
+y = mycar.make; // y 의 값은 "Toyota" 입니다.
+                // (make 속성은 myFunc에서 변경되었습니다.)
+
+ +

함수 표현식

+ +

위에서 함수 선언은 구문적인 문(statement)이지만, 함수 표현식( function expression)에 의해서 함수가 만들어 질 수도 있습니다. 이 같은 함수를 익명이라고 합니다. 이 말은 모든 함수가 이름을 가질 필요는 없다는 것을 뜻합니다. 예를 들어, 함수 square은 다음과 같이 정의 될 수도 있습니다:

+ +
var square = function(number) { return number * number };
+var x = square(4) // x 의 값은 16 입니다.
+ +

하지만, 함수 표현식에서 함수의 이름을 지정 할 수 있으며, 함수내에서 자신을 참조하는데 사용되거나, 디버거 내 스택 추적에서 함수를 식별하는 데 사용될 수 있습니다.

+ +
var factorial = function fac(n) { return n<2 ? 1 : n*fac(n-1) };
+
+console.log(factorial(3));
+
+ +

함수 표현식은 함수를 다른 함수의 매개변수로 전달할 때 편리합니다. 다음 예는 첫 번째 인자로로 함수를, 두 번째 인자로 배열을 받는 map 함수를 보여줍니다.

+ +
function map(f,a) {
+  var result = [], // Create a new Array
+      i;
+  for (i = 0; i != a.length; i++)
+    result[i] = f(a[i]);
+  return result;
+}
+
+ +

다음 코드에서, 함수 표현식으로 정의된 함수를 인자로 받아, 2번 째 인자인 배열의 모든 요소에 대해 그 함수를 실행합니다.

+ +
function map(f, a) {
+  var result = []; // Create a new Array
+  var i; // Declare variable
+  for (i = 0; i != a.length; i++)
+    result[i] = f(a[i]);
+      return result;
+}
+var f = function(x) {
+   return x * x * x;
+}
+var numbers = [0, 1, 2, 5, 10];
+var cube = map(f,numbers);
+console.log(cube);
+ +

함수는 [0, 1, 8, 125, 1000] 을 반환합니다.

+ +

JavaScript에서 함수는 조건에 의해 정의될 수 있습니다. 예를 들어, 다음 함수 정의는 오직 num이 0일 때 경우에 만 myFunc을 정의합니다.

+ +
var myFunc;
+if (num == 0){
+  myFunc = function(theObject) {
+    theObject.make = "Toyota"
+  }
+}
+ +

여기에 기술된 바와 같이 함수를 정의하는것에 더하여 {{jsxref("eval", "eval()")}} 과 같이 런타임에 문자열에서 함수들을 만들기위해 {{jsxref("Function")}} 생성자를 사용할 수 있습니다.

+ +

객체내의 한 속성이 함수인 경우 메서드라고 합니다. Working with objects에서 객체와 방법에 대해 자세히 알아보세요.

+ +

함수 호출

+ +

함수를 정의하는 것은 함수를 실행하는 것이 아닙니다. 함수를 정의하는 것은 간단히 함수의 이름을 지어주고, 함수가 호출될 때 무엇을 할지 지정 해주는 것입니다. 사실 함수를 호출하는 것은 나타나있는 매개변수를 가지고 지정된 행위를 수행하는 것입니다. 예를 들어, 만약 여러분이 함수 square를 정의한다면, 함수를 다음과 같이 호출할 수 있습니다.

+ +
square(5);
+
+ +

위의 문장은 5라는 인수를 가지고 함수를 호출합니다. 함수는 이 함수의 실행문을 실행하고 값 25를 반환합니다.

+ +

함수는 호출될 때 범위 내에 있어야 합니다. 그러나 함수의 선언은 이 예에서와 같이, 호이스팅 될 수 있습니다. (코드에서 호출 아래에 선언문이 있습니다.):

+ +
console.log(square(5));
+/* ... */
+function square(n) { return n*n }
+
+ +

함수의 범위는 함수가 선언된 곳이거나, 전체 프로그램 에서의 최상위 레벨(전역)에 선언된 곳입니다.

+ +
+

비고: 위에 구문을 사용하여 함수를 정의하는 경우에만 작동합니다 (즉, function funcName(){} ). 아래와 같은 코드는 작동되지 않습니다. 이것이 의미하는 바는, 함수 호이스팅은 오직 함수 선언과 함께 작동하고, 함수 표현식에서는 동작하지 않습니다.

+
+ +
console.log(square);   // square는 초기값으로 undefined를 가지고 호이스트된다.
+console.log(square(5));  // TypeError: square는 함수가 아니다.
+square = function (n) {
+  return n * n;
+}
+
+ +

함수의 인수는 문자열과 숫자에 제한되지 않습니다. 여러분은 함수에 전체 객체를 전달할 수 있습니다. show_props() 함수(Working with objects에서 정의된)는 인수로 객체를 취하는 함수의 예입니다.

+ +

함수는 자신을 호출할 수 있습니다. 예를 들어, 팩토리얼을 재귀적으로 계산하는 함수가 있습니다:

+ +
function factorial(n){
+  if ((n == 0) || (n == 1))
+    return 1;
+  else
+    return (n * factorial(n - 1));
+}
+
+ +

여러분은 다음과 같이 1부터 5까지의 팩토리얼을 계산할 수 있습니다.

+ +
var a, b, c, d, e;
+a = factorial(1); // a gets the value 1
+b = factorial(2); // b gets the value 2
+c = factorial(3); // c gets the value 6
+d = factorial(4); // d gets the value 24
+e = factorial(5); // e gets the value 120
+
+ +

함수를 호출하는 다른 방법들이 있습니다. 함수를 동적 호출해야 하거나, 함수의 인수의 수가 달라져야 하거나, 함수 호출의 맥락이 런타임에서 결정된 특정한 객체로 설정될 필요가 있는 경우가 자주 있습니다. 함수가 그 자체로 객체이고 이들 객체는 차례로 메서드를({{jsxref("Function")}} 객체를 참조) 가지고 있습니다. 이들 중 하나인 {{jsxref("Function.apply", "apply()")}} 메서드는 이러한 목표를 달성하기 위해 사용될 수 있습니다.

+ +

함수의 범위

+ +

함수 내에서 정의된 변수는 변수가 함수의 범위에서만 정의되어 있기 때문에, 함수 외부의 어느 곳에서든 액세스할 수 없습니다. 그러나, 함수가 정의된 범위 내에서 정의된 모든 변수나 함수는 액세스할 수 있습니다. 즉, 전역함수는 모든 전역 변수를 액세스할 수 있습니다. 다른 함수 내에서 정의 된 함수는 부모 함수와 부모 함수가 액세스 할 수 있는 다른 변수에 정의된 모든 변수를 액세스할 수 있습니다.

+ +
// The following variables are defined in the global scope
+var num1 = 20,
+    num2 = 3,
+    name = "Chamahk";
+
+// This function is defined in the global scope
+function multiply() {
+  return num1 * num2;
+}
+
+multiply(); // Returns 60
+
+// A nested function example
+function getScore () {
+  var num1 = 2,
+      num2 = 3;
+
+  function add() {
+    return name + " scored " + (num1 + num2);
+  }
+
+  return add();
+}
+
+getScore(); // Returns "Chamahk scored 5"
+
+ +

범위와 함수 스택

+ +

재귀

+ +

함수는 자신을 참조하고 호출할 수 있습니다. 함수가 자신을 참조하는 방법은 세 가지가 있습니다.

+ +
    +
  1. 함수의 이름
  2. +
  3. arguments.callee
  4. +
  5. 함수를 참조하는 범위 내 변수
  6. +
+ +

예를 들어, 다음 함수의 정의를 고려해보세요.

+ +
var foo = function bar() {
+   // statements go here
+};
+
+ +

함수 본문 내에서 다음은 모두 동일합니다.

+ +
    +
  1. bar()
  2. +
  3. arguments.callee()
  4. +
  5. foo()
  6. +
+ +

자신을 호출하는 함수를 재귀 함수라고 합니다. 어떤 면에서, 재귀는 루프와 유사합니다. 둘 다 동일한 코드를 여러 번 실행하고, 조건(무한 루프를 방지하거나, 이 경우에는 오히려 무한 재귀하는)을 요구합니다. 예를 들어, 다음 루프는:

+ +
var x = 0;
+while (x < 10) { // "x < 10" is the loop condition
+   // do stuff
+   x++;
+}
+
+ +

아래와 같이 재귀 함수와 그 함수에 대한 호출로 변환될 수 있습니다.

+ +
function loop(x) {
+  if (x >= 10) // "x >= 10" 는 탈출 조건 ("!(x < 10)"와 동등)
+    return;
+  // do stuff
+  loop(x + 1); // the recursive call
+}
+loop(0);
+
+ +

그러나 일부 알고리즘은 단순 재귀 루프로 변환할 수 없습니다. 예를 들어, 트리 구조(가령, DOM)의 모든 노드를 얻는 것은 재귀를 사용하여 보다 쉽게 할 수 있습니다:

+ +
function walkTree(node) {
+  if (node == null) //
+    return;
+  // do something with node
+  for (var i = 0; i < node.childNodes.length; i++) {
+    walkTree(node.childNodes[i]);
+  }
+}
+
+ +

함수  loop 와 비교하여, 각 재귀 호출 자체는 여기에 많은 재귀 호출을 만듭니다.

+ +

재귀적 알고리즘은 비 재귀적인 알고리즘으로 변환 할 수 있습니다. 그러나 변환된 알고리즘이 훨씬 더 복잡하며 그렇게 함으로써 스택의 사용을 요구합니다. 사실, 재귀 자체가 함수 스택을 사용 합니다.

+ +

스택형 동작은 다음의 예에서 볼 수 있습니다:

+ +
function foo(i) {
+  if (i < 0)
+    return;
+  console.log('begin:' + i);
+  foo(i - 1);
+  console.log('end:' + i);
+}
+foo(3);
+
+// Output:
+
+// begin:3
+// begin:2
+// begin:1
+// begin:0
+// end:0
+// end:1
+// end:2
+// end:3
+ +

중첩된 함수와 클로저

+ +

여러분은 함수 내에 함수를 끼워 넣을 수 있습니다. 중첩 된 (내부) 함수는 그것을 포함하는 (외부) 함수와 별개입니다. 그것은 또한 클로저를 형성합니다. 클로저는 그 변수(“폐쇄”라는 표현)를 결합하는 환경을 자유롭게 변수와 함께 가질 수 있는 표현(전형적인 함수)입니다.

+ +

중첩 함수는 클로저이므로, 중첩된 함수는 그것을 포함하는 함수의 인수와 변수를 “상속”할 수 있는 것을 의미합니다. 즉, 내부 함수는 외부 함수의 범위를 포함합니다.

+ +

요약하면:

+ + + + + +

다음 예는 중첩된 함수를 보여줍니다:

+ +
function addSquares(a,b) {
+  function square(x) {
+    return x * x;
+  }
+  return square(a) + square(b);
+}
+a = addSquares(2,3); // returns 13
+b = addSquares(3,4); // returns 25
+c = addSquares(4,5); // returns 41
+
+ +

내부 함수는 클로저를 형성하기 때문에, 여러분은 외부 함수를 호출하고, 외부 및 내부 함수 모두에 인수를 지정할 수 있습니다.

+ +
function outside(x) {
+  function inside(y) {
+    return x + y;
+  }
+  return inside;
+}
+fn_inside = outside(3); // Think of it like: give me a function that adds 3 to whatever you give it
+result = fn_inside(5); // returns 8
+
+result1 = outside(3)(5); // returns 8
+
+ +

변수의 보존

+ +

중첩된 내부 함수가 반환될 때 외부 함수의 인수 x가 보존된다는 점을 알 수 있습니다. 클로저는 그것을 참조하는 모든 범위에서 인수와 변수를 보존해두어야 합니다. 매번 호출될 때마다 잠재적으로 다른 인수를 제공할 수 있기 때문에, 클로저는 외부 함수에 대하여 매번 새로 생성됩니다. 메모리는 그 무엇도 내부 함수에 접근하지 않을 때만 해제됩니다.

+ +

변수의 보존은 일반 객체에서 참조를 저장해두는 것과 다르지 않지만, 사용자가 직접 참조를 설정하는 것이 아니고 자세히 들여다볼 수 없어서 종종 명확하지 않습니다.

+ +

다중 중첩 함수

+ +

함수는 다중 중첩될 수 있습니다. 즉, 함수 (C)를 포함하는 함수 (B)를 포함하는 함수 (A). 여기에서 두 함수 B와 C는 모두 클로저를 형성합니다. 그래서 B는 A를 엑세스할 수 있고, C는 B를 액세스 할 수 있습니다. 이와 같이, 클로저는 다중 범위를 포함 할 수 있습니다; 그들은 재귀적으로 그것을 포함하는 함수의 범위를 포함합니다. 이것을 범위 체이닝이라 합니다.(그것을 “체이닝”이라 하는 이유는 추후에 설명할 것입니다.)

+ +

다음 예를 살펴 보겠습니다:

+ +
function A(x) {
+  function B(y) {
+    function C(z) {
+      console.log(x + y + z);
+    }
+    C(3);
+  }
+  B(2);
+}
+A(1); // logs 6 (1 + 2 + 3)
+
+ +

이 예에서, C는 B의 y와 A의 x를 엑세스 합니다. 이 때문에 수행할 수 있습니다:

+ +
    +
  1. B는 A를 포함하는 클로저를 형성합니다. 즉, B는 A의 인수와 변수를 엑세스할 수 있습니다.
  2. +
  3. C는 B를 포함하는 클로저를 형성합니다.
  4. +
  5. B의 클로저는 A를 포함하고, C의 클로저는 A를 포함하기 때문에, C는 B와 A의 인수와 변수를 엑세스할 수 있습니다. 즉, 순서대로 C는 A와 B의 범위를 체이닝합니다.
  6. +
+ +

그러나 역은 사실이 아닙니다. A는 C에 접근 할 수 없습니다. 왜냐하면 A는 B의 인수와 변수(C는 B변수)에 접근할수 없기 때문입니다. 그래서 C는 B에게만 사적으로 남게됩니다.

+ +

이름 충돌

+ +

클로저의 범위에서 두 개의 인수 또는 변수의 이름이 같은 경우, 이름 충돌이 있습니다. 더 안쪽 범위가 우선순위를 갖습니다. 그래서 가장 바깥 범위는 우선순위가 가장 낮은 반면에, 가장 안쪽 범위는 가장 높은 우선순위를 갖습니다. 이것이 범위 체인(scope chaini)입니다. 체인에서 첫번째는 가장 안쪽 범위이고, 마지막 가장 바깥 쪽의 범위입니다. 다음 사항을 고려하세요:

+ +
function outside() {
+  var x = 10;
+  function inside(x) {
+    return x;
+  }
+  return inside;
+}
+result = outside()(20); // returns 20 instead of 10
+
+ +

이름 충돌이 x를 반환하는 문과 내부의 매개 변수 x와 외부 변수 x 사이에서 발생합니다. 여기에서 범위 체이닝은 {내부, 외부, 전역 객체}입니다. 따라서 내부의 x는 외부의 x보다 높은 우선순위를 갖게 되고, 20(내부의 x)이 10(외부의 x) 대신에 반환됩니다.

+ +

클로저

+ +

클로저는 자바스크립트의 강력한 기능 중 하나입니다. 자바스크립트는 함수의 중첩(함수 안에 함수를 정의하는것)을 허용하고, 내부함수가 외부 함수 안에서 정의된 모든 변수와 함수들을 완전하게 접근 할 수 있도록 승인해줍니다.(그리고 외부함수가 접근할수 있는 모든 다른 변수와 함수들까지) 그러나 외부 함수는 내부 함수 안에서 정의된 변수와 함수들에 접근 할 수 없습니다. 이는 내부 함수의 변수에 대한 일종의 캡슐화를 제공합니다. 또한, 내부함수는 외부함수의 범위에 접근할 수 있기 때문에, 내부 함수가 외부 함수의 수명을 초과하여 생존하는 경우, 외부함수에서 선언된 변수나 함수는 외부함수의 실행 기간보다 오래갑니다. 클로저는 내부 함수가 어떻게든 외부 함수 범위 밖의 모든 범위에서 사용 가능해지면 생성됩니다.

+ +
var pet = function(name) {   // 외부 함수는 'name'이라 불리는 변수를 정의합니다.
+  var getName = function() {
+    return name;             // 내부 함수는 외부 함수의 'name' 변수에 접근합니다.
+  }
+  return getName;            // 내부 함수를 리턴함으로써, 외부 범위에 노출됩니다.
+},
+myPet = pet("Vivie");
+
+myPet();                     // "Vivie"로 리턴합니다.
+
+ +

클로저는 위 코드보다 더 복잡해 질 수도 있습니다. 외부 함수의 내부 변수를 다루는 메서드를 포함한 객체도 반환될 수도 있습니다.

+ +
var createPet = function(name) {
+  var sex;
+
+  return {
+    setName: function(newName) {
+      name = newName;
+    },
+
+    getName: function() {
+      return name;
+    },
+
+    getSex: function() {
+      return sex;
+    },
+
+    setSex: function(newSex) {
+      if(typeof newSex == "string" && (newSex.toLowerCase() == "male" || newSex.toLowerCase() == "female")) {
+        sex = newSex;
+      }
+    }
+  }
+}
+
+var pet = createPet("Vivie");
+pet.getName();                  // Vivie
+
+pet.setName("Oliver");
+pet.setSex("male");
+pet.getSex();                   // male
+pet.getName();                  // Oliver
+
+ +

위 코드에서, 외부 함수의 'name' 이란 변수는 내부 함수에서 접근이 가능합니다. 그리고 그 내장 함수를 통하는 방법 말고는 내부 변수로 접근할 수 없습니다. 내부 함수의 내부 변수는 외부 인수와 변수를 안전하게 저장합니다. 내부 변수는 내부 함수가 작동하기 위해 '지속적'이고 '갭슐화된' 데이터를 보유합니다. 함수는 변수로 할당되거나, 이름을 가질 필요가 없습니다.

+ +
var getCode = (function(){
+  var secureCode = "0]Eal(eh&2";    // A code we do not want outsiders to be able to modify...
+
+  return function () {
+    return secureCode;
+  };
+})();
+
+getCode();    // Returns the secureCode
+
+ +

그러나 클로저를 쓰면서 조심해야 할 위험이 많이 있습니다. 만약 내부 함수가 외부 함수의 범위에 있는 이름과 같은 변수를 정의하였을 경우, 다시는 외부 함수 범위의 변수를 참조(접근)할 방법이 없습니다.

+ +
var createPet = function(name) {  // 외부 함수가 "name" 이라는 변수를 정의하였다
+  return {
+    setName: function(name) {    // 내부 함수 또한 "name" 이라는 변수를 정의하였다
+      name = name;               // ??? 어떻게 우리는 외부 함수에 정의된 "name"에 접근할까???
+    }
+  }
+}
+
+ +

인수(arguments) 객체 사용하기

+ +

함수의 인수는 배열과 비슷한 객체로 처리가 됩니다. 함수 내에서는, 전달 된 인수를 다음과 같이 다룰 수 있습니다. :

+ +
arguments[i]
+
+ +

i 는 0 으로 시작하는 순서 번호입니다. 따라서 함수에 전달된 첫 번째 인수는 arguments[0] 입니다. 총 인수의 개수는 arguments.length 에서 얻을 수 있습니다.

+ +

인수(arguments) 객체를 이용하면, 보통 함수에 정의된 개수보다 많은 인수를 넘겨주면서 함수를 호출할 수 있습니다. 이것은 얼마나 많은 인수가 함수로 넘겨질지 모르는 상황에서 유용합니다. arguments.length를 함수에 실제로 넘겨받은 인수의 수를 알아낼 때 사용할 수 있고 , 각각의 인수에 인수(arguments) 객체를  이용하여 접근 할 수 있습니다.

+ +

예를 들어, 몇 개의 문자열을 연결하는 함수를 생각해 봅시다. 이 함수의 유일한 형식 인수는 각 문자열을 구분해주는 문자를 나타내는 문자열입니다 . 이 함수는 다음과 같이 정의됩니다:

+ +
function myConcat(separator) {
+   var result = ""; // 리스트를 초기화한다
+   var i;
+   // arguments를 이용하여 반복한다
+   for (i = 1; i < arguments.length; i++) {
+      result += arguments[i] + separator;
+   }
+   return result;
+}
+
+ +

어떤 개수의 인수도 이 함수로 넘겨줄 수 있고, 이 함수는 각각의 인수를 하나의 문자열 "리스트" 로 연결합니다. :

+ +
// returns "red, orange, blue, "
+myConcat(", ", "red", "orange", "blue");
+
+// returns "elephant; giraffe; lion; cheetah; "
+myConcat("; ", "elephant", "giraffe", "lion", "cheetah");
+
+// returns "sage. basil. oregano. pepper. parsley. "
+myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
+
+ +
+

Note: 인수(arguments) 객체는 배열과 닮은 것이지 배열이 아닙니다. 인수(arguments) 객체는 번호 붙여진 인덱스와 길이 속성을 가지고 있다는 점에서 배열과 닮은 것입니다. 인수(arguments) 객체는 배열을 다루는 모든 메서드를 가지고 있지 않습니다.

+
+ +

더 자세한 정보를 얻고 싶으면 자바스크립트 참조문의 {{jsxref("Function")}}객체에 대하여 보세요.

+ +

함수의 매개변수

+ +

 ECMAScript 2015와 함께 시작된,두 종류의 매개변수가 있습니다 : 디폴트 매개변수 , 나머지 매개변수.

+ +

디폴트 매개변수

+ +

자바스크립트에서, 함수의 매개변수는 undefined 가 기본으로 설정됩니다. 그러나, 어떤 상황에서는 다른 값을 기본값으로 가진 것이 유용할 때가 있습니다. 이때가 디폴트 매개변수가 도움을 줄 수 있는 상황입니다.

+ +

옛날엔, 기본값을 설정하는 보편적인 전략은 함수의 본문에서 매개변수 값을 테스트하여 그 값이 undefined 인 경우에 값을 할당하는 것이었습니다. 다음과 같은 예제에서, 함수호출 시 b 매개변수에 아무 값을 주지 않으면, a*b 계산 시 b 매개변수의 값은 undefined 일 것이므로 multiply 함수 호출은 NaN을 리턴할 것입니다. 그러나 이런 것은 이 예제의 2번째 줄에서 걸립니다:

+ +
function multiply(a, b) {
+  b = typeof b !== 'undefined' ?  b : 1;
+
+  return a*b;
+}
+
+multiply(5); // 5
+
+ +

디폴트 매개변수와 함께라면, 함수 본문에서 검사하는 부분은 필요가 없습니다. 이제 , 함수 머리에서 b 의 기본값에 간단히 1을 넣어주면 됩니다:

+ +
function multiply(a, b = 1) {
+  return a*b;
+}
+
+multiply(5); // 5
+ +

더 자세한 내용을 보고 싶으시면,  default parameters 문서를 참조하세요.

+ +

나머지 매개변수

+ +

 나머지 매개변수 구문을 사용하면 배열로 불확실한 개수의 인수를 나타낼 수 있습니다. 이 예제에서, 우리는 나머지 매개변수를 2번째 인수부터 마지막 인수까지 얻기 위하여 사용하였습니다. 그리고 우리는 첫번째 값으로 나머지 매개변수에 곱하였습니다. 이 예제는 다음 섹션에서 소개할  화살표(arrow) 함수 입니다.

+ +
function multiply(multiplier, ...theArgs) {
+  return theArgs.map(x => multiplier * x);
+}
+
+var arr = multiply(2, 1, 2, 3);
+console.log(arr); // [2, 4, 6]
+ +

화살표 함수

+ +

 화살표 함수 표현 (뚱뚱한 화살표(fat arrow) 함수라고 알려진)은 함수 표현과 비교하였을때 짧은 문법을 가지고 있고 사전적으로 this 값을 묶습니다. 화살표 함수는 언제나 익명입니다. hacks.mozilla.org 블로그 포스트 "ES6 In Depth: Arrow functions" 를 참조하세요.

+ +

화살표  함수 소개에 영향을 주는 두 요소: 더 짧은 함수와 바인딩 되지않은 this.

+ +

더 짧은 함수

+ +

어떤 함수적 패턴에서는, 더 짧은 함수가 환영받습니다. 다음을 비교해 보세요:

+ +
var a = [
+  "Hydrogen",
+  "Helium",
+  "Lithium",
+  "Beryl­lium"
+];
+
+var a2 = a.map(function(s){ return s.length });
+
+console.log(a2); // logs [8, 6, 7, 9]
+
+var a3 = a.map( s => s.length );
+
+console.log(a3); // logs [8, 6, 7, 9]
+ +

사전적 this

+ +

화살표 함수에서, 모든 new함수들은  그들의  this 값을 정의합니다 (생성자로서의 새로운 객체, 정의되지 않은 strict mode의 함수 호출,   함수가 "object method"로 호출했을때의 context object ,등등.). 이런 것은 객체지향 프로그래밍 스타일에서 짜증을 불러 일으킵니다.

+ +
function Person() {
+  // The Person() constructor defines `this` as itself.
+  this.age = 0;
+
+  setInterval(function growUp() {
+    // In nonstrict mode, the growUp() function defines `this`
+    // as the global object, which is different from the `this`
+    // defined by the Person() constructor.
+    this.age++;
+  }, 1000);
+}
+
+var p = new Person();
+ +

IECMAScript 3/5 에서는, 이 문제는 this 안의 값을 뒤덮을 수 있는변수에 할당하면서 고쳐졌습니다.

+ +
function Person() {
+  var self = this; // Some choose `that` instead of `self`.
+                   // Choose one and be consistent.
+  self.age = 0;
+
+  setInterval(function growUp() {
+    // The callback refers to the `self` variable of which
+    // the value is the expected object.
+    self.age++;
+  }, 1000);
+}
+ +

또는, 적절한 this 값이 growUp() 함수에 전달되도록, 바인딩된 함수가 생성될 수 있습니다.

+ + + +

화살표 함수에는 this;가 없습니다. 화살표 함수를 포함하는 객체 값이 사용됩니다. 따라서 다음 코드에서 setInterval에 전달 된 함수 내의 this 값은 화살표 함수를 둘러싼 함수의 this와 같은 값을 갖습니다.

+ +
function Person() {
+  this.age = 0;
+
+  setInterval(() => {
+    this.age++; // |this| properly refers to the person object
+  }, 1000);
+}
+
+var p = new Person();
+ +

미리 정의된 함수들

+ +

자바스크립트에는 최고 등급의 몇가지 내장함수가 있습니다:

+ +
+
{{jsxref("Global_Objects/eval", "eval()")}}
+
+

eval() 메소드는 문자열로 표현된 자바스크립트 코드를 수행합니다.

+
+
{{jsxref("Global_Objects/uneval", "uneval()")}} {{non-standard_inline}}
+
+

uneval() 메소드는  {{jsxref("Object")}}의 소스코드를 표현하는 문자열을 만듭니다.

+
+
{{jsxref("Global_Objects/isFinite", "isFinite()")}}
+
+

전역 isFinite() 함수는 전달받은 값이 유한한지 결정합니다. 만약 필요하다면, 매개변수는 첫번째로 숫자로 변환됩니다.

+
+
{{jsxref("Global_Objects/isNaN", "isNaN()")}}
+
+

isNaN() 함수는 {{jsxref("Global_Objects/NaN", "NaN")}}인지 아닌지 결정합니다. Note:  isNaN 함수 안의 강제 변환은  흥미로운 규칙을 가지고 있습니다;  {{jsxref("Number.isNaN()")}}을 대신 사용하고 싶을것입니다, ECMAScript 6 에서 정의된,또는 값이 숫자값이 아닐때,  typeof 를 사용할 수도 있습니다 .

+
+
{{jsxref("Global_Objects/parseFloat", "parseFloat()")}}
+
+

parseFloat() 함수는  문자열 인수 값을 해석하여 부동소숫점 수를 반환합니다.

+
+
{{jsxref("Global_Objects/parseInt", "parseInt()")}}
+
+

parseInt() 함수는 문자열 인수 값을 해석하여 특정한 진법의 정수를 반환합니다  (수학적 수 체계를 기반으로 해서).

+
+
{{jsxref("Global_Objects/decodeURI", "decodeURI()")}}
+
+

decodeURI() 함수는  사전에 {{jsxref("Global_Objects/encodeURI", "encodeURI")}}을 통해 만들어지거나 비슷한 과정을 통해 만들어진 URI(Uniform Resource Identifier)  를 해독합니다.

+
+
{{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent()")}}
+
+

decodeURIComponent() 메소드는 사전에{{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}}를 통하여 만들어 지거나 또는 비슷한 과정을 통해 만들어진 URI (Uniform Resource Identifier) 컴포넌트를 해독합니다.

+
+
{{jsxref("Global_Objects/encodeURI", "encodeURI()")}}
+
+

encodeURI() 메소드는  URI(Uniform Resource Identifier)를  각 인스턴스의 특정한 문자를 한개, 두개,세개, 또는 네개의 UTF-8인코딩으로 나타내어지는 연속된 확장문자들과 바꾸는 방법으로 부호화 합니다 .(두"surrogate"문자로 구성된 문자들은 오직 네개의 연속된 확장문자 입니다. ).

+
+
{{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}}
+
+

encodeURIComponent() 메소드는  URI(Uniform Resource Identifier) 컴포넌트를  각 인스턴스의 특정한 문자를 한개, 두개,세개, 또는 네개의 UTF-8인코딩으로 나타내어지는 연속된 확장문자들과 바꾸는 방법으로 부호화 합니다 .(두"surrogate"문자로 구성된 문자들은 오직 네개의 연속된 확장문자 입니다. ).).

+
+
{{jsxref("Global_Objects/escape", "escape()")}} {{deprecated_inline}}
+
+

곧 사라질 escape() 메소드는 한 문자열에서 특정 문자들이 16진 확장 비트열로 바뀌어진 문자열로 계산합니다.  {{jsxref("Global_Objects/encodeURI", "encodeURI")}} 또는 {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} 를 사용하세요.

+
+
{{jsxref("Global_Objects/unescape", "unescape()")}} {{deprecated_inline}}
+
+

곧 사라질 unescape() 메소드는 문자열에서 확장 비트열이 확장 비트열이 나타내는 문자로 바뀌어진 문자열로 계산합니다.  {{jsxref("Global_Objects/escape", "escape")}}에서 확장 비트열이 소개될 것입니다.  unescape() 메소드가 곧 사라지기 때문에,  {{jsxref("Global_Objects/decodeURI", "decodeURI()")}} or {{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent")}} 를 대신 사용하세요.

+
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}

+ + + + -- cgit v1.2.3-54-g00ecf