The Complete JavaScript Handbook
JavaScript는 세상에서 가장 인기있는 프로그램언어중 하나이고, 현재 브라우저외에도 널리 사용되고 있다. 최근 몇년 사이에 Node.js가 뜨면서 Java, Ruby, Python, PHP 및 보다 전통적인 서버측 언어의 영역있었던 백 엔드 개발영역까지 확장하였다. JavaScript요약집은 80/20룰을 따른다. 시간의 20%안에 자바스크립트의 80%를 배운다. JavaScript의 모든 것을 배워라!
내용목록
자바스크립트는 세상에 가장인기있는 프로그래밍언어중하나다. 20년전에 만들어졌고, 초라한시작부터 아주 먼 길을 왔다. 처음이자 웹브라우저에서 기본적으로 지원되는 유일한 스크립팅 언어였으므로, 단순한 것이었다. 초기에는 거의 오늘날과 같이 강력하지 않았으며, 주로 동적인 HTML(DHTML)로 알려진 멋진 애니메이션과 경이로움에 주로 사용되었다. 웹플랫폼이 요구하는 요구 사항이 증가함에 따라 자바스크립트는 세계에서 가장 널리 사용되는 생태계 중 하나의 요구사항을 수용하기 위해 성장할 책임이 있었다. 브라우저 APIs함께 플랫폼에 많은 것들이 도입되었고, , 그러나 언어도 상당히 많이 성장했다. JavaScript는 현재 브라우저 밖에서도 널리 사용되고 있다.지난 몇년 동안 Node.js의 부상은 Java, Ruby, Python, PHP 및보다 전통적인 서버 측 언어의 도메인이었던 백 엔드 개발영역까지 확장하였다. JavaScript는 이제 언어 파워 데이터베이스와 더 많은 애플리케이션이기도 하다. 임베디드 애플리케이션, 모바일 앱, TV 세트 앱 등을 개발하는 것도 가능하다.브라우저 안에서 작은 언어로 시작된 것이 이제 세계에서 가장 인기 있는 언어가 되었다.
자바스크립라는 아래 기술된 프로그램언어이다.
혹시 궁금하실지 모르겠지만, 자바스크립트는 자바와 아무 관련이 없습니다. 불행한 이름 선택이지만 우리는 그것을 견뎌야 합니다.
ECMAScript라는 용어를 소개하겠습니다. 우리는 ECMAScript에 전념하는 완전한 가이드를 가지고 있는데, 여기서 더 많이 잠수할 수 있지만, 우선 ECMAScript(ES라고도 함)가 JavaScript 표준의 이름이라는 것을 알아야 한다.
자바스크립트는 그 표준을 구현한 것이다. 그래서 ES6, ES2015, ES2016, ES2017, ES2018 등등에 대해 듣게 될 것이다.
매우 오랫동안 모든 브라우저가 실행한 JavaScript 버전은 ECMAScript 3이었습니다. 버전 4는 특징 크리프 때문에 취소되었다(한 번에 너무 많은 것을 추가하려고 했다). ES5는 JavaScript의 거대한 버전 이었지만 ES2015라고도 불리는 ES2015도 거대했습니다.
그 이후로 담당 담당자는 릴리스간에 너무 많은 시간을 유휴 상태로 두지 않기 위해 연간한 버전을 출시하기로 결정했으며 더 빠른 피드백 루프를 갖습니다.
현재, 최근에 승인된 자바스크립트 버전은 ES2017이다.
JavaScript에 대해 읽을 때마다 필연적으로 다음 용어 중 하나를 볼 수 있습니다.
이것이 의미하는 것은 무엇일까?
그들은 모두 ECMAScript라고 불리는 표준을 언급하고 있다.
ECMAScript는 JavaScript의 기반을 두고 있는 표준이며, 종종 ES로 약칭된다.
JavaScript 외에도 다른 언어(다음을 포함)는 ECMAScript로 구현되고 있다.:
하지만 물론 자바스크립트는 ES의 가장 인기 있고 널리 사용되는 구현이다. 왜 이 이상한 이름이죠? Ecma International은 국제 표준을 정의하는 일을 담당하는 스위스 표준 협회다.
JavaScript가 만들어 졌을 때, 그것은 Netscape와 Sun Microsystems에 의해 Ecma에 제시되었고 그들은 ECMA-262 별칭 ECMAScript라는 이름을 붙였습니다.
넷스케이프와 선 마이크로시스템(자바의 제조사)의 보도자료는 위원회에 있던 마이크로소프트의 법적 및 브랜딩 문제를 포함할 수 있는 이름 선택을 알아내는 데 도움이 될 수 있다. 위키피디아에 따르면, IE9 이후 마이크로소프트는 브라우저에서 ES 지원을 JScript로 낙인찍는 것을 중단하고 자바스크립트라고 부르기 시작했다(적어도 더 이상 언급할 수는 없었다). 그래서 201x년 이래로, ECMAScript 스펙을 지원하는 유일한 인기 언어는 JavaScript입니다.
현재 ECMAScript버젼은 ES2018이다. 2018년 6월에 배포되었다.
역사적으로, 자바스크립트판은 여름동안에 표준화되어왔다. 그래서 우리는 ECMAScript2019는 2019년 여름에 배포될 것으로 기대되지만, 이것은 그냥 추측일 뿐이다.
TC39는 자바스크립트를 진화시키는 위원회다.
TC39의 회원은 Mozilla, Google, Facebook, Apple, Microsoft, Intel, PayPal, SalesForce 및 기타를 포함한 JavaScript 및 브라우저 공급 업체에 참여하는 회사입니다.
모든 표준 버전 제안은 여기서 설명한 다양한 단계를 거쳐야 한다.
나는 왜 때때로 ES 버전이 판 번호로, 때로는 연도별로 참조되는지 혼란스러워했다.
ES2015 이전에는 ECMAScript 사양이 일반적으로 그들의 판으로 불렸다. 따라서 ES5는 2009년에 발표된 ECMAScript 사양 업데이트의 공식 이름입니다.
왜 이런 일이 일어나는가? ES2015로 이어지는 과정에서 ES6에서 ES2015로 이름이 바뀌었지만, 이것이 늦게 끝났기 때문에 사람들은 여전히 ES6로 언급했고, 지역사회는 판 이름을 뒤에 남기지 않았다. 세계는 여전히 ES 발매를 판 번호로 부르고 있다.
혼돈을 피하기 위하여 표로 정리하였다.
| Edition | Offical name | 출판일 |
|---|---|---|
| ES9 | ES2018 | June 2018 |
| ES8 | ES2017 | June 2017 |
| ES7 | ES2016 | June 2016 |
| ES6 | ES2015 | June 2015 |
| ES5.1 | ES5.1 | June 2011 |
| ES5 | ES5 | December 2009 |
| ES4 | ES4 | Abandoned |
| ES3 | ES3 | December 1999 |
| ES2 | ES2 | June 1998 |
| ES1 | ES1 | June 1997 |
ESx은 항상 다음 버전의 JavaScript를 나타내는 이름입니다. 글쓰기 당시 ES9가 출시되었고, 다음은 ES10입니다.
ES6라고도 알려진 ECMAScript 2015는 ECMAScript 표준의 기본 버전입니다.
최신 표준 개정판인 ECMAScript 5.1 이후 4년 만에 발행되었으며, 또한 판 번호에서 연도 번호로 전환했습니다.
따라서 ES6(모든 사람들이 그렇게 부르지만)라고 이름 지어서는 안 되지만 대신 ES2015라고 이름 붙여야 한다.
ES5는 1999년부터 2009년까지 10년 동안 제작되었으며, 따라서 언어의 기본적이고 매우 중요한 개정이었습니다.하지만 시간이 너무 많이 지났기 때문에 ES5 이전 코드가 어떻게 작동하는지에 대해 논의할 가치가 없다.
ES5.1과 ES6 사이에 오랜기간이 걸렸기 때문에, 이 릴리스는 자바스크립트 프로그램 개발에 있어서 제안된 모범 사례의 중요한 새로운 기능과 주요 변경사항으로 가득 차 있다. ES2015가 얼마나 근본적인지 이해하기 위해 이 버전으로 사양 문서가 250 페이지에서 600 페이지로 진행되었음을 명심하십시오.
ES2015에 포함된 가장 중요한 변화:
let and const이 안내서에서는 각 영역별로 이것들을 다룰 것이다. 그럼, 시작해보자
화살표 함수는 대부분의 JavaScript 코드가 (그리고 작동하는) 방식을 변화시켰다.
시각적으로 간단하고 환영할 만한 변화다.
const foo = function foo() { //... }
에서
const foo = () => { //... }
로
그리고 함수의 내용이 한줄이라면, 단지
const foo = () => doSomething()
또한, 파라메터가 하나라면, 우리는 이렇게 쓸 수 있다.
const foo = param => doSomething(param)
이것은 파괴적인 변화는 아니며, 이전의 function문법은 계속해서 작동한다.
화살표함수의 this영역은 문맥으로 부터 상속받는다.
정규함수에서는 this는 항상 최근접 함수를 참조한다. 화살표함수에서는 이문제를 없애으며, 더이상 var that = this를 작성하지 않아도 된다.
Promise는 비록 좀 더 복잡한것을 도입하지만, 유명한 “callback hell”을 제거할 수 있게 해준다.(ES2017에서 좀 더 높은 수준의 구조인 async로 해결)
Promise는 ES2015이전에는 많은 다른 라이브러리로 구현을 가지고 JavaScript개발자에 의해서 사용되었다.(예를 들어 jQuery, q, deferred.js, 등…). 표준은 차이점으로 부터 공통점을 만들었다.
promises를 사용하여
setTimeout(function() { console.log('I promised to run after is') setTimeout(function(){ console.log('I promised to run after 2s') }, 1000) }, 1000)
를
const wait = () => new Promise((resolve, reject) => { setTimeout(resolve, 1000) }) wait().then(() => { console.log('I promised to run after 1s') return wait() }) .then(() => console.log('I promised to run after 2s'))
로 작성할 수 있다.
Generators는 자신을 실행중지 할 수 있는 능력을 가진 특별한 종류의 함수이다. 나중에 다시 시작하여 다른 코드가 실행되도록한다.
이 코드는 기다려야 한다고 결정하므로 다른 코드가 “queue안에”있게 실행되고 “기다리는 것”이 끝나면 작업을 재개할 권리가 있다. 이 모든 것은 하나의 단순한 키워드로 이루어진다. generator에 해당 키워드가 포함되어 있으면 실행이 중단된다.
generator는 많은 yield키워드를 포함할 수 있으므로 여러 번 중단할 수 있으며, C,C++ 또는 Go와 같은 하위 레벨 프로그래밍 언어에 사용되는 포인터 참조 연산자와 혼동하지 않는 *기능 키워드로 식별된다.
genterator는 자바스크립트에서 완전히 새로운 프로그래밍 패러다임을 가능하게 하여 다음을 허용한다:
여기에 이 모든 작업을 설명하는 generator의 예제가 있다.
function *calculator(input) { var doubleThat = 2 * (yield (input / 2)) var another = yield(doubleThat) return (input * doubleThat * another) }
이것을 다음으로 초기화 하고
const calc = calculator(10)
그리고 우리의 generator의 iterator를 시작한다:
calc.next()
이 첫 반복은 iterator를 시작한다. 코드는 this오브젝트를 리턴한다:
{ done: false value: 5 }
무엇이 일었났나:코드는 함수를 실행, input = 10을 가지고 generator생성자에 전달한다. 이것은 yield를 만날때까지 실행하고, yield:input / 2 =5의 내용을 리턴한다. 그리하여 우리는 5의 값을 얻고, 반복은 종료되지 않음을 가르킴(함수는 단지 멈춤상태이다.)
두번째 반복에서는 우리는 값7을 전달한다:
calc.next(7)
그리고 우리가 돌아왔을 때 얻는 것은:
{ done: false value: 14 }
7은 doubleThat의 값으로 대체된다.
중요: 당신은input / 2는 argument라고 생각할 것이나, 그러나 그것은 단지 첫번째 반복의 리턴값이다. 우리는 그것을 건너뛰고, 새로운 입력 값,7을 사용하여 이것에 2를 곱한다.
우리는 그리고 두번째 수확자에 도착하고, 그리고 doubleThat을 리턴하며, 그래서 리턴값은 14다.
다음으로, 마지막, 반복, 100을 전달한다.
calc.next(100)
그리고 리턴에서 우리가 얻는 것은:
{ done: true value: 14000 }
그리하여 반복은 끝났으며(더이상 yield키워드를 찾을 수 없음), 우리는 단지 (input * doubleThat * another)의 결과인 10 * 14 * 100을 리턴한다.
var는 정통적인 funcion scoped이다.
let은 block scoped를 갖는 새로운 변수 선언자다.
이 의미는 for반복문에서, if문 안에서, 또는 블럭에서 let에 의한 변수선언이 블럭의 “범위밖”에서는 그 변수를 사용할 수 없고, var들은 함수정의로 감아 올려진다.
const는 let과 유사하지만, immutable(불변의)이다.
앞으로 나아갈 자바스크립트에서, 너는 더 이상 var선언을 거의 보지 않고 let과 const만 보게될 것이다.
특히, 아마도 놀랍게도 const는 오늘날에는 불변성이 매우 인기 있는 것으로 널리 사용되고 있다.
정통적으로 자바스크립트는 prototype기반 상속을 가진 유일한 주류 언어이었다. 프로그래머들은 클래스 기반 언어에서 자바스크립트로 전환하는 것이 곤혹스럽다는 것을 알았지만, ES2015는 classes을 소개하였으나, 자바스크립트의 내부 작업에 대한 단지 문법적 첨가물이지만, 우리가 자바스크립트 프로그램을 어떻게 바꾸어서 만드는지 소개하였다.
자, 상속은 매우 쉽고, 다른 오브젝트 오리엔티드 프로그램언어와 유사하다:
class Person{ constructor(name) { this.name = name } hello() { return 'Hello, I am ' + this.name + '.' } } class Actor extends Person { hello() { return super.hello() + ' I am an actor.' } } var tomCruise = new Actor('Tom Cruise') tomCruise.hello()
이 프로그램은 “Hello, I am Tom Cruise. I am an actor.”을 출력한다.
Classes는 명시적은 클래스 변수 선언은 없지만, 생성자에서 변수를 초기화해야 합니다.
Classes는 new통해 클래스를 초기화할 때 호출하는 constructor라는 특별한 메소드를 가진다.
부모 클래스는 참조할때는 super()를 이용한다.
property를 위한 getter 선언은:
class Person { get fullName() { reurn `${this.firstName} ${this.lastName}` } }
setter는 같은 방법으로:
class Person { set age(years) { this.theAge = years } }
ES2015 이전에는 커뮤니티를 분열시킨 적어도 3 가지 주요 경쟁 모듈 표준이 있었습니다.
ES2015는 이것을 일반적인 형식으로 표준화했다.
수입은 import … from …를 통해 구성한다.
import * from 'mymodule' import React from 'react' import { React, Component } from 'react' import React as MyLibrary from 'react'
모듈을 쓸 수 있고 다른 모듈에게 무엇가를 수출하려면 export키워드를 사용한다.
export var foo = 2 export function bar() { /* ... */ }
문자열을 만드는 새로운 문법:
const aString = `A string`
이 것은 문법 ${a_variable} 내장수식을 이용하여 값을 효과적으로 삽입하는 방법을 제공한다:
const var = 'test' const string = `something ${var}` //something test
좀 더 복잡한 수식도 잘 작동한다:
const string = `something ${1 + 2 + 3}` const string2 = `something ${foo()? 'x' : 'y' }`
그리고 문자열을 여러 줄에 걸쳐서 표현할 수 있다.
const string3 = `Hey this string is awesome!`
ES2015이전에 여러 줄의 문자열을 표현하는 것과 비교하면:
var string = 'One\n' + 'Two\n' + 'Three'
이제 함수에 디폴트 파라메터를 지원한다.
const foo = function(index = 0, testing = true) { /* ... */ } foo()
펼침연산자 …를 이용하여 배열, 오브젝트, 문자열을 퍼지게 할 수 있다.
배열예제부터 시작하자. 아래가 주어졌다:
const a = [1, 2, 3]
새로운 배열을 만들 수 있다.
const b = [...a, 4, 5, 6]
또한 배열을 복사할 수 있다.
const c = [...a]
오브젝트들도 잘 작동한다. 오브젝트를 복사:
const newObj = { ...oldObj }
문자열에 이용하면, 문자열에 있는 각 문자를 갖는 배열을 만든다:
const hey = 'hey' const arrayized = [...hey] // ['h', 'e', 'y']
이 연산자에는 꽤 유용한 응용 프로그램이 있습니다. 가장 중요한 것은 매우 간단한 방법으로 배열을 함수 인수로 사용하는 것입니다.
const f = (foo, bar) => {} const a = [1, 2] f(...a)
과거에는 이것과 동일한 것을 수행하려면 f.apply(null, a)을 이용하였는데 좋지도 읽기도 꽝이다.
주어진 오브젝트에서 일부 값을 추출하고 명명된 변수에 넣을 수 있다.
const person = { firstName: 'Tom', lastName: 'Cruise', actor: true, age: 54, //made up } const {firstName: name, age} = person
name과 age에는 요구된 값을 갖는다.
배열을 이용하는 문법은:
const a = [1,2,3,4,5] [first, second, , , fifth] = a
ES2015에서 Object Literals는 강력해졌다.
const something = 'y' const x = { something: something }
를 사용하는 대신에
const something = 'y' const x = { something }
로 할 수 있다.
prototype을 기술할 수 있다.
const anObject = { y: 'y' } const x = { __proto__: anObject }
const anObject = { y: 'y', test: () => 'zoo' } const x = { __proto__: anObject, test() { return super.test() + 'x' } } x.test() //zoox
const x = { ['a' + '_' + 'b']: 'z' } x.a_b //z
2009년 ES5에서 forEach()반복문을 도입하였다. 좋았지만, 중간에 끊을 방법을 제안하지 않았다.(for반복은 항상 실행한다.)
ES2015는 for-of반복을 도입하여, 중단기능을 갖는 forEach의 간결함과 결합되었다.
//iterate over the value for (const v of ['a', 'b', 'c']) { console.log(v); } //get the index as well, using `entries()` for (const [i, v] of ['a', 'b', 'c'].entries()) { console.log(i, v); }
Map과 Set (그리고 각각의 가비지 수집 WeakMap과 WeakSet)은 두 가지 매우 대중적인 데이터 구조 (공식적으로 나중에 소개 됨)의 공식 구현물입니다.
ES7, 공식적으로 ECMAScript2016로 알려진, 2016년 6월에 종료됨.
ES6와 비교하면, ES7는 단지 2개의 특성(기능)을 포함한 자바스크립트의 작은 배포판이다.
이 기능은 배열에 요소가 포함되어 있는지 확인하기 위해보다 읽기 쉬운 구문을 도입했다.
ES6 이하에서는 배열에 요소가 포함되어 있는지 확인하기 위해 배열의 인덱스를 검사하는 indexOf를 사용해야하고 요소가 없으면 -1을 반환합니다.
-1은 true 값으로 평가되므로, 예를 들어 수행 할 수 없습니다.
if (![1,2].indexOf(3)) { console.log('Not found') }
ES7에서는 이 기능을 가지고 수행 할 수 있습니다.
if (![1,2].includes(3)) { console.log('Not found') }
지수 연산자 **는 Math.pow ()와 동일하지만 라이브러리 함수가 아닌 언어로 가져 왔습니다.
Math.pow (4, 2) == 4 ** 2
이 기능은 수학 집중적 인 JavaScript 애플리케이션을위한 훌륭한 추가 기능입니다.
**연산자는 Python, Ruby, MATLAB, Lua, Perl 등 많은 언어에서 표준화되어 있습니다.
ECMAScript2017, ECMA-262표준의 8번째판(또한 일반적으로 ES2017 또는 ES8로 불리는), 2017년 6월 발표되었다.
ES6와 비교하면, ES8은 매우 유용한 특성(기능)를 도입하였지만, 자바스크립트의 작은 배포판이다.
문자열 패딩의 목적은 문자열에 문자를 추가하여 특정 길이에 도달하는 것입니다.
ES2017은 두개의 String메서드인 padStart()와 padEnd()를 도입하였다:
padStart(targetLength [, padString]) padEnd(targetLength [, padString])
단순한 사용:
| padStart() | |
|---|---|
| 'test'.padStart(4) | 'test' |
| 'test'.padStart(5) | ' test' |
| 'test'.padStart(8) | ' test' |
| 'test'.padStart(8,'abcd') | 'abcdtest' |
이 메서드는 오브젝트가 가진 모든 속성들을 [key, value]]쌍의 배열를 반환한다.
사용:
const person = { name: 'Fred', age: 87 } Object.entries(person) // [['name', 'Fred'], ['age', 87]]
Object.entries()는 배열과 함께하면:
const people = ['Fred', 'Tony'] Object.entries(people) // [['0', 'Fred'], ['1', 'Tony']]
이 메서드는 오브젝트가 가진 모든 속성(상속되지않은) 기술자(descripter)를 반환한다.
자바스크립트의 임의의 오브젝트는 속성들의 집합을 가지고, 이 속성들의 각각은 기술자를 갖는다.
이 기술자는 속성의 속성의 집합이고, 아래의 하위 집합에 의한 조합이다.
enumberable이면 true
Object.getOwnPropertyDescriptors(obj)는 오브젝트를 허용하며, 기술자의 집합를 갖는 오브젝트를 리턴한다.
ES2015는 우리에게 Object.assign()을 주었으며, 하나 이상의 오브젝트로부터 모든 열거(enumerable) 가능한 고유 속성을 복사하고 새로운 오브젝트를 반환한다.
그러나 디폴트 속성이 아닌 속성을 올바르게 복사하지 않기 때문에 문제가 있다.
예를 들어 객체에 setter가 있는 경우 Object.assign()을 사용하여 새 객체에 정확하게 복사되지 않는다.
예를 들면:
const person1 = { set name(newName) { console.log(newName) } }
이것은 작동하지 않는다:
const person2 = {} Object.assign(person2, person1)
하지만 이것은 작동한다:
const person3 = {} Object.defineProperties(person3, Object.getOwnPropertyDescriptors(person1))
단순한 콘솔 테스트를 본다면:
person1.name = 'x' "x" person2.name = 'x' person3.name = 'x' "x"
person2는 setter가 없으며, 복사되지 않았다.
같은 제한사항은 Object.create()를 통한 오브젝트 복제에도 있다.
이 특색은 함수선언과 함수호출시에 후행 콤마를 갖는 것을 허용한다.
const doSomething = (var1, var2,) => { //... } doSomething('test2', 'test2',)
이 변화는 개발자가 습관적으로 못생긴 “콤마로 시작하는 줄”를 없애도록 하여준다.
ES2017는 비동기 함수의 개념을 도입하였고, 이것은 ECMAScript판에서 가장 중요한 변화이다.
비동기함수는 promises를 둘러싼 상용구를 줄이기 위해 promises와 generators를 결합한 것이며, “제한을 깨지 마십시오”라는 체인 promises의 제한이다.
promises보다 높은 수준의 추상화입니다. ES2015에 약속이 도입되었을 때, 비동기 코드 문제를 해결하기위한 것이 었습니다. 그러나 ES2015와 ES2017사이의 2년 동안 promises가 최종 해결책이 될 수 없음이 분명했습니다.
유명한 callback hell 문제를 해결하기 위해 promises이 도입되었지만, 자신의 복잡성과 구문의 복잡성을 도입했습니다. 그것들은 더 좋은 구문이 개발자들에게 노출 될 수있는 좋은 기본 요소였습니다 : 비동기 함수를 도입하라.
비동기함수의 유용성을 확인하여 주는 코드:
function doSomethingAsync() { return new Promise((resolve) => { setTimeout(() => resolve('I did something'), 3000) }) } async function doSomething() { console.log(await doSomethingAsync()) } console.log('Before') doSomething() console.log('After')
이 코드가 브라우저 콘솔에 출력:
Before
After
I did something //after 3s
비동기 함수는 매우 쉽게 연결될 수 있으며 구문은 일반 promises보다 훨씬 읽기 쉽습니다.
function promiseToDoSomething() { return new Promise((resolve)=>{ setTimeout(() => resolve('I did something'), 10000) }) } async function watchOverSomeoneDoingSomething() { const something = await promiseToDoSomething() return something + ' and I watched' } async function watchOverSomeoneWatchingSomeoneDoingSomething() { const something = await watchOverSomeoneDoingSomething() return something + ' and I watched as well' } watchOverSomeoneWatchingSomeoneDoingSomething().then((res) => { console.log(res) })
WebWorkers는 브라우저에서 다중 스레드 프로그램을 작성하는 데 사용됩니다.
이벤트를 통해 메시징 프로토콜을 제공합니다. ES2017부터는 SharedArrayBuffer를 사용하여 웹 작업자와 작성자간에 공유 메모리 배열을 만들 수 있습니다.
공유 메모리 부분에 쓰는 시간이 전파되는 데 걸리는 시간을 알지 못하기 때문에 Atomics는 값을 읽고 모든 종류의 쓰기 작업이 완료 될 때이를 적용 할 수있는 방법입니다.
이에 대한 자세한 내용은 구현 된 사양 제안서에서 확인할 수 있습니다.
ES2018은 ECMAScript 표준의 최신 버전이다.
이것에 새롭게 도입된 것은 무엇인다.
ES6에서 array destructuring와 함께 작동하는 rest element의 개념을 도입하였다:
const number = [1, 2, 3, 4, 5] [first, second, ...others] = numbers
spread elements:
const numbers = [1, 2, 3, 4, 5] const sum = (a, b, c, d, e) => a + b + c + d + e const sum = sum(...numbers)
ES2018에서 오브젝트에 대해서도 도입하였다.
Rest properties:
const { first, second, ...others } = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5 } first // 1 second // 2 others // { third: 3, fourth: 4, fifth: 5 }
Spread properties을 사용하면 스프레드 연산자 뒤에 전달 된 객체의 속성을 결합하여 새 객체를 만들 수 있습니다.
const items = { first, second, ...others } items //{ first: 1, second: 2, third: 3, fourth: 4, fifth: 5 }
for-await-of의 새로운 구문을 사용하면 반복 가능한 비동기 객체를 루프 반복으로 사용할 수 있습니다.
for await (const line of readLines(filePath)) { console.log(line) }
await를 사용하면, 정상적인 await (async/await 참조)과 같이 비동기 함수에서만 사용할 수 있습니다.
promise가 성취되면 성공적으로 then() 메소드를 호출합니다.
이 중에 뭔가가 실패하면, then() 메서드는 건너뛰고 catch() 메서드가 실행됩니다.
finally()는 약속의 성공 또는 실패 여부에 관계없이 일부 코드를 실행할 수있게합니다.
fetch('file.json') .then(data => data.json()) .catch(error => console.error(error)) .finally(() => console.log('finished'))
RegExp lookbehind assertions: 앞에 오는 것에 따라 문자열을 일치시킵니다.
이것은 lookahead이다: ?=를 사용하여 특정 하위 문자열이 오는 문자열을 찾습니다.
/Roger(?=Waters)/ /Roger(?= Waters)/.test('Roger is my dog') //false /Roger(?= Waters)/.test('Roger is my dog and Roger Waters is a famous musician') //true
?!는 문자열에 특정 하위 문자열이없는 경우 일치하는 역 연산을 수행합니다.
/Roger(?!Waters)/ /Roger(?! Waters)/.test('Roger is my dog') //true /Roger(?! Waters)/.test('Roger Waters is a famous musician') //false
Lookaheads는 ?= 기호를 사용합니다. 그들은 이미 이용 가능했다.
새 기능인 Lookbehinds는 ?<=를 이용한다.
/(?<=Roger) Waters/ /(?<=Roger) Waters/.test('Pink Waters is my dog') //false /(?<=Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician') //true
lookbehind의 역 연산은 ?<!을 이용한다:
/(?<!Roger) Waters/ /(?<!Roger) Waters/.test('Pink Waters is my dog') //true /(?<!Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician') //false
정규식 패턴에서는 \d를 사용하여 임의의 숫자와 일치 시키거나, \s를 사용하여 공백이 아닌 문자를 일치 시키거나, \w를 사용하여 영숫자 문자와 일치시킬 수 있습니다.
이 새로운 기능은 이 개념을 \p{}를 소개하는 모든 유니 코드 문자로 확장하고 부정 \P{}입니다.
모든 유니 코드 문자에는 일련의 속성이 있습니다. 예를 들어 Script는 언어 군을 결정하고 ASCII는 ASCII 문자에 대해 참인 부울입니다. 이 속성을 그래프 괄호에 넣으면 정규식이 true인지 확인합니다.
/^\p{ASCII}+$/u.test('abc') //✅ /^\p{ASCII}+$/u.test('ABC@') //✅ /^\p{ASCII}+$/u.test('ABC🙃') //❌
ASCII_Hex_Digit은 문자열이 유효한 16 진수 만 포함하고 있는지 검사하는 다른 부울 속성입니다.
/^\p{ASCII_Hex_Digit}+$/u.test('0123456789ABCDEF') //✅ /^\p{ASCII_Hex_Digit}+$/u.test('h') //❌
다른 대다수의 부울 속성이 있습니다. 대문자, 소문자, White_Space, Alphabetic, Emoji 등 그래프 괄호에 이름을 추가하여 확인하면됩니다.
/^\p{Lowercase}$/u.test('h') //✅ /^\p{Uppercase}$/u.test('H') //✅ /^\p{Emoji}+$/u.test('H') //❌ /^\p{Emoji}+$/u.test('🙃🙃') //✅
이러한 2 진 등록 정보 외에도 특정 값과 일치하도록 유니 코드 문자 특성을 점검 할 수 있습니다. 이 예에서는 문자열이 그리스어 또는 라틴 알파벳으로 쓰여 있는지 확인합니다.
/^\p{Script=Greek}+$/u.test('ελληνικά') //✅ /^\p{Script=Latin}+$/u.test('hey') //✅
제안서에서 직접 사용할 수있는 모든 속성에 대해 자세히 알아보십시오.
ES2018에서 캡처 그룹은 결과 배열의 슬롯을 할당하는 대신 이름에 할당 할 수 있습니다.
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/ const result = re.exec('2015-01-02') // result.groups.year === '2015'; // result.groups.month === '01'; // result.groups.day === '02';
단일 행의 줄임말 인 s플래그는 . 새 줄 문자도 일치시킵니다. 이 문자가 없으면 점은 일반 문자와 일치하지만 새 문자는 그렇지 않습니다.
/hi.welcome/.test('hi\nwelcome') // false /hi.welcome/s.test('hi\nwelcome') // true
JavaScript 코딩 스타일은 JavaScript를 사용할 때 사용되는 규칙 세트입니다. 코딩 스타일은 프로젝트에 일관성을 유지하기 위해 자신과 팀과 합의한 것입니다. 그리고 팀이 없다면 코드를 항상 자신의 기준에 맞게 유지하는 것이 좋습니다. 코드 작성 형식에 대한 고정 된 규칙을 사용하면보다 읽기 쉽고 관리하기 쉬운 코드를 확보하는 데 많은 도움이됩니다.
주변에는 꽤 많은 것들이 있습니다. 자바 스크립트 세계에서 가장 일반적인 것들이 2 개 있습니다:
이 중 하나를 따르거나 자신 만의 스타일 가이드를 만드는 것은 당신의 몫입니다.
스타일 세트를 선호하더라도 프로젝트에서 작업 할 때는 해당 스타일을 사용해야합니다.GitHub의 오픈 소스 프로젝트는 일련의 규칙을 따를 수 있으며 팀과 함께하는 또 다른 프로젝트는 완전히 다른 규칙을 따를 수 있습니다.더 예쁘게 만드는 것은 코드 형식을 시행하는 훌륭한 도구이므로 사용해야합니다.
우리는 항상 최신 ES 버전을 사용합니다. 이전 브라우저 지원이 필요한 경우 Babel을 사용하십시오.
var를 절대로 사용하지 마십시오. 디폴트는 const이며, 변수를 재 지정하면 let 만 사용하십시오.const test = (a, b) => a + b const another = a => a + 2
-로 구분해야합니다.if
if (condition) { statements } if (condition) { statements } else { statements } if (condition) { statements } else if (condition) { statements } else { statements }
for:
항상 캐시 할 초기화의 길이를 초기화하고 조건에 삽입하지 마십시오. .hasOwnProperty()와 함께사용하는 것을 제외하고 for in 사용하는 것을 피하십시오. for of 선호 :
for (initialization; condition; update) { statements }
while
while (condition) { statements }
do
do { statements } while (condition);
switch
switch (expression) { case expression: statements default: statements }
try
try { statements } catch (variable) { statements } try { statements } catch (variable) { statements } finally { statements }
(따라오면 공백 문자를 넣고; 이진 연산 (+, -, /, *, && ..) 앞뒤에; for 문 안에, 문장을 구분하는 ;뒤에 ; 각 ,후 에 공백문자를 넣으세요.이제 유니 코드, 세미콜론, 공백, 대소 문자 구분, 주석, 리터럴, 식별자 및 예약어와 같은 JavaScript 구축 요소에 대해 자세히 살펴 보겠습니다. 유니 코드 JavaScript는 유니 코드로 작성됩니다. 즉, Emojis를 변수 이름으로 사용할 수 있습니다. 😃 😧 😲 그러나 더 중요한 것은 식별자를 몇 가지 규칙과 함께 모든 언어 (예 : 일본어 또는 중국어)로 작성할 수 있다는 것입니다.
세미콜론 JavaScript는 C와 매우 유사한 구문을 가지고 있으며, 각 행의 끝에서 세미콜론을 특징으로하는 많은 코드 샘플을 볼 수 있습니다.
세미콜론은 필수 항목이 아니며 자바 스크립트는 세미콜론을 사용하지 않는 코드에는 아무런 문제가 없습니다. 요즘 많은 개발자, 특히 세미콜론이없는 언어를 사용하는 개발자는 사용을 피하기 시작했습니다. 여러 행에 명령문을 입력하는 것과 같은 이상한 일을하지 않아도됩니다.
return
variable
또는 괄호 ([또는 ()로 시작하는 라인은 99.9 %의 시간 동안 안전합니다 (린터가 경고합니다).
개인적인 취향에 달려 있으며 최근에는 쓸모없는 세미콜론을 추가하지 않기로 결정했습니다. 따라서 이 기사에서는 결코 볼 수 없습니다.
White space 자바 스크립트는 의미있는 공백을 고려하지 않습니다. 이론적으로는 공간과 줄 바꿈을 원하는대로 설정할 수 있습니다.실제로는 잘 정의 된 스타일을 유지하고 사람들이 일반적으로 사용하는 것에 충실하게 적용 할 수 있으며 lint 또는 Prettier와 같은 스타일 도구를 사용하여이를 적용 할 수 있습니다.예를 들어, 항상 2 자로 들여 쓰기를 좋아합니다.
Case sensitive
자바스크립트는 대소문자를 구별합니다. 변수명 something은 Something과 다릅니다.
모든 식별자에 동일합니다.
Comments 자바스크립트는 두 종류의 주석을 사용합니다.
/* */ //
첫 번째 줄은 여러 줄에 걸쳐 있고 닫을 필요가 있습니다.
두 번째는 오른쪽에있는 모든 것을 현재 줄에 주석 처리합니다.
리터럴은 숫자, 문자열, 부울 또는 객체 리터럴 또는 배열 리터럴과 같은 고급 구문과 같이 소스 코드에 작성된 값을 정의합니다.
5 'Test' true ['a', 'b'] {color: 'red', shape: 'Rectagle'}
식별자는 변수, 함수, 오브젝트를 구별하는 문자의 열이다. 문자, $, _로 시작하고 아라비아숫자를 포함할 수 있다. 유니코드를 이용하면, 어떠한 문자도 사용할 수 있다. 예를 들어 이모지 😄.
Test test TEST _test Test1 $test
달러문자는 DOM요소를 참조하는데 일반적으로 사용된다.
언어에서 예약된 다음 단어는 식별자로 사용할 수 없다.
변수는 식별자에 대응되는 문자열이며, 그래서 프로그램에서 후에 참조되고 사용된다. 우리는 JavaScript에서 어떻게 선언하는지 배울것이다.
Introduction to JavaScript Variables 변수는 식별자에 대응되는 문자열이며, 그래서 프로그램에서 후에 참조되고 사용된다.
자바스크립트에서 변수는 어떤 형을 갖지는 않는다. 단지 변수에 특별한 문자형을 대응시켜기며, 후에 형 오류나 어떤 문제없이 어떤 다른 형을 갖는 변수를 사용할 수 있다.
이것은 왜 자바스크립트를 “untyped”라도 하는 이유이다.
변수는 사용되기 전에 선언해야 한다. 여기에 선언하는 3가지 길이 있다.: var, let 또는 const. 이 3가지 길의 차이점을 논의할 것이다.
Using var
ES2015까지, var는 변수를 선언를 위한 유일한 생성자였다.
var a = 0
var를 추가하는 것을 잊어 버리면 선언되지 않은 변수에 값을 할당하게되고 결과가 달라질 수 있습니다.
엄격한 모드가 활성화된 최신 환경에서는 오류가 발생합니다. 이전 환경에서는 (또는 엄격 모드가 비활성화 된 경우) 변수를 초기화하고 전역 객체에 할당하기 만하면 됩니다.
선언 할 때 변수를 초기화하지 않으면 값을 할당 할 때까지 변수가 정의되지 않은 값을 갖습니다.
var a // typeof a === 'undefined'
변수를 여러 번 다시 선언하여 재정의 할 수 있습니다.
var a = 1 var a = 2
같은 문장에 다중변수를 선언할 수 있다.
var a = 1, b = 2
영역(Scope)는 변수가 표시되는 코드 부분입니다.
함수 밖에서 var로 초기화 된 변수는 전역 객체에 할당되고 전역 범위를 가지며 어디에서나 볼 수 있습니다. 함수 내에서 var로 초기화 된 변수는 해당 함수에 할당되며 함수 매개 변수와 마찬가지로 로컬 변수이며 그 내부에서만 볼 수 있습니다.
전역 변수와 동일한 이름을 가진 함수에 정의 된 변수는 전역 변수보다 우선 순위가 높습니다.
블록 (중괄호 쌍으로 식별 됨)이 새 범위를 정의하지 않는다는 것을 이해하는 것이 중요합니다. 새로운 범위는 함수가 생성 될 때만 생성됩니다. var에는 블록 범위가 아니라 함수 범위가 있기 때문입니다.
함수 내에서 정의 된 모든 변수는 모든 함수 코드에서 볼 수 있습니다. 함수의 끝에서 변수가 선언 되더라도 처음부터 참조 할 수 있습니다. 코드를 실행하기 전에 JavaScript가 실제로 모든 변수를 맨 위에 이동시키기 때문입니다 (hoisting라고하는 것). 혼동을 피하기 위해 항상 함수 시작 부분에 변수를 선언하십시오.
Using let
let은 ES2015에서 소개 된 새로운 기능이며 기본적으로 블록 범위의 var입니다. 범위는 정의 된 블록, 명령문 또는 표현식 및 포함 된 모든 내부 블록으로 제한됩니다.
최신 자바 스크립트 개발자는 let을 사용하고 var의 사용을 완전히 버리기로 선택할 수 있습니다.
let이 모호한 용어로 보인다면, 단순히color = 'red'를 읽으면 색상이 빨간색이되고 훨씬 더 의미가 있습니다.
var에 반하는 함수 밖에서 let을 정의하면 전역 변수가 작성되지 않습니다.
Using const
var 또는 let으로 선언 된 변수는 나중에 프로그램에서 변경되어 다시 할당 될 수 있습니다. 일단 const가 초기화되면, 그 값은 결코 다시 변경 될 수 없으며 다른 값으로 재 할당 될 수 없습니다.
const a = 'test'
우리는 const에 다른 리터럴을 할당 할 수 없습니다. 그러나 내용을 변경하는 메소드를 제공하는 객체인 경우 이를 변형 할 수 있습니다.
const는 불변성을 제공하지 않으며 참조를 변경할 수 없도록합니다.
const는 let과 같은 블록 범위를가집니다.
최신 자바 스크립트 개발자는 나중에 프로그램에서 재 할당 할 필요가없는 변수에 항상 const를 사용하도록 선택할 수 있습니다.
왜? 왜냐하면 우리는 항상 오류를 피하기 위해 가능한 가장 단순한 구조를 사용해야하기 때문입니다.
JS가 유형이 없다는 것을 읽는 경우가 있지만 잘못된 것입니다. 모든 종류의 다른 유형을 변수에 지정할 수 있지만 JavaScript에는 유형이 있습니다. 특히 기본 유형 및 객체 유형을 제공합니다. Primitive types(기본유형) 기본 유형은
그리고 두 가지 특별한 유형 :
다음 섹션에서 자세히 살펴 보겠습니다.
내부적으로 자바 스크립트는 숫자에 대해 하나의 유형을 가지고 있습니다. 모든 숫자는 부동입니다. 숫자 리터럴은 소스 코드에 표시된 숫자이며, 작성 방법에 따라 다르며 정수 리터럴 또는 부동 소수점 리터럴 일 수 있습니다. 정수 :
10 5354576767321 0xCC // 16 진수
실수 :
3.14 .1234 5.2e4 //5.2 * 10 ^ 4
문자열 유형은 일련의 문자입니다. 그것은 소스 코드에서 따옴표 나 큰 따옴표로 묶인 문자열 리터럴로 정의됩니다
'문자열' "다른 문자열"
문자열은 백 슬래시를 사용하여 여러 줄에 걸쳐있을 수 있습니다.
"\
끈"
문자열에는 \n과 같이 문자열을 인쇄 할 때 해석 할 수있는 이스케이프 시퀀스가 포함될 수 있습니다. 백 슬래시는 따옴표로 묶인 문자열에 따옴표를 입력하여 char을 닫는 따옴표로 해석하지 못하게 할 때도 유용합니다.
'I\'m a developer'
문자열은 + 연산자를 사용하여 결합 할 수 있습니다.
"A"+ "문자열"
ES2015에서 소개 된 템플릿 문자열은 문자열을 정의하는보다 강력한 방법을 허용하는 문자열 리터럴입니다.
`문자열`
자바 스크립트 표현식의 결과를 포함하여 문자열 대체를 수행 할 수 있습니다.
`$ {something} '이있는 문자열 `$ {something + somethingElse} '문자열 `$ {obj.something ()}`이있는 문자열
여러 줄을 쉽게 사용할 수 있습니다.
`끈 와 $ {something}`
JavaScript는 부울에 대한 두 개의 예약어 true 및 false를 정의합니다. 많은 비교 연산 == === < > (등등)은 둘 중 하나를 반환합니다.
if, while 문과 다른 제어 구조는 프로그램의 흐름을 결정하기 위해 부울을 사용합니다.
그들은 진실하거나 거짓을 받아들이는 것이 아니라 진리와 거짓의 가치를 받아들이는 것입니다.
위조 된 값, false로 해석되는 값은 다음과 같습니다.
0 -0 NaN undefined null '' // empty string
나머지는 진리 값으로 간주됩니다.
null은 값이 없음을 나타내는 특수한 값입니다.
다른 언어의 일반적인 개념이기도합니다. 예를 들어 Python에서는 nil 또는 None으로 알 수 있습니다.
undefined는 변수가 초기화되지 않았으며 값이 없음을 나타냅니다.
일반적으로 return 값이 없는 함수에서 반환됩니다. 함수가 매개 변수를 받아들이지만 호출자가 매개 변수를 설정하지 않으면 정의되지 않습니다.
값이 undefined를 확인하려면 다음 구문을 사용합니다.
typeof variable === 'undefined'
원시 타입이 아닌 것은 객체 타입입니다. 함수, 배열 및 우리가 객체라고 부르는 것은 객체 유형입니다. 그것들은 독자적으로 특별하지만, 속성을 가지거나 그러한 속성에 대해 작동 할 수있는 메서드를 갖는 것과 같은 많은 개체 속성을 상속합니다.
표현식은 평가되어 값으로 해석 될 수있는 코드 단위입니다. JS의 표현식은 범주로 나눌 수 있습니다.
이 카테고리에서 숫자로 평가되는 모든 표현식을 찾으십시오.
1 / 2 나는 ++ i - = 2 i * 2
문자열로 평가되는 표현식 :
'A'+ '문자열'
이 카테고리에서는 변수 참조, 리터럴 및 상수를 사용합니다.
2 0.02 '어떤 것' true false this // 현재 객체 undefined i // 여기서 i는 변수 또는 상수입니다.
뿐만 아니라 일부 언어 키워드 :
function class function* // 생성자 함수 yield // generator pauser / resumer yield* // 다른 생성자 또는 반복자에 위임합니다. async function* // 비동기 함수 표현식 await // 비동기 함수 기다리기 완료를 위해 일시 중지/다시시작/대기 /pattern/i // regex () // 그룹핑
[] // 배열 리터럴 {} // 객체 리터럴 [1,2,3] {a : 1, b : 2} {a : {b : 1}}
논리식은 논리 연산자를 사용하고 부울 값으로 해석합니다.
a && b a || b !a
new // 생성자의 인스턴스를 생성한다. super // 부모 생성자를 호출합니다. ... obj // 스프레드 연산자를 사용하는 표현식
object.property // 객체의 속성 (또는 메소드) 참조 object[property] object['property']
new object() new a(1) new MyRectangle('name', 2, {a: 4})
function() {} function(a, b) { return a * b } (a, b) => a * b a => a * 2 () => { return 2 }
함수 또는 메서드 호출 구문
a.x (2) window.resize ()
JavaScript는 프로토타입 상속을 사용하기 때문에 인기있는 프로그래밍 언어 환경에서 매우 독특합니다. 그게 무슨 뜻인지 알아 보겠습니다.
대부분의 객체 지향 언어는 클래스 기반 상속 모델을 사용하지만 JavaScript는 프로토타입 상속 모델을 기반으로합니다.
이것은 무엇을 의미 하는가?
모든 단일 JavaScript 객체에는 prototype이라는 속성이 있습니다.이 속성은 다른 객체를 가리 킵니다.
이 다른 객체는 object prototype입니다.
우리의 객체는 객체 프로토타입을 사용하여 속성과 메소드를 상속받습니다.
다음과 같이 객체 리터럴 구문을 사용하여 객체를 만들었습니다.
const car = {}
또는 new Object구문으로 생성
const car = new Object()
어떤 경우든, car의 prototype은 Object이다.
객체인 배열을 초기화하는 경우 :
const list = [] // 또는 const list = new Array()
prototype은 Array이다
Object.getPrototypeOf () 및 Object.prototype.isPrototypeOf () 메소드를 확인하여이를 확인할 수 있습니다.
const car = {} const list = [] Object.getPrototypeOf(car) === Object.prototype Object.prototype.isPrototypeOf(car) Object.getPrototypeOf(list) === Array.prototype Array.prototype.isPrototypeOf(list)
프로토타입의 모든 속성과 메서드는 해당 프로토타입이있는 객체에서 사용할 수 있습니다.
Object.prototype은 모든 객체의 기본 prototype이다.
Object.getPrototypeOf(Array.prototype) == Object.prototype
Object.prototype의 프로토타입이 무엇인지 궁금하다면 프로토타입이 없습니다. 이것은 'null'입니다. 특별한 눈송이예요. ❄️
위에서 본 예는 직장에서 프로토타입 체인의 예입니다. 나는 Array와 객체를 확장하는 객체를 만들 수 있습니다. 객체를 인스턴스화하는 것은 프로토타입 체인에 Array와 Object를 가지며 모든 조상의 속성과 메서드를 상속받습니다. new 연산자를 사용하여 객체를 만들거나 객체 및 배열에 리터럴 구문을 사용하는 것 외에도 Object.create ()를 사용하여 객체를 인스턴스화 할 수 있습니다. 전달 된 첫 번째 인수는 프로토타입으로 사용되는 객체입니다.
const car = Object.create({}) const list = Object.create(Array)
isPrototypeOf () 메서드를 사용하여 객체의 프로토타입을 확인할 수 있습니다.
Array.isPrototypeOf(list) //true
배열을 인스턴스화 할 수 있기 때문에 주의를 기울이십시오.
const list = Object.create (Array.prototype)
이 경우 Array.isPrototypeOf (list)는 false이고 Array.prototype.isPrototypeOf (list)는 true입니다.
2015 년에 ECMAScript 6(ES6) 표준에 class을 도입했습니다. 그 전에 JavaScript에는 상속을 구현하는 고유한 방법만 있었습니다. 필자의 견해로는 프로토타입 상속은 다른 유명한 프로그래밍언어와 달랐습니다. Java 또는 Python이나 다른 언어에서 온 사람들은 프로토타입 상속의 복잡성을 이해하기가 어려웠으므로 ECMAScript위원회는 구문 설탕을 그 위에 소개하고 다른 대중적인 구현에서 클래스 기반 상속이 어떻게 작동하는지를 결정했습니다. 이것은 중요합니다. 두포의 JavaScript는 여전히 동일하므로 일반적인 방법으로 객체 프로토타입에 액세스 할 수 있습니다.
class의 표시방법입니다.
class Person { constructor(name) { this.name = name } hello() { return 'Hello, I am ' + this.name + '.' } }
class는 식별명을 가지며, 우리는 새로운 객체를 new ClassIdentifier()를 사용하여 만들 수 있습니다.
객체가 초기화될때, constructor메서드가 호출되고, 일련의 파라메터가 전달됩니다.
클래스에는 필요한만큼의 메소드도 있습니다. 이 경우 hello는 메소드이며이 클래스에서 파생된 모든 객체에서 호출 할 수 있습니다.
const flavio = new Person ( 'Flavio') flavio.hello ()
class는 다른 클래스를 확장할 수 있고, 두 클래스의 모든 메소드들를 상속한 클래스를 사용하여 객체를 준비한다.
상속된 클래스에 계층 구조의 상위 클래스 중 하나와 이름이 같은 메서드가 있으면 가장 가까운 메서드가 우선 적용됩니다.
class Programmer extends Person { hello() { return super.hello() + ' I am a programmer.' } } const flavio = new Programmer('Flavio') flavio.hello()
위의 프로그램은 “Hello, I am Flavio. I am a programmer.”를 출력한다.
클래스에는 명시적 클래스 변수 선언이 없지만 생성자에서 모든 변수를 초기화해야합니다.
클래스 내에서 super()를 호출하는 부모 클래스를 참조 할 수 있습니다.
평범한 메서드들은 인스턴스에 정의된다. 클래스에 정의되는 것이 아니다.
대신 정적메서드는 클래스에서 실행된다.
class Person { static genericHello() { return 'Hello' } } Person.gernericHello() //Hello
자바스크립트는 전용/보호메서드를 정의하기 위한 내장방법를 갖고 있지 않는다.
우회방법은 있다, 하지만 여기에서는 설명하지 않겠다.
getter와 setter를 만들기 위해서 get, set를 메서드 앞에 추가한다.
class Person { constructor(name) { this._name = name } set name(value) { this._name = value } get name() { return this._name } }
getter 만있는 경우 속성을 설정할 수 없으며 이렇게 시도하면 무시됩니다. setter 만 있으면 값을 변경할 수는 있지만 외부에서 액세스 할 수는 없습니다.
코드가 예기치 않은 문제에 빠지면 이러한 상황을 처리할 수 있는 관용적인 자바스크립트방법은 예외를 통해 이루어집니다.
throw키워드를 사용하여 예외가 생성됩니다.
throw value
여기서 value는 문자열, 숫자 또는 객체를 포함한 모든 JavaScript 값이 될 수 있습니다.
JavaScript가 이 줄을 실행하자마자 정상적인 프로그램 흐름이 중단되고 컨트롤은 가장 가까운 exception handler(예외 처리기)로 잡힙니다.
예외처리기는 try/catch문이다.
try블록에 포함 된 코드 행에서 발생한 예외는 해당 catch블록에서 처리됩니다.
try { // lines of code } catch (e) { }
이 예제에서 e는 exception value다.
다른 종류의 오류를 잡을 수있는 여러 핸들러를 추가 할 수 있습니다.
finally
이 문장을 완성하기 위해 JavaScript에는 finally라고하는 또 다른 명령문이 있습니다. 여기에는 프로그램 흐름에 관계없이 실행되는 코드가 포함되며 예외가 처리되거나 예외가 있거나 없는 경우 실행됩니다.
try { // lines of code } catch (e) { } finally { }
catch블록없이 finally파일을 사용하면 파일이나 네트워크 요청과 같이 try블럭에서 열었던 모든 리소스를 정리할 수 있습니다.
try{ // lines of code } finally { }
try블럭은 충첩될 수 있으며, 예외는 항상 가까운 catch블럭에서 처리된다.
try { //lines of code try { //other lines of code } finally { //other lines of code } } catch (e) { }
내부 try에서 예외가 발생하면 외부 catch 블록에서 처리됩니다.
JavaScript 세미콜론은 선택 사항입니다. 필자는 개인적으로 코드에서 세미콜론을 사용하지 않으려하지만 많은 사람들이 선호합니다. JavaScript의 세미콜론은 커뮤니티를 나눕니다. 어떤 사람들은 무엇이든 항상 그들을 사용하는 것을 선호합니다. 다른 이들은 그들을 피하기를 좋아합니다. 세미콜론을 수년간 사용하고 난 후, 2017 년 가을, 필자는 필요에 따라 코드를 사용하지 않기로 결정했다. 필요로하는 특정 코드 구조가 없으면 코드에서 세미콜론을 자동으로 제거하도록 Prettier를 설정했다. 이제 세미콜론을 피하는 것이 자연 스럽다는 것을 알았습니다. 코드가 더 좋아 보이고 읽을 때 더 깨끗하다고 생각합니다. JavaScript는 세미콜론을 엄격하게 요구하지 않기 때문에이 모든 것이 가능합니다. 세미콜론이 필요한 곳이있을 때 장면 뒤에 추가합니다. 이를 수행하는 프로세스를 자동 세미콜론 삽입이라고합니다. 세미콜론을 사용하는 규칙을 아는 것이 중요합니다. 예상대로 작동하지 않기 때문에 버그를 생성하는 코드를 작성하지 않아야합니다.
JavaScript 파서는 소스 코드를 파싱하는 동안 다음과 같은 특정 상황을 발견하면 자동으로 세미콜론을 추가합니다.
}, 현재 블록 닫기return 문이있는 경우break 문이있을 때throw 문이있을 때continue 문이있는 경우const hey = 'hey' const you = 'hey' const heyYou = hey + ' ' + you ['h', 'e', 'y'].forEach((letter) => console.log(letter))
Uncaught TypeError : 규칙1을 기반으로하기 때문에 undefined의 'forEach' 속성을 읽을 수 없습니다. JavaScript는 코드를 다음과 같이 해석합니다.
const hey = 'hey' const you = 'hey' const heyYou = hey + ' ' + you['h', 'e', 'y'].forEach((letter) => console.log(letter))
const a = 1 const b = 2 const c = a + b (a + b).toString()
위의 코드는 TypeError: b is not a function예외를 발생시키며, 다음과 같이 자바스크립트는 이것을 다음과 같이 번역을 시도한다.
const a = 1 const b = 2 const c = a + b(a + b).toString()
규칙4의 예제
(() => { return { color: 'white' } })()
이 즉시 호출 된 함수의 반환 값은 color 속성을 포함하는 객체가 될 것으로 예상되지만 그렇지는 않습니다. JavaScript는 반환 후에 세미콜론을 삽입하므로 정의되지 않습니다. 대신 반환 직후에 여는 괄호를 넣어야합니다.
(() => { return { color: 'white' } })()
이 코드는 경고에서 '0'으로 표시됩니다.
1 + 1 -1 + 1 === 0 ? alert(0) : alert(2)
그러나 규칙 2의 JavaScript는 규칙 1에 따라 자바 스크립트를 다음과 같이 해석하기 때문에 대신 '2'를 표시합니다.
1 + 1 -1 + 1 === 0 ? alert(0) : alert(2)
조심하라. 어떤 사람들은 세미콜론에 대해서 매우 비판적입니다. 솔직히 신경 쓰지는 않습니다.이 도구를 사용하면 옵션을 사용할 수 없으므로 세미콜론을 피할 수 있습니다. 나는 당신 자신의 결정을 내리는 것 외에는 아무것도 제안하지 않고 있다. 기본 시나리오가 대부분 코드에 나타나지 않더라도 대부분주의를 기울여야합니다. 몇 가지 규칙을 선택하십시오.
궁극적으로 항상 코드를 테스트하여 원하는대로 작동하는지 확인하십시오.
이제 JavaScript 및 고유 기능에서 허용되는 인용문을 살펴 보겠습니다. 자바 스크립트를 사용하면 세 가지 유형의 따옴표를 사용할 수 있습니다.
const test = 'test' const test = 'te\'st' const test = 'te"st' const test = "te\"st" const test = "te'st" const multilineString = 'A string\non multiple lines'
const multilineString = `A string on multiple lines`
${}구문을 사용하여 변수를 보간할 수 있다.
const multilineString = `A string on ${1+1} lines`
ES2015, ES6에서 소개 된 Template Literals는 문자열을 선언하는 새로운 방법을 제공하지만 이미 널리 보급 된 몇 가지 새로운 흥미로운 구문을 제공합니다. 템플릿 리터럴은 새로운 ES2015 / ES6 기능으로 ES5 이하와 비교하여 참신한 방법으로 문자열로 작업 할 수 있습니다. 첫눈에 구문은 매우 간단합니다. 작은 따옴표 나 큰 따옴표 대신 백틱을 사용하십시오.
const a_string = `something`
그들은 일반적인 문자열이 따옴표로 작성된 많은 기능을 제공하기 때문에 고유합니다.
Pre-ES6, 두 줄에 걸쳐있는 문자열을 만들려면 줄 끝에 \ 문자를 사용해야합니다.
const string = 'first part \ second part'
이렇게하면 2 줄에 문자열을 만들 수 있지만 한 줄에만 렌더링됩니다.
first part second part
문자열을 여러 줄에 렌더링하려면 다음과 같이 각 줄의 끝에 \n을 명시 적으로 추가해야합니다.
const string = 'first line\n \ second line'
또는
const string = 'first line\n' + 'second line'
Template 리터럴은 여러 줄을 훨씬 단순하게 만듭니다. 템플리트 리터럴이 백틱과 함께 열리면 특수 문자가없는 새 행을 작성하려면 enter를 눌러 그대로 표시됩니다.
const string = `Hey this string is awesome!`
템플릿 리터럴은 변수와 표현식을 문자열로 쉽게 삽입 할 수있는 방법을 제공합니다.
${…} 구문을 사용하면 이렇게 할 수 있습니다.
const var = '테스트' const string =`something $ {var}`// 무언가 테스트
${} 안에는 표현식도 추가 할 수 있습니다.
const string =`something $ {1 + 2 + 3}` const string2 =`something $ {foo ()? 'x': 'y'}`
태그가 추가 된 템플릿은 처음에는 덜 유용하게 들릴 수 있지만, Styled Components 나 Apollo, GraphQL 클라이언트/서버 라이브러리와 같이 인기있는 많은 라이브러리에서 실제로 사용됩니다. 따라서 어떻게 작동하는지 이해하는 것이 필수적입니다. Styled Components에서 템플릿 태그는 CSS 문자열을 정의하는 데 사용됩니다.
const Button = styled.button` font-size: 1.5em; background-color: black; color: white; `;
Apollo에서 템플릿 태그는 GraphQL 쿼리 스키마를 정의하는 데 사용됩니다.
const query = gql` query { ... } `
이 예제에서 강조 표시된 styled.button 및 gql 템플릿 태그는 단지 함수입니다.
function gql(literals, ...expressions) { }
이 함수는 모든 종류의 계산 결과 일 수있는 문자열을 반환합니다.
리터럴은 표현식 보간에 의해 토큰 화 된 템플릿 리터럴 내용을 포함하는 배열입니다.
expressions에는 모든 보간이 포함됩니다.
위 예제를 취하면 :
const string = `something ${1 + 2 + 3}`
리터럴은 두 개의 항목이있는 배열입니다. 첫 번째 보간은 첫 번째 보간까지의 문자열이고 두 번째는 빈 문자열입니다. 첫 번째 보간의 끝 (문자열이 하나뿐입니다)과 문자열의 끝 사이의 공백입니다. 이 경우 표현식은 단일 항목이 6 인 배열입니다. 보다 복잡한 예제는 다음과 같습니다.
const string = `something another ${'x'} new line ${1 + 2 + 3} test`
이 경우 리터럴은 첫 번째 항목이있는 배열입니다. `something another` 두 번째는 : ` new line` 세 번째는 : ` test` 이 경우 식은 x와 6의 두 항목이있는 배열입니다.
이 값들이 전달되는 함수는 그것들과 함께 무엇이든 할 수 있으며, 이것은 이런 종류의 기능의 힘입니다. 가장 간단한 예제는 문자열 보간이 단순히 리터럴과 표현식을 결합하여 복제하는 것입니다.
const interpolated = interpolate`I $ {10} €`
이것이 interpolate의 작동하는 방법입니다.
function interpolate(literals, ...expressions) { let string = `` for (const [i, val] of expressions.entries()) { string += literals[i] + val } string += literals[literals.length - 1] return string }
이제는 일반적인 개요에서부터 사용법을 개선하는 작은 세부 사항에 이르기까지 모든 기능에 대해 배우게됩니다. 자바 스크립트의 모든 기능은 함수에서 발생합니다. 함수는 한 번 정의되고 원하는 횟수만큼 실행될 수있는 코드 블록 (자체 포함)입니다. 함수는 선택적으로 매개 변수를 받아 들일 수 있으며 하나의 값을 반환합니다. JavaScript의 함수는 특별한 종류의 Object인 function objects입니다. 그들의 초강대국은 그들이 부름받을 수 있다는 사실에 있습니다. 또한 함수는 값에 할당 될 수 있고 first class function(1차 클래스 함수)라고하며 인수로 전달되고 반환 값으로 사용될 수 있습니다. ES6 / ES2015 이전 구문부터 시작하겠습니다. 다음은 함수 선언입니다.
function dosomething(foo) { // do something }
이제 regular function(정규 함수)이라고하는 ES6 / ES2015 이후의 세계에서 함수를 변수에 할당 할 수 있습니다 (function expression(함수 표현식)이라고 함).
const dosomething = function(foo) { // do somethind }
Named function expressions(명명된 함수 표현식)은 비슷하지만 스택 호출 추적을 통해 더 잘 수행됩니다.이 함수는 오류가 발생했을 때 유용하며 함수의 이름을 포함합니다.
const dosomething = function dosomething(foo) { // do somethind }
ES6 / ES2015에서는 arrow functions(화살표 함수)를 도입했습니다. 이는 인라인 함수, 매개 변수 또는 콜백으로 작업 할 때 특히 유용합니다.
const dosomething = foo => { // do something }
화살표 함수는 위의 다른 함수 정의와 중요한 차이점이 있으며, 이후에 고급 함수라는 것을 알 수 있습니다.
함수는 하나이상의 매개변수를 가질수 있습니다.
const dosomething = () => { //do something } const dosomethingElse = foo => { //do something } const dosomethingElseAgain = (foo, bar) => { //do something }
ES6 / ES2015부터 함수는 매개 변수에 대한 기본값을 가질 수 있습니다.
const dosomething = (foo = 1, bar = 'hey') => { //do something }
이렇게하면 모든 매개 변수를 채우지 않고 함수를 호출 할 수 있습니다.
dosomething(3) dosomething()
ES2018은 매개 변수에 후행 쉼표를 추가하여 매개 변수 주위를 이동할 때 쉼표가 누락되어 버그를 줄이는 데 도움이되는 기능을 제공합니다 (예 : 가운데 마지막 이동).
const dosomething = (foo = 1, bar = 'hey') => { //do something } dosomething(2, 'ho!')
모든 인수를 배열로 래핑하고 함수를 호출 할 때 spread 연산자를 사용할 수 있습니다.
const dosomething = (foo = 1, bar = 'hey') => { //do something } const args = [2, 'ho!'] dosomething(...args)
많은 매개 변수를 사용하면 순서를 기억하는 것이 어려울 수 있습니다. 객체를 사용하면 매개 변수 이름을 유지할 수 있습니다.
const dosomething = ({ foo = 1, bar = 'hey' }) => { //do something console.log(foo) // 2 console.log(bar) // 'ho!' } const args = { foo: 2, bar: 'ho!' } dosomething(args)
모든 함수는 값을 리턴합니다. 디폴트는 undefined입니다.
> const dosomething = (foo = 1, bar = 'hey') => { // do something } <- undefined > dosomething() <- undefined
모든 함수는 코드 행이 끝나거나 실행 흐름이 return 키워드를 찾으면 종료됩니다. JavaScript가이 키워드를 만나면 함수 실행을 종료하고 호출자에게 다시 제어권을 부여합니다. 값을 전달하면 해당 값이 함수의 결과로 반환됩니다.
const dosomething = () => { return 'test' } const result = dosomething() // result === 'test'
하나의 값만 반환 할 수 있습니다.
여러 값을 반환하는 것을 시뮬레이트하기 위해 객체 리터럴 또는 배열을 반환하고 함수를 호출 할 때 소멸 할당을 사용할 수 있습니다.
배열 사용 :하나의 값만 반환 할 수 있습니다.
여러 값을 반환하는 것을 시뮬레이트하기 위해 객체 리터럴 또는 배열을 반환하고 함수를 호출 할 때 소멸 할당을 사용할 수 있습니다.
배열 사용 :
함수는 다른 함수 안에 정의할 수 있다.
const dosomething = () => { const dosomethingelse = () => {} dosomethingelse() return 'test' }
중첩 된 함수는 외부 함수로 범위가 지정되며 외부에서 호출 할 수 없습니다.
객체 속성으로 사용될 때 함수를 메서드라고 부릅니다.
const car = { brand: 'Ford', model: 'Fiesta', start: function() { console.log(`Started`) } } car.start()
객체 메소드로 사용될 때 Arrow Functions 대 일반 함수의 중요한 동작이 있습니다. 다음 예제를 주목하십시오.
const car = { brand: 'Ford', model: 'Fiesta', start: function() { console.log(`Started ${this.brand} ${this.model}`) }, stop: () => { console.log(`Stopped ${this.brand} ${this.model}`) } }
이는 두 함수 선언스타일에서 this 처리 방법이 다르기 때문입니다. 이것은 화사표함수에서 this 함수를 포함하는 함수 컨텍스트를 참조합니다. 이 경우에는 window 개체입니다.
this, function()을 사용하여 호스트객체를 참조함니다.
이는 화살표함수가 객체 메소드 및 생성자에 사용하기에 적합하지 않다는 것을 의미합니다 (화살표 함수 생성자는 실제로 호출 될 때 TypeError를 발생시킵니다).
IIFE는 함수를 선언 후에 바로 즉시 실행하는 함수이다.
;(function dosomething() {
console.log('executed')
})()
결과를 변수에 지정 할 수 있다.
const something = (function dosomething() { return 'something' })()
함수를 정의한 후에 별도로 함수를 호출 할 필요가 없으므로 매우 편리합니다.
코드를 실행하기 전에 JavaScript는 몇 가지 규칙에 따라 재정렬합니다. 특히 함수는 범위의 맨 위로 이동합니다. 이것이 왜 합법적인가?
dosomething() function dosomething() { console.log('did something') }
내부적으로 JavaScript는 호출 전에 함수를 이동시키고 같은 범위에있는 다른 모든 함수를 이동합니다.
function dosomething() { console.log('did something') } dosomething()
이제 명명 된 함수 표현식을 사용하면 변수를 사용하기 때문에 다른 결과가 발생합니다. 변수선언은 끌어 올렸지만 값이 아니기 때문에 함수가 아닙니다.
dosomething() const dosomething = function dosomething() { console.log('did something') }
일하지 않을 것이다:
내부적으로 발생하는 것은 다음과 같습니다.
const dosomething dosomething() dosomething = function dosomething() { console.log('did something') }
let선언에서도 마찬가지입니다. var선언은 작동하지 않지만 다른 오류가 있습니다.
이것은 var선언은 값으로 undefined로 초기화되고 초기화되는 반면 const 및 let은 초기화되지만 초기화되지 않기 때문입니다.
화살표 기능은 ES6 / ES2015에서 가장 영향력있는 변화 중 하나이며 요즘 널리 사용됩니다. 정규 기능과 약간 다릅니다. 아래에서 어떻게 보죠. 위의 화살표 함수를 이미 소개했지만 중요한 것은 자체 섹션이 필요합니다. Arrow 함수는 ES6 / ECMAScript 2015에서 소개되었으며, 소개 이후 JavaScript 코드가 어떻게 보이고 (작동하는지) 영원히 바뀌 었습니다. 필자의 의견으로는이 변화가 매우 환영 받기 때문에 현재의 코드베이스에서는 function 키워드의 사용법을 거의 볼 수 없다. 시각적으로 간단하고 환영할만한 변경입니다. 다음과 같은 짧은 구문으로 함수를 작성할 수 있습니다.
const myFunction = function foo() { //... } 이렇게 const myFunction = () => { //... }
만약 함수본문이 단지 한 문자이라면, 중괄호를 제거하고 한줄에 쓸 수 있다.
const myFunction = () => doSomething()
매개변수는 괄호안에 전달됩니다.
const myFunction = (param1, param2) => doSomething(param1, param2)
만약 하나의 매개변수만 있다면, 괄호도 제거할 수 있다.
const myFunction = param => doSomething(param)
이 짧은 구문으로 인해 작은 기능은 화살표함수의 사용을 권장합니다.
화살표 함수를 사용하면 암시적으로 반환 할 수 있습니다. return키워드를 사용하지 않아도 값이 반환됩니다.
함수 본문에 온라인 문이 있을 때 작동합니다.
const myFunction = () => 'test' myFunction() // 'test'
또 다른 예는 객체를 반환하는 것입니다 (괄호 안에 포장 괄호를 넣으면 포장 괄호로 묶지 않습니다).
const myFunction = () => ({value: 'test'}) myFunction() //{value: 'test'}
this는 컨텍스트에 따라 많이 달라지며 JavaScript (엄격모드 또는 비엄격모드)의 모드에 따라 달라지기 때문에 이해하기가 복잡 할 수 있는 개념입니다.
화살표 함수는 일반 함수와 매우 다르게 동작하므로 이 개념을 명확히하는 것이 중요합니다.
객체의 메소드로 정의 될 때, 정규 함수에서 이것은 객체를 참조하므로 다음을 수행 할 수 있습니다.
const car = { model: 'Fiesta', manufacturer: 'Ford', fullName: function() { return `${this.manufacturer} ${this.model}` } }
car.fullName()을 호출하면 “Ford Fiesta”를 출력한다.
화살표함수가 있는 this범위는 실행 컨텍스트에서 상속됩니다. 화살표 함수는 this을 전혀 바인드하지 않으므로이 값은 호출 스택에서 조회 될 것이므로 이 코드에서 car.fullName()은 작동하지 않고 “undefined undefined”라는 문자열을 반환합니다.
const car = { model: 'Fiesta', manufacturer: 'Ford', fullName: () => { return `${this.manufacturer} ${this.model}` } }
이 때문에 화살표 함수는 객체 메소드로 적합하지 않습니다.
화살표 함수는 객체를 인스턴스화 할 때 생성자로도 사용할 수 없습니다. TypeError가 발생합니다.
동적 컨텍스트가 필요하지 않은 경우 정규 함수를 대신 사용해야합니다.
이것은 또한 이벤트를 처리 할 때 문제가됩니다. DOM 이벤트 리스너는 this을 대상 요소로 설정하고, 이벤트 핸들러에서 this을 사용한다면 정규 함수가 필요합니다.
const link = document.querySelector('#link') link.addEventListener('click', () => { // this === window }) const link = document.querySelector('#link') link.addEventListener('click', function() { // this === link })
다음은 JavaScript 함수가 작동하는 방식을 이해하는 데 핵심인 클로저 주제에 대해 자세히 설명합니다. 자바스크립트에서 함수를 작성해 본 적이 있다면 이미 클로저를 사용하고있는 것입니다. 이해해야 할 중요한 주제이며, 할 수 있는 일에 의미가 있습니다.
함수가 실행될 때, 정의된 시점에 실행된 범위로 실행되고, 실행될 때 상태로 실행되지 않습니다.
범위는 기본적으로 보이는 변수 세트입니다. 함수는 해당 어휘 범위를 기억하고 부모 범위에 정의 된 변수에 액세스 할 수 있습니다. 간단히 말해서, 함수는 액세스 할 수 있는 변수의 전체 수하물을 가지고 있습니다. 이것을 분명히하기위한 예를 즉시 알려 드리겠습니다.
const bark = dog => { const say = `${dog} barked!` ;(() => console.log(say))() } bark(`Roger`)
이것은 예상대로 콘솔에 Roger barked!를 로그한다.
대신 액션을 반환하려면 어떻게해야합니까?
const prepareBark = dog => { const say = `${dog} barked!` return () => console.log(say) } const bark = prepareBark(`Roger`) bark()
console에 Roger barked!를 로그한다.
두 개의 다른 개를 위해 prepareBark를 다시 사용하는 마지막 예를 하나 만들어 보겠습니다.
const prepareBark = dog => { const say = `${dog} barked!` return () => { console.log(say) } } const rogerBark = prepareBark(`Roger`) const sydBark = prepareBark(`Syd`) rogerBark() sydBark()
이출력은:
Roger barked! Syd barked!
보시다시피, 변수의 상태는 prepareBark()에서 반환 된 함수에 연결됩니다. 또한 두 번째로 prepareBark()를 호출 할 때 새로운 say 변수를 다시 정의하지만 첫 번째 prepareBark() 범위의 상태에는 영향을 미치지 않습니다. 클로저가 작동하는 방식입니다. 반환 된 함수는 원래 상태를 유지합니다.
시간이 지남에 따라 자바스크립트 배열은 점점 더 많은 기능을 가지며 때로는 어떤 구조와 다른 구조를 사용해야 할지를 아는 것이 까다로운 경우가 있습니다. 이 섹션에서는 2018 년부터 사용해야 할 것을 설명하고자합니다.
const a = [] const a = [1, 2, 3] const a = Array.of(1, 2, 3) const a = Array(6).fill(1) //init an array of 6 items of value 1
이전 구문을 사용하지 마십시오 (입력 된 배열에만 사용).
const a = new Array() // never use const a = new Array(1, 2, 3) // never use
const l = a.length
a.every(f)
f()가 false를 반환 할 때까지 a를 반복합니다.
예제
// Check if everybody has 18 years old of more. var ages = [30, 43, 18, 5]; ages.every(function(elem) { return elem >= 18; }); // Output: false
a.some(f)
f()가 true를 반환 할 때까지 a를 반복합니다.
const b = a.map(f)
a를 반복하고 각 요소에 대해 f()를 실행 한 결과로 새 배열을 작성합니다.
// Let's upper case the items in the array ['bob', 'joe', 'jen'].map(function(elem) { return elem.toUpperCase(); }); // Output: ['BOB', 'JOE', 'JEN']
const b = a.filter(f)
a를 반복하고 각 요소에서 f()를 실행할 때 true를 반환하는 요소를 사용하여 새 배열을 작성합니다. 예제:
// Finding the even numbers [1,2,3,4,5,6].filter(function(elem){ return (elem % 2 == 0) }); // Output: [2,4,6]
a.reduce((accumulator, currentValue, currentIndex, array) => { //... }, initialValue)
reduce()는 배열의 모든 항목에 대해 콜백 함수를 실행하고 점진적으로 결과를 계산할 수 있도록합니다. initialValue를 지정하면 첫 번째 반복의 누적 기가 해당 값과 같습니다.
예제:
;[1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => { return accumulator * currentValue }, 1) // iteration 1: 1 * 1 => return 1 // iteration 2: 1 * 2 => return 2 // iteration 3: 2 * 3 => return 6 // iteration 4: 6 * 4 => return 24 // return value is 24
[1,2,3,4].reduce(function(previous, current) { return previous + current; }); // Output: 10 // 1st iteration: previous=1, current=2 => result=3 // 2nd iteration: previous=3, current=3 => result=6 // 3rd iteration: previous=6, current=4 => result=10
ES6
a.forEach(f)
멈출 방법없이 f를 반복합니다.
예제:
a.forEach(v => { console.log(v) })
ES6
for (let v of a) { console.log(v) }
for (let i = 0; i < a.length; i += 1) { //a[i] }
a를 반복하며, return과 break를 사용하며 멈출수 있고, continue를 이용하여 건너뛸 수 있다.
ES6
배열로부터 iterator를 얻는 것은 값의 반복자를 반환한다.
const a = [1, 2, 3] let it = a[Symbol.iterator]() console.log(it.next().value) //1 console.log(it.next().value) //2 console.log(it.next().value) //3
.entries() key/value쌍의 iterator를 반환한다.
const a = [1, 2, 3] let it = a.entries() console.log(it.next().value) //[0, 1] console.log(it.next().value) //[1, 2] console.log(it.next().value) //[2, 3]
.keys()는 key들의 반복자로 사용할 수 있다.
let it = a.keys() console.log(it.next().value) //0 console.log(it.next().value) //1 console.log(it.next().value) //2
.next()는 배열의 끝이면 undefined를 리턴한다. it.next()를 보면 iteration을 종료했는지 여부를 감지 할 수 있는 value, done쌍을 리턴한다. done은 true를 반환하는 마지막 요소까지 항상 false입니다.
a.push(4)
a.unshift(0) a.unshift(-2,-1)
a.pop()
a.shift()
a.splice(0,2) get the first 2 items a.splice(3,2) get then 2 items starting from index 3
정의되지 않은 값을 남기므로 remove()를 사용하지 마십시오.
a.splice(2, 3, 2, 'a', 'b')
// removes 3 items starting from // index 2, and add 2 items, // still starting from index 2
const a = [1, 2] const b = [3, 4] a.concat(b) // 1, 2, 3, 4
a.indexOf() 첫번째 찾은 항목의 index를 리턴, 못 찾으면 -1를 리턴
a.lastIndexOf() 마지막 찾은 항목의 index를 리턴, 못 찾으면 -1를 리턴
a.find((element, index, array) => { // return true or false })
true를 반환하는 첫번째 항목를 리턴, 못 찾으면 undefined를 반환
일반적으로 사용되는 문법은:
a.find(x => x.id === my_id)
위의 행은 id === my_id 인 배열의 첫 번째 요소를 반환합니다.
findIndex는 true를 반환하는 첫 번째 항목의 인덱스를 반환하고 찾지 못한 경우 undefined를 반환합니다.
a.findIndex((element, index, array) => { //return true or false })
a.includes(value)
a가 value를 갖지고 있으면 true를 반환
a.includes(value, i)
a가 value를 i위치 이후로 가지면 true를 반환
aslice()
알파벳 정렬(ASCII값에 의해서 - 0-9A-Za-z)
const a = [1, 2, 3, 10, 11] a.sort() //1, 10, 11, 2, 3 const b = [1, 'a', 'Z', 3, 2, 11] b = a.sort() //1, 11, 2, 3, Z, a
사용자함수에 의해서 정렬
const a = [1, 10, 3, 2, 11] a.sort((a, b) => a - b) // 1, 2, 3, 10, 11
배열의 역순
a.reverse()
a.toString()
배열의 문자열 표현을 얻음
a.join()
배열 요소의 문자열 연결을 반환합니다. 매개 변수를 전달하여 맞춤 구분 기호 추가
a.join(', ')
const b = Array.from(a) const b = Array.of(...a)
const a = [1, 2, 3, 4] a.copyWithin(0, 2) // [3, 4, 3, 4] const b = [1, 2, 3, 4, 5] b.copyWithin(0, 2) // [3, 4, 5, 4, 5] //0 is where to start copying into, // 2 is where to start copying from const c = [1, 2, 3, 4, 5] c.copyWithin(0, 2, 4) // [3, 4, 3, 4, 5] //4 is an end index
JavaScript는 루프를 반복하는 여러 가지 방법을 제공합니다. 이 섹션에서는 작은 예제와 주요 속성을 가진 최신 자바 스크립트의 모든 다양한 루프 가능성을 설명합니다.
for
const list = ['a', 'b', 'c'] for (let i = 0; i < list.length; i++) { console.log(list[i]) //value console.log(i) //index }
break를 사용해서 for루프를 인터럽트 할 수 있다.continue를 사용하여 for루프의 다음 반복으로 빨리 진행 할 수 있습니다.
ES5에 도입되었습니다. 배열이 주어지면 list.forEach()를 사용하여 속성을 반복 할 수 있습니다.
const list = ['a', 'b', 'c'] list.forEach((item, index) => { console.log(item) //value console.log(index) //index }) //index is optional list.forEach(item => console.log(item))
불행하게도 이 루프를 벗어날 수는 없습니다.
const list = ['a', 'b', 'c'] let i = 0 do { console.log(list[i]) //value console.log(i) //index i = i + 1 } while (i < list.length)
break를 사용하여 while루프를 벗어날 수 있습니다.
do { if (something) break } while (true)
const list = ['a', 'b', 'c'] let i = 0 while (i < list.length) { console.log(list[i]) //value console.log(i) //index i = i + 1 }
break를 사용하여 while루프를 빠져나 갈 수 있다.
while (true) { if (something) break }
그리고 continue를 사용하여 다음 반복으로 점프 할 수 있다.
while (true) { if (something) continue //do something else }
do…while의 차이점은 do…while은 적어도 한 싸이클은 항상 실행한다.
개체의 열거 가능한 모든 속성을 반복하여 속성 이름을 제공합니다.
for (let property in object) { console.log(property) // property name console.log(object[property]) //property value }
ES2015는 forEach의 간결함과 중단 기능을 결합한 for … of 루프를 도입했습니다.
//iterate over the value for (const value of ['a', 'b', 'c']) { console.log(value) //value } //get the index as well, using `entries()` for (const [index, value] of ['a', 'b', 'c'].entries()) { console.log(index) //index console.log(value) //value }
'for…in'과의 차이점은 …
for…of는 property values(속성값)으로 반복한다.for…in은 property names(속성명)으로 반복한다.브라우저의 JavaScript는 이벤트 중심 프로그래밍 모델을 사용합니다. 모든 것은 사건을 따라 시작합니다. 이 섹션에서는 JavaScript 이벤트에 대한 소개와 이벤트 처리 방법에 대해 설명합니다.
브라우저의 JavaScript는 이벤트 중심 프로그래밍 모델을 사용합니다.
모든 것은 사건을 따라 시작합니다.
이 이벤트는 DOM이로드되거나 가져 오기를 완료하는 비동기 요청이거나 사용자가 요소를 클릭하거나 페이지를 스크롤하거나 키보드의 사용자 유형 일 수 있습니다.
서로 다른 종류의 이벤트가 있습니다.
이벤트가 발생할 때 호출되는 함수 인 이벤트 핸들러(event handlers)를 사용하여 모든 이벤트에 응답 할 수 있습니다.
동일한 이벤트에 대해 여러 핸들러를 등록 할 수 있으며 해당 이벤트가 발생할 때 모두 호출됩니다.
JavaScript는 이벤트 처리기를 등록하는 세 가지 방법을 제공합니다.
이 스타일의 이벤트 핸들러는 제한 사항으로 인해 오늘날 거의 사용되지 않지만 자바 스크립트 초기에는 유일한 방법이었습니다.
<a href="site.com" onclick="dosomething();">A link</a>
이 경우 객체에 여러 개의 핸들러를 추가 할 방법이 없으므로 객체에 최대 하나의 이벤트 핸들러가있는 경우 일반적입니다.
window.onload = () => { //window loaded }
XHR 요청을 처리 할 때 가장 일반적으로 사용됩니다.
const xhr = new XMLHttpRequest() xhr.onreadystatechange = () => { //.. do something }
if ('onsomething' in window) {}를 사용하여 핸들러가 이미 속성에 할당되었는지 확인할 수 있습니다.
이것은 현대적인 방법입니다. 이 메소드를 사용하면 필요한만큼 핸들러를 등록 할 수 있으며 가장 많이 사용되는 핸들러를 찾을 수 있습니다.
window.addEventListener('load', () => { //window loaded })
IE8 이하에서는이 기능을 지원하지 않고 대신 자체attachEvent()API를 사용했습니다. 이전 브라우저를 지원해야하는 경우 계속 기억하십시오.
키보드 사용과 같이 window에서 “글로벌” 이벤트를 가로 채기 위해 들을 수 있으며, 마우스 클릭 버튼처럼 특정 요소에 귀를 기울여 이벤트가 발생하는지 확인할 수 있습니다.
이것이 addEventListener가 때때로 윈도우에서, 때로는 DOM 요소에서 호출되는 경우입니다.
이벤트 핸들러는 첫 번째 매개 변수로 Event 객체를 가져옵니다.
const link = document.getElementById('my-link') link.addEventListener('click', event => { // link clicked })
이 객체에는 다음과 같은 유용한 속성 및 메서드가 많이 포함되어 있습니다.
target, 이벤트를 발생시킨 DOM요소type, 이벤트의 typestopPropagation(), DOM에서 이벤트의 전파를 멈추기 위해서 호출이벤트는 특정 이벤트에 대한 인터페이스이므로 다른 속성은 특정 종류의 이벤트에 의해 제공됩니다.
각각 MDN 페이지가 링크되어있어 모든 속성을 검사 할 수 있습니다. 예를 들어 KeyboardEvent가 발생하면 키 속성을 확인하여 읽을 수있는 형식 (Escape, Enter 등)으로 눌려진 키를 확인할 수 있습니다.
window.addEventListener('keydown', event => { // key pressed console.log(event.key) })
마우스 이벤트에서 어떤 마우스 버튼이 눌려 졌는지 확인할 수 있습니다 :
const link = document.getElementById('my-link') link.addEventListener('mousedown', event => { // mouse button pressed console.log(event.button) //0=left, 2=right })
버블링 및 캡처는 이벤트가 전파하는 데 사용하는 두 가지 모델입니다.
DOM 구조가 있다고 가정 해 보겠습니다.
<div id="container"> <button>Click me</button> </div>
사용자가 버튼을 클릭 할 때를 추적하면 button에 하나 그리고 #container에 하나씩 하여 두 개의 이벤트 리스너가 있다. 전달을 중지하지 않는 한 자식 요소에 대한 클릭은 부모 노드에 항상 전파된다는 것을 기억하십시오 (나중에 살펴 보겠습니다).
이러한 이벤트 리스너는 순서대로 호출되며이 순서는 사용된 이벤트 버블링 / 캡처 모델에 의해 결정됩니다.
Bubbling은 이벤트가 클릭 된 항목 (하위 항목)에서 모든 상위 트리까지 가장 가까운 항목에서부터 전파됨을 의미합니다.
이 예제에서는 button핸들러가 #container핸들러보다 먼저 실행됩니다.
Capturing는 반대입니다. 바깥 쪽 이벤트 처리기는 더 구체적인 처리기(button에 하나)보다 먼저 발생합니다.
addEventListener에 세 번째 인수를 적용하여 true로 설정하여 이벤트 캡처를 채택하도록 선택할 수 있습니다.
document.getElementById('container').addEventListener( 'click', () => { //window loaded }, true )
모든 캡처 이벤트 처리기가 먼저 실행됩니다.
그런 다음 모든 버블링 이벤트 핸들러.
순서는 다음과 같은 원칙을 따릅니다: DOM은 Window 객체에서 시작하는 모든 요소를 거치고 클릭 된 항목을 찾습니다. 그렇게하는 동안 이벤트와 연결된 모든 이벤트 핸들러를 호출합니다 (캡처 단계).
일단 목표에 도달하면 Window 객체가 다시 이벤트 핸들러를 호출 할 때까지 부모 트리까지의 여행을 반복합니다 (버블링 단계).
DOM 요소의 이벤트는 중지되지 않는 한 모든 부모 요소 트리로 전파됩니다.
<html> <body> <section> <a id="my-link" ...>
a클릭 이벤트는 section 및 body로 전파됩니다.
이벤트의 stopPropagation() 메서드를 호출하여 전파를 중지 할 수 있습니다. 대개 이벤트 처리기의 끝에서 수행합니다.
const link = document.getElementById('my-link')
link.addEventListener('mousedown', event => {
// process the event
// ...
event.stopPropagation()
})
다음은 가장 일반적인 이벤트 목록입니다.
페이지로드가 완료되면 window 및 body 요소에서 로드가 시작됩니다.
클릭하면 마우스 버튼을 클릭하면 실행됩니다. 마우스를 두 번 클릭하면 dblclick됩니다. 물론 이 경우 click은이 이벤트 직전에 해고됩니다. mousedown, mousemove 및 mouseup을 조합하여 드래그 앤 드롭 이벤트를 추적 할 수 있습니다. mousemove에주의하십시오. 마우스 이동 중에 여러 번 발사되기 때문에 (나중에 조절 참조)
keydown은 키보드 버튼을 눌렀을 때 (그리고 버튼이 눌려져있는 동안 키가 반복 될 때) 발동됩니다. keyup 키를 놓으면 keyup이 시작됩니다.
scroll 이벤트는 페이지를 스크롤 할 때마다 창에서 시작됩니다. 이벤트 처리기 내에서 window.scrollY (Y 축)를 확인하여 현재 스크롤 위치를 확인할 수 있습니다.
이 이벤트는 일회성 이벤트가 아니라는 점을 명심하십시오. 스크롤링이 끝날 때나 시작될 때뿐만 아니라 스크롤하는 동안 많은 시간이 소요되기 때문에 핸들러에서 무거운 계산이나 조작을하지 마십시오. 대신 throttling을 사용하십시오.
위에서 언급했듯이 mousemove와 scroll은 이벤트 당 한 번만 실행되는 것이 아니라 액션이 지속되는 동안 지속적으로 이벤트 핸들러 함수를 호출하는 두 가지 이벤트입니다. 이는 좌표를 제공하기 때문에 좌표를 제공하기 때문에 발생하는 상황을 추적 할 수 있기 때문입니다. 이벤트 처리기에서 복잡한 작업을 수행하면 성능에 영향을 미치고 사이트 사용자에게 느린 사용 경험을 유발할 수 있습니다. Lodash와 같은 제한 기능을 제공하는 라이브러리는 가능한 모든 유스 케이스를 처리하기 위해 100 줄 이상의 코드로 구현합니다. 간단하고 이해하기 쉬운 구현은 setTimeout을 사용하여 100ms마다 스크롤 이벤트를 캐시하는 this입니다.
let cached = null window.addEventListener('scroll', event => { if (!cached) { setTimeout(() => { //you can access the original event at `cached` cached = null }, 100) } cached = event })
이벤트 루프는 자바 스크립트를 이해하는 데 가장 중요한 요소 중 하나입니다.
필자는 JavaScript로 수년간 프로그래밍 해왔지만, 후드에서 어떻게 작동하는지 완전히 이해하지 못했습니다. 이 개념을 자세히 알지 못하는 것은 완전히 멋지지만 평소와 같이 어떻게 작동하는지 알면 도움이됩니다. 또한이 시점에서 좀 궁금해 할 수도 있습니다.
이 섹션에서는 JavaScript가 단일 스레드에서 작동하는 방법과 비동기 함수를 처리하는 방법에 대해 자세히 설명합니다.
JavaScript 코드는 단일 스레드로 실행됩니다. 한 번에 한 가지 일이 발생합니다.
이는 동시성 문제에 대해 걱정하지 않고 프로그래밍하는 방법을 단순화하므로 실제로 매우 유용합니다.
코드 작성 방법에주의를 기울여야하며 동기식 네트워크 호출이나 무한 루프와 같이 스레드를 차단할 수있는 요소는 피하십시오.
일반적으로 대부분의 브라우저에는 모든 브라우저 탭에 대한 이벤트 루프가있어 모든 프로세스를 격리하고 전체 루프를 차단하는 무한 루프 또는 무거운 처리가있는 웹 페이지를 피할 수 있습니다.
환경은 여러 개의 동시 이벤트 루프를 관리하여 예를 들어 API 호출을 처리합니다. 웹 작업자는 자체 이벤트 루프에서도 실행됩니다.
주로 코드가 단일 이벤트 루프에서 실행되고 코드를 차단하지 않도록이 코드를 염두에 두어야합니다.
이벤트 루프로 제어를 되돌리는데 너무 시간이 걸리는 JavaScript코드는 페이지의 모든 JavaScript 코드 실행을 차단하고 UI스레드를 차단하며 사용자는 클릭하거나 페이지를 스크롤 할 수 없습니다.
JavaScript의 거의 모든 I/O 프리미티브는 비 블로킹입니다. 네트워크 요청, Node.js 파일 시스템 작업 등. 블로킹이 예외이며, 이것이 JavaScript가 callback에 기반하고 있는 이유이며, 최근에는 promises(약속) 및 async/await(비동기/대기)에 기반합니다.
호출 스택은 LIFO queue (Last In, First Out)입니다. 이벤트 루프는 call stack(호출 스택)을 계속 검사하여 실행해야하는 기능이 있는지 확인합니다.
그렇게하는 동안 발견 한 함수 호출을 호출 스택에 추가하고 각 호출을 순서대로 실행합니다.
디버거 또는 브라우저 콘솔에서 익숙한 오류 스택 추적을 알고 있습니까? 브라우저는 호출 스택에서 함수 이름을 찾아 어떤 함수가 현재 호출을 시작했는지 알려줍니다.
예제를 골라봅시다:
const bar = () => console.log('bar') const baz = () => console.log('baz') const foo = () => { console.log('foo') bar() baz() } foo()
이 코드는
foo bar baz
로 출력되는 것을 예상합니다.
이 시점에서 호출 스택은 다음과 같습니다.
모든 반복에서 이벤트 루프는 호출 스택에 무언가가 있는지 찾아서 실행합니다.
모든 call stack이 빌때까지.
위의 예는 정상적으로 보입니다. 특별한 것은 없습니다. JavaScript는 실행해야 할 것을 찾고, 순서대로 실행합니다.
스택이 깨끗해질 때까지 함수를 연기하는 방법을 살펴 보겠습니다.
setTimeout( () ⇒ {}), 0)의 사용 예는 함수를 호출하는 것이지만 코드의 다른 모든 함수가 실행 된 후에는 함수를 호출하는 것입니다.
이 예제를 보자.
const bar = () => console.log('bar') const baz = () => console.log('baz') const foo = () => { console.log('foo') setTimeout(bar, 0) baz() } foo()
이 코드는 아마 놀랍게도 다음를 출력한다.
foo baz bar
이 코드가 실행되면 먼저 foo()가 호출됩니다. foo() 내부에서 우리는 먼저 bar를 인수로 전달하여 setTimeout을 호출하고 타이머를 0으로 전달하면서 가능한 한 빨리 실행하도록 지시합니다. 그런 다음 baz()를 호출합니다.
이 시점에서 호출 스택은 다음과 같습니다.
다음은 프로그램의 모든 함수에 대한 실행 순서입니다.
왜 이런 일이 일어나는 걸까요?
setTimeout()이 호출되면 Browser 또는 Node.js가 타이머를 시작합니다. 타이머가 만료되면 이 경우 즉시 0으로 설정하여 콜백 함수가 Message Queue에 저장됩니다.
Message Queue는 클릭 이벤트나 키보드 이벤트 또는 응답 가져 오기와 같은 사용자가 시작한 이벤트가 코드에 응답 할 기회가 오기 전에 대기합니다. 또는 onLoad와 같은 DOM 이벤트.
루프는 호출 스택에 우선 순위를 부여하고, 호출 스택에서 찾은 모든 것을 먼저 처리하고 거기에 아무 것도 없으면 이벤트 대기열에서 항목을 선택합니다.
우리는 setTimeout, fetch 또는 다른 것들을 브라우저가 제공하기 때문에 자신의 작업을 수행 할 때까지 기다릴 필요가 없습니다. 예를 들어, setTimeout 시간 초과를 2초로 설정하면 2초를 기다릴 필요가 없습니다. 대기는 다른 곳에서 발생합니다.
ECMAScript 2015는 Promises가 사용하는 Job Queue 개념을 도입했습니다 (ES6/ES2015에서도 소개 됨). 이것은 호출 스택의 끝에 놓기보다는 가능한 한 빨리 비동기 함수의 결과를 실행하는 방법입니다.
현재 함수가 끝나기 전에 해결되는 약속은 현재 함수 바로 다음에 실행됩니다.
놀이공원에서의 롤러코스터 타기의 유추는 좋은 설명합니다: 메시지 큐는 당신이 줄에 있는 다른 모든 사람들과 함께 줄을 서게 하고, 직업 큐는 당신이 이전 것을 마친 직후에 또 다른 놀이기구를 탈 수 있게 해주는 고속 통행 티켓이다. 예 :
const bar = () => console.log('bar') const baz = () => console.log('baz') const foo = () => { console.log('foo') setTimeout(bar, 0) new Promise((resolve, reject) => resolve('should be right after baz, before bar') ).then(resolve => console.log(resolve)) baz() } foo()
결과는
foo baz should be right after baz, before bar bar
이는 promises(약속에 기반한 Async/await)와 setTimeout() 또는 다른 플랫폼 API를 통한 평범한 오래된 비동기 함수의 큰 차이점입니다.
JavaScript는 기본적으로 동기이며 단일 스레드입니다. 이는 코드가 새로운 스레드를 생성하고 병렬로 실행할 수 없음을 의미합니다. 비동기 코드가 의미하는 것과 그것이 어떻게 보이는지 배우자.
컴퓨터는 설계 상 비동기식입니다.
비동기란 주 프로그램 흐름과 관계없이 일이 발생할 수 있음을 의미합니다.
현재의 소비자 컴퓨터에서는 모든 프로그램이 특정 시간슬롯동안 실행된 다음 다른 프로그램이 실행을 계속할 수 있도록 실행을 중지합니다. 이 작업은 너무 빨리 실행되기 때문에 알아 차릴 수 없으며 컴퓨터에서 여러 프로그램을 동시에 실행한다고 생각합니다. 그러나 이는 환상적입니다 (다중 프로세서 시스템 제외).
프로그램은 내부적으로 시스템의주의를 끌기 위해 프로세서로 방출되는 신호 인 인터럽트를 사용합니다.
필자는 내부적인 내용을 다루지는 않겠지만, 프로그램이 비동기적이며 주의가 필요할 때까지 실행을 중단하는 것은 정상적인 현상이며 컴퓨터가 그 동안 다른 작업을 수행 할 수 있다는 점을 명심하십시오. 프로그램이 네트워크의 응답을 기다리고있을 때 요청이 완료 될 때까지 프로세서를 중지 할 수 없습니다.
일반적으로 프로그래밍언어는 동기식이며 일부는 언어나 라이브러리를 통해 비동기를 관리하는 방법을 제공합니다. C, Java, C #, PHP, Go, Ruby, Swift, Python 등이 모두 기본적으로 동기식입니다. 그들 중 일부는 스레드를 사용하여 비동기를 처리하여 새로운 프로세스를 생성합니다.
JavaScript는 기본적으로 동기이며 단일 스레드입니다. 이는 코드가 새로운 스레드를 생성하고 병렬로 실행할 수 없음을 의미합니다.
코드 행은 차례대로 차례대로 실행됩니다. 예를 들면 다음과 같습니다.
const a = 1 const b = 2 const c = a * b console.log(c) doSomething()
그러나 자바 스크립트는 브라우저 내부에서 태어났다. 처음에는 자바 스크립트가 onClick, onMouseOver, onChange, onSubmit 등과 같은 사용자 액션에 응답하는 것이 주 업무였다. 어떻게 동기식 프로그래밍 모델로이를 수행 할 수 있습니까? 대답은 그 환경에 있었습니다. 브라우저는 이러한 종류의 기능을 처리 할 수있는 API 세트를 제공하여 이를 수행하는 방법을 제공합니다. 최근에 Node.js는 이 개념을 파일 액세스, 네트워크호출 등으로 확장하는 비 차단 I/O 환경을 도입했습니다.
사용자가 버튼을 클릭 할 때를 알 수 없으므로 클릭 이벤트에 대한 이벤트 핸들러를 정의합니다. 이 이벤트 핸들러는 이벤트가 트리거 될 때 호출 될 함수를 받아들입니다.
document.getElementById('button').addEventListener('click', () => { //item clicked })
이것을 일명 callback이라 합니다.
콜백은 다른 함수에 값으로 전달되는 간단한 함수이며 이벤트가 발생할 때만 실행됩니다. JavaScript는 변수에 할당되고 다른 함수 (고차 함수라고 함)로 전달 될 수있는 first-class 함수를 JavaScript가 가지고 있기 때문에 이를 수행 할 수 있습니다. 페이지가 준비되었을 때만 콜백 함수를 실행하는 window 객체의 로드이벤트 리스너에 모든 클라이언트 코드를 래핑하는 것이 일반적입니다.
window.addEventListener('load', () => { //window loaded //do what you want })
콜백은 DOM 이벤트뿐만 아니라 모든 곳에서 사용됩니다.
하나의 일반적인 예는 타이머를 사용하는 것입니다.
setTimeout(() => { // runs after 2 seconds }, 2000)
XHR 요청도 콜백을 허용합니다. 이 예에서는 특정이벤트가 발생할 때 호출 될 속성에 함수를 할당합니다 (이 경우 요청 상태가 변경됨).
const xhr = new XMLHttpRequest() xhr.onreadystatechange = () => { if (xhr.readyState === 4) { xhr.status === 200 ? console.log(xhr.responseText) : console.error('error') } } xhr.open('GET', 'https://yoursite.com') xhr.send()
콜백으로 오류를 어떻게 처리합니까? 하나의 매우 일반적인 전략은 Node.js가 채택한 것을 사용하는 것입니다. 콜백 함수의 첫 번째 매개 변수는 오류 객체입니다. error-first callbacks
오류가 없으면 객체는 null입니다. 오류가 있으면 오류 및 기타 정보에 대한 설명이 포함됩니다.
fs.readFile('/file.json', (err, data) => { if (err !== null) { //handle error console.log(err) return } //no errors, process data console.log(data) })
콜백은 간단한 경우에 좋습니다!
그러나 모든 콜백은 중첩 수준을 추가하며 콜백이 많으면 코드가 매우 빠르게 복잡해집니다.
window.addEventListener('load', () => { document.getElementById('button').addEventListener('click', () => { setTimeout(() => { items.forEach(item => { //your code here }) }, 2000) }) })
이것은 단순한 4단계 코드 일 뿐이지만 더 많은 중첩 수준을 보았고 재미가 없습니다.
어떻게 해결할 수 있을까요?
ES6부터는 JavaScript는 콜백을 사용하지 않는 비동기코드를 지원하는 몇 가지 기능을 제공합니다.
Promises는 코드에서 너무 많은 콜백을 작성하지 않고 JavaScript의 비동기코드를 처리하는 한 가지 방법입니다.
promise는 일반적으로 사용할 수 있는 값을 위한 프록시로 정의됩니다.
약속은 코드에 너무 많은 콜백을 작성하지 않고 비동기코드를 처리하는 한 가지 방법입니다.
수년 전부터 존재 해 왔지만 ES2015에서 표준화되고 도입되었으며 이제 ES2017에서 비동기 기능으로 대체되었습니다.
Async functions는 promise API를 빌딩 블록으로 사용하므로 새로운 코드에서 promise 대신 Async function을 사용할 수 있다고 하더라도 이를 이해하는 것이 기초입니다.
promises가 호출되면 보류 상태로 시작됩니다. 즉, 호출자 함수는 자체 처리를 수행하기를 기다리는 동안 호출자 함수가 실행을 계속하고 호출자 함수에 일부 피드백을 제공합니다.
이 시점에서 호출자 함수는 약속 상태가 해결된 상태 또는 거부된 상태로 약속을 반환하기를 기다리지만 함수는 약속이 작동하는 동안 해당 함수를 계속 실행합니다.
자신의 코드 및 라이브러리 코드 외에도 다음과 같은 표준 현대 웹 API가 약속을 사용합니다.
현대 자바스크립트에서는 약속을 사용하지 않을 가능성이 거의 없기 때문에, 그 약속에 곧장 뛰어들어보자.
Promise API는 새로운 Promise()를 사용하여 초기화하는 Promise생성자를 제공합니다.
let done = true const isItDoneYet = new Promise( (resolve, reject) => { if (done) { const workDone = 'Here is the thing I built' resolve(workDone) } else { const why = 'Still working on something else' reject(why) } } )
보시다시피 약속은 done 글로벌 상수를 검사하고, 이것이 사실이라면 해결 된 약속을 반환하고 그렇지 않으면 약속을 취소합니다.
resolve와 reject를 사용하면 값을 다시 전달할 수 있으며, 위의 경우에는 문자열만 반환하지만 객체 일 수도 있습니다.
마지막 부분에서 우리는 약속이 어떻게 만들어지는지 소개했다.
이제 그 약속이 어떻게 consumed되거나 사용될 수 있는지 살펴보자.
const isItDoneYet = new Promise( //... ) const checkIfItDone = () => { isItDoneYet .then((ok) => { console.log(ok) }) .catch((err) => { console.error(err) }) }
checkIfItsDone()을 실행하면 isItDoneYet() 약속이 실행되고 then 콜백을 사용하여 해결 될 때까지 기다렸다가 오류가 있으면 catch 콜백에서 처리합니다.
약속은 약속의 사슬을 만들어 다른 약속으로 되돌려 질 수 있습니다.
연결 약속의 좋은 예는 XMLHttpRequest API 위에있는 계층 인 Fetch API에서 제공합니다.이 API는 리소스를 가져올 때 사용할 수있는 일련의 약속을 대기열에 저장하는 데 사용할 수 있습니다.
Fetch API는 약속 기반 메커니즘이며 fetch() 호출은 새로운 Promise()를 사용하여 우리 자신의 약속을 정의하는 것과 같습니다.
const status = (response) => { if (response.status >= 200 && response.status < 300) { return Promise.resolve(response) } return Promise.reject(new Error(response.statusText)) } const json = (response) => response.json() fetch('/todos.json') .then(status) .then(json) .then((data) => { console.log('Request succeeded with JSON response', data) }) .catch((error) => { console.log('Request failed', error) })
이 예에서는 fetch()를 호출하여 도메인 루트에있는 todos.json 파일에서 TODO 항목 목록을 가져오고 약속 체인을 만듭니다.
fetch()를 실행하면 많은 속성을 가진 응답과 반환하고 참조하는 응답을 반환합니다.
status, HTTP 상태 코드를 나타내는 숫자 값statusText, 상태 메시지, 요청이 성공하면 OK입니다.response에는 json() 메서드가 있습니다.이 메서드는 JSON으로 처리되고 변형 된 본문의 내용으로 해결 될 수있는 약속을 반환합니다.
그 전제가 주어지면 다음과 같은 상황이 발생합니다. 체인의 첫 번째 약속은 status()라고하는 정의 된 함수로 응답 상태를 확인하고 성공 응답 (200에서 299 사이)이 아니라면 약속을 거부합니다.
이 작업은 약속 체인이 나열된 모든 연결된 약속을 건너 뛰게하고 아래쪽의 catch() 문으로 직접 건너 뛰고 오류 메시지와 함께 요청 Request failed를 기록합니다.
그것이 성공한다면, 우리가 정의한 json() 함수를 호출합니다. 이전 약속이 성공했을 때 response객체를 반환 했으므로 두 번째 약속의 입력으로 사용합니다.
이 경우 JSON이 처리 한 데이터가 반환되므로 세 번째 약속은 JSON을 직접받습니다.
.then((data) => { console.log('Request succeeded with JSON response', data) })
단순히 콘솔에 이것을 로그합니다.
이 예에서 이전 섹션에서는 약속의 사슬에 추가 된 catch가 있었습니다.
약속의 사슬에있는 어떤 것이라도 실패하고 오류가 발생하거나 약속을 거부하면, 사슬을 따라 가장 가까운 catch() 문으로 이동합니다.
new Promise((resolve, reject) => { throw new Error('Error') }) .catch((err) => { console.error(err) }) // or new Promise((resolve, reject) => { reject('Error') }) .catch((err) => { console.error(err) })
catch() 내부에서 오류가 발생하면 두 번째 catch()를 추가하여 처리 할 수 있습니다.
new Promise((resolve, reject) => { throw new Error('Error') }) .catch((err) => { throw new Error('Error') }) .catch((err) => { console.error(err) })
다른 약속을 동기화해야하는 경우 Promise.all()을 사용하면 약속 목록을 정의하고 모든 약속이 해결되면 이를 실행할 수 있습니다. 예 :
const f1 = fetch('/something.json') const f2 = fetch('/something2.json') Promise.all([f1, f2]).then((res) => { console.log('Array of results', res) }) .catch((err) => { console.error(err) })
ES2015 구조 지정 지정 구문을 사용하면
Promise.all([f1, f2]).then(([res1, res2]) => { console.log('Results', res1, res2) })
당신은 코스의 가져 오기를 사용하는 것에 국한되지 않으며, 어떤 약속도 좋습니다.
Promise.race ()는 전달 된 약속 중 첫 번째가 해결 될 때 실행되며 연결된 약속을 한 번만 실행하고 첫 번째 약속이 해결 된 결과를 실행합니다. 예 :
const first = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'first') }) const second = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'second') }) Promise.race([first, second]).then((result) => { console.log(result) // second })
이제 JavaScript에서 비동기 함수에 대한 현대적인 접근 방식을 살펴 보겠습니다. JavaScript는 콜백에서 Promises로 매우 짧은 시간에 진화했으며, ES2017부터 async/await 구문을 사용하면 비동기 JavaScript가 훨씬 간단해 졌습니다.
비동기 함수는 약속과 생성자의 조합이며 기본적으로 약속보다 높은 수준의 추상화입니다. 나에게 반복하자. async/await은 약속에 기반한다.
그들은 약속들에 관한 상용구를 줄이며, “약속의 사슬을 끊지 말라”는 약속의 한계를 지킵니다.
약속이 ES2015에 도입되었을 때, 비동기 코드 문제를 해결하기위한 것이었지만 ES2015와 ES2017을 분리 한 2 년 동안 약속이 최종 해결책이 될 수 없음이 분명했습니다.
약속은 유명한 콜백 지옥 문제를 해결하기 위해 도입되었지만 복잡성과 구문 복잡성을 도입했습니다.
그것들은 더 좋은 구문이 개발자에게 노출 될 수 있는 좋은 기본 요소였으므로 시간이 맞으면 비동기 함수가 생겼습니다.
이 코드는 동기식처럼 보이게하지만 비동기식이며 비공개입니다.
비동기 함수는 다음 예와 같이 약속을 반환합니다.
const doSomethingAsync = () => { return new Promise((resolve) => { setTimeout( () => resolve('I did something'), 3000) }) }
이 함수를 호출하기를 원할 때 await를 앞에 붙이고, prmise가 해결되거나 거부 될 때까지 호출 코드를 멈춥니다. 하나의 주의사항 : 클라이언트 함수는 비동기로 정의되어야합니다. 다음은 그 예입니다.
const doSomething = async () => { console.log(await doSomethingAsync()) }
비동기적으로 함수를 실행하는 데 사용되는 async/await의 간단한 예입니다.
const doSomethingsAsync = () => { return new Promise((resolve) => { setTimeout(() => resolve('I did something'), 3000) }) } const doSomething = async () => { console.log(await doSomethingAsync()) } console.log('Before') doSomething() console.log('After')
위의 코드는 브라우저 콘솔에 아래와 같이 출력한다.
Before After I did something // after 3s
임이의 함수에 async키워드를 붙이는 것은 promise를 반환하는 함수를 의미한다.
비록 명백히 그렇게 하지 않아도, 이것은 내부적으로 promise를 반환하게 만든다.
이것이 이코드가 유효한 이유입니다.
const aFunction = async () => { return 'test' } aFunction().then(alert) // This will alert 'test'
이 것은 다음과 같다:
const aFunction = async () => { return Promise.resolve('test') } aFunction().then(alert) // This will alert 'test'
위의 예제에서 보는 것과 같이, 우리의 코드는 매우 단순하다. chaining과 callback함수와 함께 평범한 promise를 사용하는 코드에 비교해보라.
그리고 이것은 매우 단순한 예제이고, 주 이득은 코드가 더 많고 복잡해질때 볼 수 있다.
예를 들어 JSON 자원을 얻고, 그것을 분석하는 promise를 사용하는 예이다.
const getFirstUserData = () => { return fetch('/users.json') // get users list .then(response => response.json()) // parse JSON .then(users => users[0]) //pick fist user .then(user => fetch(`/users/${user.name}`)) // get user data .then(userResponse => response.json()) // parse JSON } getFirstUserData()
여기 await/async를 사용하여 같은 기능을 제시하면:
const getFirstUserData = async() => { const response = await fetch('/user.json') // get users list const users = await reponse.json() // parse JSON const user = users[0] // pick first user const userResponse = await fetch(`/users/${user.name}`) // get user data const userData = await user.json() // parse JSON return userData } getFirstUserData()
비동기 함수는 매우 쉽게 연결될 수 있으며 구문은 일반 약속보다 훨씬 읽기 쉽습니다.
const promiseToDoSomething = () => { return new Promise(resolve => { setTimeout(() => resolve('I did something'), 10000) }) } const watchOverSomeoneDoingSomething = async () => { const something = await promiseToDoSomething() return something + ' and I watched' } const watchOverSomeoneWatchingSomeoneDoingSomething = async () => { const something = await watchOverSomeoneDoingSomething() return something + ' and I watched as well' } watchOverSomeoneWatchingSomeoneDoingSomething().then((res) => { console.log(res) })
출력은…
I did something and I watched and I watched as well
디버거가 asynchronous코드 단계적으로 수행하지 않기 때문에 promises디버깅은 어렵습니다.
Async/await는 컴파일러에서 동기 코드와 매우 비슷하기 때문에 매우 쉽습니다.
JavaScript에는 루프 및 범위 지정과 관련하여 개발자에게 두통을 줄 수있는 기능이 있습니다. 우리는 var와 let을 사용하여 루프와 범위 지정에 관한 몇 가지 트릭을 배웁니다.
이 예제를 보자.
const operations = [] for (var i = 0; i < 5; i++) { operations.push(() => { console.log(i) }) } for (const operation of operations) { operation() }
이것은 operation을 콜하는 배열에 함수를 다섯번 추가하는 기본적인 반복이다. 이 함수는 루프 인덱스 변수i를 콘솔에 단순히 로그하는 함수이다.
후에 이 함수들은 실행한다.
기대되는 결과는 0 1 2 3 4 이지만 실제적으로는 5 5 5 5 5 이다.
왜 이런 경우가 발생될까? 이유는 var의 사용이다.
var선언은 hoisted된다, 위의 코드는 다음과 같다.
var i; const operations = [] for(i=0; i<5; i++) { operations.push(() => { console.log(i) }) } for (const operation of operations) { operation() }
그래서, for-of루프에서 i는 아직까지 보이고, 이것은 5와 같으며 함수안에서 i에 대한 모든 참조는 이 값을 사용한다.
그럼, 우리가 원하는 것을 수행하는 것을 만들기위해서는 어떻게 해야하나?
단순한 해결책은 let선언을 사용하는 것이다. var선언에 대한 기묘한 것들의 일부를 필하는데 큰 도움이되는 let은 ES2015에 소개되었다.
단순하게 루프변수에서 var에서 let변경으로 훌륭하게 일할 것이다.
const operations = [] for (let i = 0; i < 5; i++) { operations.push(() => { console.log(i) }) } for (const operation of operations) { operation() }
출력은 여기에
0
1
2
3
4
어떻게 이것이 가능할까? 이것은 매 루프 반복마다 매번 새로운 변수로 만들어지며 operations 배열에 추가 된 모든 함수는 i의 자체 복사본을 가져 오기 때문에 작동합니다.
이 경우 const는 사용할 수 없음을 기억하라, for는 두번째 반복에서 새로운 값을 할당하려는 시도에 의해서 error가 된다.
ES6 이전 코드에서 일반적으로 이 문제를 해결하는 다른 방법은 Immediately Invoked Function Expression(IIFE)에 의해서 호출하는 것이다.
이 경우 전체 함수를 랩핑하고 i를 바인딩 할 수 있습니다. 이 방법으로 즉시 실행되는 함수를 생성하고 있으므로 새 함수를 반환하므로 나중에 실행할 수 있습니다.
const operations = [] for (var i = 0; i < 5; i++) { operations.push(((j)=>{ return () => console.log(j) })(i)) } for (const operation of operations) { operation() }
자바스크립트코드를 작성할때 함수의 실행을 늦추수 있습니다. 앞으로 setTimeout 및 setInterval을 사용하여 함수를 예약하는 방법에 대해 설명합니다.
JavaScript 코드를 작성할 때 함수의 실행을 지연시킬 수 있습니다.
이것은 setTimeout의 작업입니다. 나중에 실행할 콜백 함수와 나중에 실행할 시간을 나타내는 값을 밀리 초 단위로 지정합니다.
setTimeout(() => { // runs after 2 seconds }, 2000) setTimeout(() => { // runs after 50 milliseconds }, 50)
이 구문은 새로운 함수를 정의합니다. 거기에 원하는 다른 함수를 호출하거나 기존 함수 이름과 매개 변수 집합을 전달할 수 있습니다.
const myFunction = (firstParam, secondParam) => { // do something } // runs after 2 seconds setTimeout(myFunction, 2000, firstParam, secondParam)
setTimeout은 타이머 ID를 반환합니다. 이것은 일반적으로 사용되지 않지만이 ID를 저장할 수 있으며이 예약 된 함수 실행을 삭제하려는 경우 지울 수 있습니다.
const id = setTimeout(() => { // should run after 2 seconds }, 2000) // I changed my mind clearTimeout(id)
제한 시간 지연을 0으로 지정하면 콜백 함수가 가능한 빨리 실행되지만 현재 함수 실행 후 :
setTimeout(() => { console.log('after ') }, 0) console.log(' before ') //출력은 before after.
이는 집중적 인 작업에서 CPU를 막지 않도록하고, 스케줄러에서 대기열 기능을 사용하여 많은 계산을 수행하는 동안 다른 기능을 실행할 수있게하는 데 특히 유용합니다.
일부 브라우저 (IE 및 Edge)는이 똑같은 기능을 수행하는 setImmediate() 메소드를 구현하지만 표준이 아니며 다른 브라우저에서는 사용할 수 없습니다. 하지만 Node.js의 표준 함수입니다.
setInterval은 setTimeout과 비슷한 함수입니다. 콜백 함수를 한 번 실행하는 대신 지정하는 특정 시간 간격 (밀리 초)에 영원히 실행합니다.
setInterval(() => { // runs every 2 seconds }, 2000)
위의 함수는 중지하라는 메시지를 표시하지 않는 한 clearInterval을 사용하여 2 초마다 실행하고 setInterval이 반환 한 interval id를 전달합니다.
const id = setInterval(() => { // runs every 2 seconds }, 2000) clearInterval(id)
setInterval 콜백 함수 내에서 clearInterval을 호출하여 다시 실행해야 하는지 중지할지 자동 결정하도록하는 것이 일반적입니다. 예를 들어이 코드는 App.somethingIWait에 값이 도착하지 않으면 실행됩니다.
const interbal = setInterbal(() => { if (App.somethingIWait === 'arrived') { clearInterbal(interbal) return } // otherwise do thing }, 100)
setInterval은 함수가 실행을 마친 시점을 고려하지 않고 n 밀리 초마다 함수를 시작합니다.
함수가 항상 같은 시간이 걸린다면 괜찮습니다.
예를 들어, 네트워크 조건에 따라 함수의 실행 시간이 달라질 수 있습니다.
그리고 아마도 하나의 긴 실행이 다음 실행과 겹칠 수 있습니다.
이를 방지하기 위해 콜백 함수가 완료되면 재귀적 setTimeout이 호출되도록 예약 할 수 있습니다.
const myFunction = () => { // do something setTimeout(myFunction, 1000) } setTimeout( myFunction(), 1000)
이 시나리오를 달성하려면 :
setTimeout 및 setInterval은 Timers 모듈을 통해 Node.js에서 사용할 수 있습니다.
Node.js는 setTimeout( () ⇒ {}, 0)을 사용하는 것과 동일한 setImmediate()도 제공하며, 주로 Node.js 이벤트 루프와 함께 사용됩니다.
this 값은 사용되는 위치에 따라 다른 값을 갖는 값입니다. 자바 스크립트의 작은 세부 사항을 알지 못 하면 많은 골칫거리를 유발할 수 있으므로 모든 트릭을 배우는 데 5 분이 소요됩니다.
자바스크립트에 대한이 작은 세부사항을 알지 못하면 많은 골칫거리를 유발할 수 있으므로 모든 트릭을 익히는 데 5 분이 소요됩니다.
어떤 객체 외부에서 엄격모드에서 this는 항상 undefined다.
공지 사항 엄격 모드를 언급했습니다. 엄격 모드가 사용 중지 된 경우 (파일 상단에 'use strict'를 명시 적으로 추가하지 않으면 기본 상태입니다.), 이는 부적절한 모드(sloppy mode)입니다. this는 여기에 언급 된 특별한 경우가 아니면 전역 개체의 값입니다.
브라우저 컨텍스트에서 window을 의미합니다.
메서드는 객체에 연결된 함수입니다.
다양한 형태로 볼 수 있습니다.
여기에 하나 있습니다 :
const car = { maker: 'Ford', model: 'Fiesta', drive() { console.log(`Driving a ${this.maker} ${this.model} car!`) } } car.drive() //Driving a Ford Fiesta car!
이 경우, 정규함수를 사용, this는 자동적으로 객체에 묶인다.
노트: 위의 메소드선언은 drive: function() {와 같으…,
그러나 잛게:
const car = { maker: 'Ford', model: 'Fiesta', drive: function() { console.log(`Driving a ${this.maker} ${this.model} car!`) } }
이 예제는 같은 일을 수행한다.
const car = { maker: 'Ford', model: 'Fiesta' } car.drive = function() { console.log(`Driving a ${this.maker} ${this.model} car!`) } car.drive() //Driving a Ford Fiesta car!
같은 방법으로 어휘적으로 바인딩되는 화살표함수는 작동하지 않습니다.
const car = { maker: 'Ford', model: 'Fiesta', drive: () => { console.log(`Driving a ${this.maker} ${this.model} car!`) } } car.drive() //Driving a undefined undefined car!
일반 함수처럼 값을 화살표 함수에 바인딩 할 수 없습니다.
그들이 일하는 방식 때문에 단순히 불가능합니다. 이것은 어휘적으로 바인드됩니다.(lexically bound) 즉, 그 값은 정의되고있는 문맥으로부터 파생합니다.
JavaScript는 이를 원하는 모든 객체에 매핑하는 몇 가지 방법을 제공합니다.
함수 선언 단계에서 bind() 사용:
const car = { maker: 'Ford', model: 'Fiesta' } const drive = function() { console.log(`Driving a ${this.maker} ${this.model} car!`) }.bind(car) drive() //Driving a Ford Fiesta car!
기존 객체 메소드를 바인드하여 this값을 다시 매핑 할 수도 있습니다.
const car = { maker: 'Ford', model: 'Fiesta', drive() { console.log(`Driving a ${this.maker} ${this.model} car!`) } } const anotherCar = { maker: 'Audi', model: 'A4' } car.drive.bind(anotherCar)() //Driving a Audi A4 car!
call() 또는 appli()를 사용하여, function invocation단계에서
const car = { maker: 'Ford', model: 'Fiesta' } const drive = function(kmh) { console.log(`Driving a ${this.maker} ${this.model} car at ${kmh} km/h!`) } drive.call(car, 100) //Driving a Ford Fiesta car at 100 km/h! drive.apply(car, [100]) //Driving a Ford Fiesta car at 100 km/h!
call() 또는 apply()에 전달하는 첫번째 매개변수는 항상 this에 묶인다. call()과 apply()의 차이는 두 번째 인자가 인자 목록으로 배열을 원하지만 첫 번째 인자가 인자로 전달되는 변수의 수를 허용한다는 것입니다.
이벤트 헨들러의 콜백에서, this는 이벤트를 받은 HTML 요소를 참조한다.
document.querySelector('#button').addEventListener('click', function(e) { console.log(this) //HTMLElement })
이것에 bind를 사용 할 수 있다.
document.querySelector('#button').addEventListener('click', function(e) { console.log(this) //Window if global, or your context }.bind(this))
엄격 모드(Strict Mode)는 ES5 기능이며, JavaScript를 더 나은 방법으로 작동시키는 방법입니다. Strict Mode는 JavaScript 언어의 의미를 변경하기 때문에 다른 방식으로 작동합니다.
엄격 모드의 JavaScript코드와 일반 자바스크립트간의 주요 차이점을 아는 것은 정말로 중요합니다. 보통 자바 스크립트는 부적절한 모드라고도합니다.
그리고 다른 방법으로 Strict Mode를 활성화하면 JavaScript 언어의 의미가 변경됩니다.
strict 모드에서의 JavaScript코드와 종종 “엉성한 모드”라고하는 “보통”JavaScript 사이의 주요 차이점을 아는 것은 정말로 중요합니다.
엄격 모드 (Strict Mode)는 주로 ES3에서 가능했던 기능을 제거하고 ES5 이후에는 더 이상 사용되지 않는 기능을 제거합니다 (그러나 이전 버전과의 호환성 요구 사항으로 인해 제거되지는 않음)
엄격 모드는 선택 사항입니다. 자바 스크립트의 모든 주요 변경 사항과 마찬가지로, 자바 스크립트가 돌연 변할 수 있기 때문에 언어의 기본 동작 방식을 간단히 변경할 수는 없으며 자바 스크립트는 1996 년 자바 스크립트 코드가 여전히 작동하는지 확인하기 위해 많은 노력을 기울입니다. 그것은 성공의 열쇠입니다.
그래서 엄격 모드를 사용하기 위해 우리가 사용해야하는 '엄격한 사용'지시어가 있습니다.
파일의 시작 부분에 넣으면 파일에 포함 된 모든 코드에 적용 할 수 있습니다.
'use strict' const name = 'Flavio' const hello = () => 'hey' //...
개별 함수에 대해서 Strict Mode를 활성화할 수 이다. 'use string'를 함수 몸체의 시작에 넣어 줍으로 해서
function hello() { 'use strict' return 'hey' }
이 방법은 테스트 할 시간이 없는 레거시 코드 또는 전체 파일에 엄격 모드를 사용하도록 설정할 때 유용합니다.
선언되지 않은 변수에 값을 할당하면 JavaScript는 기본적으로 해당 변수를 전역 객체에 만듭니다.
;(function() { variable = 'hey' })()(() => { name = 'Flavio' })() variable //'hey' name //'Flavio'
Strict Mode를 작동시키면, 위의 것을 시도하면 error를 일으킨다.
;(function() { 'use strict' variable = 'hey' })()(() => { 'use strict' name = 'Flavio' })()
JavaScript는 자동으로 일부 변환 오류를 해결합니다. 엄격 모드 (Strict Mode)에서는 이러한 사일런트 오류로 인해 문제가 발생합니다.
const undefined = 1(() => { 'use strict' undefined = 1 })()
Infinity, NaN, eval, arguments 등에도 동일하게 적용됩니다.
JavaScript에서는 객체의 속성을 쓰기 가능하지 않도록 정의 할 수 있습니다.
const car = {} Object.defineProperty(car, 'color', { value: 'blue', writable: false })
strict mode에서 이 값은 덮어쓸 수 없으며 sloppy mode에서는 가능하다.
getter들에 대해서도 같은 일을 한다.
const car = { get color() { return 'blue' } } car.color = 'red'( //ok () => { 'use strict' car.color = 'yellow' //TypeError: Cannot set property color of #<Object> which has only a getter } )()
sloppy mode는 확장 할 수 없는 객체를 확장 할 수 있습니다.
const car = { color: 'blue' } Object.preventExtensions(car) car.model = 'Fiesta'( //ok () => { 'use strict' car.owner = 'Flavio' //TypeError: Cannot add property owner, object is not extensible } )()
또한 sloppy mode는 아무런 조치도 취하지 않고 원시 값에 대한 속성을 설정할 수 있습니다.
true.false = ''( //'' 1 ).name = 'xxx' //'xxx' var test = 'test' //undefined test.testing = true //true test.testing //undefined
Strict mode에서는 이 모든 경우에서 실패한다.
;(() => { 'use strict' true.false = ''( //TypeError: Cannot create property 'false' on blooean 'true' 1 ).name = 'xxx' //TypeError: Cannot create property 'name' on number '1' 'test'.testing = true //TypeError: Cannot create property 'testing' on string 'test'
sloppy mode에서 삭제할수 없는 property의 삭제를 시도한다면, 자바스크립트는 단순히 false를 반환한다. strict mode에서는 TypeError를 일으킨다.
delete Object.prototype( //false () => { 'use strict' delete Object.prototype //TypeError: Cannot delete property 'prototype' of function Object() { [native code] } } )()
일반 함수에서는 매개변수에 대한 이름의 중복을 가질 수 있다.
(function(a, a, b) { console.log(a, b) })(1, 2, 3) //2 3 (function(a, a, b) { 'use strict' console.log(a, b) })(1, 2, 3) //Uncaught SyntaxError: Duplicate parameter name not allowed in this context
Note: 화살표함수는 이 경우에 항상 SyntaxError를 일으킨다
((a, a, b) => { console.log(a, b) })(1, 2, 3) //Uncaught SyntaxError: Duplicate parameter name not allowed in this context
엄격 모드의 8 진수 구문은 사용할 수 없습니다. 기본적으로 8 진수 숫자 형식과 호환되는 숫자 앞에 0을 붙이면 (때때로 혼란스럽게) 8 진수로 해석됩니다.
(() => { console.log(010) })() //8 (() => { 'use strict' console.log(010) })() //Uncaught SyntaxError: Octal literals are not allowed in strict mode.
0oXX구문을 이용하여 Strict mode에서 8진수를 허용한다.
;(() => { 'use strict' console.log(0o10) })() //8
Strict mode에서는 with키워드가 비활성화하여 일부 엣지 케이스를 제거하고 컴파일러 수준에서 더 많은 최적화를 허용한다.
즉시호출함수수식은 생성되는 순간 바로 함수실행하는 방법이다.
IIFE는 전역 개체를 오염시키지 않기 때문에 매우 유용하며 변수 선언을 격리하는 간단한 방법입니다.
여기 IIFE선언하는 구문
;(function(){ /* */ })()
화살표함수를 가지고도 IIFE를 선언할 수 있다.
;(() => { /* */ })()
우리는 기본적으로 괄호 안에 정의 된 함수를 가지고 있고, 그 함수를 실행하기 위해 () 함수를 추가합니다 : (/ * function * /) (). 그 감싸는 괄호는 실제로 우리의 기능을 내부적으로 표현으로 간주하는 것입니다. 그렇지 않으면 이름을 지정하지 않았으므로 함수 선언이 유효하지 않습니다.
함수선언은 이름을 원하고, 함수수식은 이것을 원하지 않습니다.
표현식 괄호 안에 호출 괄호를 넣을 수도 있습니다. 차이점은 없으며 단지 스타일을 선호합니다.
(function() { /* */ }()) (() => { /* */ }())
IIFE를 생성하는 데 사용할 수있는 더 복잡한 구문이 있지만 실제 상황에서는 거의 사용되지 않으며 단항 연산자를 사용합니다.
;-(function() { /* */ })() +(function() { /* */ })() ~(function() { /* */ })() !(function() { /* */ })()
(화살표 함수에서는 작동하지 않습니다.)
IIFE는 일반 기능 (화살표 기능 아님)으로 명명 할 수도 있습니다. 함수가 전역 범위로 “누설”되지 않고 실행 후 다시 호출 할 수 없다는 사실은 변경되지 않습니다.
;(function doSomething() { /* */ })()
당신은 야생에서 이것을 볼 수 있습니다 :
;(function() { /* */ })()
이렇게하면 두 JavaScript 파일을 맹목적으로 연결할 때 문제가 발생하지 않습니다. JavaScript는 세미콜론을 필요로하지 않으므로 구문 오류를 일으키는 마지막 행의 일부 명령문으로 파일을 연결할 수 있습니다. 이 문제는 근본적으로 webpack과 같은 “스마트”코드 번들로 해결됩니다.
수학 연산과 미적분 연산을 수행하는 것은 모든 프로그래밍 언어와 함께하는 가장 일반적인 일입니다. JavaScript는 숫자 작업에 도움이되는 여러 연산자를 제공합니다.
const three = 1 + 2 const four = three + 1
+연산자는 문자열 합치는 것을 제공합니다. 문자열사용에는 주의를 기울여야 합니다.
const three = 1 + 2 three + 1 // 4 'three' + 1 // three1
const two = 4 - 2
첫 번째 연산자와 두 번째 연산자의 몫을 반환합니다.
const result = 20 / 5 ⇐result === 4 const result = 20 / 7 ⇐result === 2.857142857142857
만약에 0으로 나누면 자바스크립트는 어떤 에러를 일으키지 않고 Infinity값(또는 음수라면 -Infinity)를 반환합니다.
1 / 0 ⇐ Infinity -1 / 0 ⇐ -Infinity
나머지연산자은 많은 경우 매우 유용한 계산이다.
const result = 20 % 5 ⇐ result === 0 const result = 20 % 7 ⇐ result === 6
0으로 나머지연산자는 항상 NaN(특별한 값으로 “숫자가 아님”)이다.
1 % 0 ⇐ NaN -1 % 0 ⇐ NaN
1 * 2 ⇐ 2 -1 * 2 ⇐ -2
첫번째 인자에 두번째 인자를 승수로
1 ** 2 // 1 2 ** 1 // 2 2 ** 2 // 4 2 ** 8 // 256 8 ** 2 // 64
숫자를 증가시켜라. 이것은 단항 연산자이며 숫자 앞에 놓이면 증가 된 값을 반환합니다. 숫자 뒤에 넣으면 원래 값을 반환 한 다음 값을 증가시킵니다.
let x = 0 x++ // 0 x // 1 ++x // 2
증가연산자와 유사하게, 값을 감소시킨다.
let x = 0 x-- // 0 x // -1 --x // -2
항의 음수를 반환한다.
let x = 2 -x // -2 x // 2
항이 Number가 아니라면 항을 변환시키려 한다. 그렇지 않으면 항이 이미 숫자인 겨우 아무 것도 수행하지 않습니다.
let x = 2 +x //2 x = '2' +x //2 x = '2a' +x //NaN
일반 할당 연산자 =는 모든 수식 연산자에 대하여 두번째 항과의 연산결과를 첫번째 항에 할당하는 할당를 결합하는 몇가지 축약형이 있습니다.
그 들은:
+=: addition assignment-=: subtraction assignment*=: multiplication assignment/=: division assignment%=: remainder assignment**=: exponentiation assignment예제:
const a = 0 a += 5 //a === 5 a -= 2 //a === 3 a *= 2 //a === 6 a /= 2 //a === 3 a %= 2 //a === 1
모든 복잡한 문장은 우선순위 문제를 소개한다.
이것을 가지고
const a = 1 * 2 + 5 / 2 % 2
결과는 2.5이다, 그러면 이유는? 어떤 연산자가 먼저 실행되고, 대기를 필요로 하는 곳은 어디인가?
어떤 연산자들은 다른 것보다 높은 우선권을 가진다. 우선권 규칙은 아래의 목록을 따른다:
- + ++ – 단항연산자, 증가와 감소* / % 곱셈/나눗셈+ - 덧셈/뺄셈= += *= /= %= **= 할당
같은 순서( +와 - 같은)상의 연산자는 그들이 나오는 순서로 실행한다.
위 순서에 따라서 이 계산을 푼다.
const a = 1 * 2 + 5 / 2 % 2 const a = 1 * 2 + 5 / 2 % 2 const a = 2 + 2.5 % 2 const a = 2 + 0.5 const a = 2.5
Math 객체에는 수학 관련 유틸리티가 많이 포함되어 있습니다. 여기 모두 다 보자.
| Item | Description |
|---|---|
| Math.E | e 오일러의 상수이며 자연로그의 밑값 e를 나타내며 약 2.718의 값을 가집니다. |
| Math.LN10 | 10의 자연로그 값, 약 2.302의 값을 가집니다. |
| Math.LN2 | 2의 자연로그 값, 약 0.693의 값을 가집니다. |
| Math.LOG10E | e의 로그 10 값, 약 0.434의 값을 가집니다. |
| Math.LOG2E | e의 로그 2 값, 약 1.442의 값을 가집니다. |
| Math.PI | 원의 둘레와 지름의 비율, 약 3.14159의 값을 가집니다. |
| Math.SQRT1_2 | 2의 제곱근의 역수, 즉 1/2의 제곱근(약 0.707) |
| Math.SQRT2 | 2의 제곱근(약1.414) |
모든 함수들은 정적이다. Math는 인스턴트 할 수 없다. Math의 메서드
Math.abs(x)
숫자의 절댓값을 반환합니다.
Math.acos(x)
숫자의 아크코사인 값을 반환합니다.
Math.acosh(x)
숫자의 쌍곡아크코사인 값을 반환합니다.
Math.asin(x)
숫자의 아크사인 값을 반환합니다.
Math.asinh(x)
숫자의 쌍곡아크사인 값을 반환합니다.
Math.atan(x)
숫자의 아크탄젠트 값을 반환합니다.
Math.atanh(x)
숫자의 쌍곡아크탄젠트 값을 반환합니다.
Math.atan2(y, x)
인수 몫의 아크탄젠트 값을 반환합니다.
Math.cbrt(x)
숫자의 세제곱근을 반환합니다.
Math.ceil(x)
인수보다 크거나 같은 수 중에서 가장 작은 정수를 반환합니다.
Math.clz32(x)
주어진 32비트 정수의 선행 0 개수를 반환합니다.
Math.cos(x)
숫자의 코사인 값을 반환합니다.
Math.cosh(x)
숫자의 쌍곡코사인 값을 반환합니다.
Math.exp(x)
Ex 를 반환합니다. x는 인수이며 E 는 오일러 상수(2.718…) 또는 자연로그의 밑입니다.
Math.expm1(x)
exp(x)에서 1을 뺀 값을 반환합니다.
Math.floor(x)
인수보다 작거나 같은 수 중에서 가장 큰 정수를 반환합니다.
Math.fround(x)
인수의 가장 가까운 단일 정밀도 표현을 반환합니다.
Math.hypot([x[, y[, …]]])
인수의 제곱합의 제곱근을 반환합니다.
Math.imul(x, y)
두 32비트 정수의 곱을 반환합니다.
Math.log(x)
숫자의 자연로그(loge 또는 ln) 값을 반환합니다.
Math.log1p(x)
숫자 x에 대해 1 + x의 자연로그(loge 또는 ln) 값을 반환합니다.
Math.log10(x)
숫자의 밑이 10인 로그를 반환합니다.
Math.log2(x)
숫자의 밑이 2인 로그를 반환합니다.
Math.max([x[, y[, …]]])
0개 이상의 인수에서 제일 큰 수를 반환합니다.
Math.min([x[, y[, …]]])
0개 이상의 인수에서 제일 작은 수를 반환합니다.
Math.pow(x, y)
x의 y 제곱을 반환합니다.
Math.random()
0과 1 사이의 난수를 반환합니다.
Math.round(x)
숫자에서 가장 가까운 정수를 반환합니다.
Math.sign(x)
x의 양의 수인지 음의 수인지 나타내는 부호를 반환합니다.
Math.sin(x)
숫자의 사인 값을 반환합니다.
Math.sinh(x)
숫자의 쌍곡사인 값을 반환합니다.
Math.sqrt(x)
숫자의 제곱근을 반환합니다.
Math.tan(x)
숫자의 탄젠트 값을 반환합니다.
Math.tanh(x)
숫자의 쌍곡탄젠트 값을 반환합니다.
Math.trunc(x)
숫자의 정수 부분을 반환합니다.
ES모듈은 모듈 작업을 위한 ECMAScript 표준입니다. Node.js는 CommonJS 표준을 오랫동안 사용해 왔지만 브라우저에는 모듈 시스템이 없었습니다. 모듈 시스템과 같은 모든 주요 결정은 먼저 ECMAScript에 의해 표준화 된 다음 브라우저에 의해 구현되어야 합니다. 이 표준화 과정은 ES6에서 완성되었으며 브라우저는이 표준을 구현하여 모든 것을 잘 정렬하고 동일한 방식으로 작동시키며, 이제 ES모듈은 Chrome, Safari, Edge 및 Firefox (버전 60 이후)에서 지원됩니다.
모듈은 모든 종류의 기능을 캡슐화하고 이 기능을 라이브러리로 다른 JavaScript 파일에 표시 할 수 있기 때문에 매우 멋지다.
module를 import하는 구문:
import package from 'module-name'
CommonJS를 사용하면
const package = require('module-name')
module은 export키워드를 사용한 하나 또는 그 이상의 값(객체, 함수, 또는 변수들)를 exports하는 자바스크립트 파일이다. 예를 들어 이 module은 문자열 대문자를 리턴하는 함수를 내보내기한다.
export default str => str.toUpperCase()
이 예제에서 모듈은 단일 default export를 정의하므로 익명의 함수가 될 수 있습니다. 그렇지 않으면 다른 수출과 구분하기 위해 이름이 필요합니다.
이제 다른 JavaScript 모듈은 uppercase.js를 import하여 기능을 가져올 수 있습니다.
HTML 페이지는 특수한 type = “module”속성과 함께 <script> 태그를 사용하여 모듈을 추가 할 수 있습니다.
<script type="module" src="index.js"></script>
Note: 이 모듈 가져 오기는 defer(지연) 스크립트 로드처럼 작동합니다. 지연 및 비동기로 JavaScript를 효율적으로 로드하십시오.
type = “module”로 로드된 스크립트는 엄격 모드에서 로드된다는 점에 유의해야합니다.
이 예제에서 uppercase.js 모듈은 기본 내보내기를 정의하므로 가져올 때 원하는 이름을 지정할 수 있습니다.
import toUpperCase from './uppercase.js'
그리고 이것을 사용할 수 있습니다.
toUpperCase('test') //'TEST' 또한 모듈 가져오기에 위해, 다른 도메인에 정의된 모듈를 참조하기 위해서 절대 패스를 사용할 수 있다. <code javascript> import toUpperCase from 'https://flavio-es-modules-example.glitch.me/uppercase.js'
이것은 정당한 가져로기 구문이다.
import { foo } from '/uppercase.js' import { foo } from './uppercase.js'
이것은 아니다.
import { foo } from 'uppercase.js' import { foo } from 'utils/uppercase.js'
절대적이거나 이름 앞에 ./ 또는 / 기호가 가져야 한다.
위의 예제를 보았다.
export default str => str.toUpperCase()
이렇게하면 하나의 기본 내보내기가 만들어집니다. 그러나 파일에서 다음 구문을 사용하여 두 가지 이상을 내보낼 수 있습니다.
const a = 1 const b = 2 const c = 3 export { a, b, c }
다른 모듈은 다음을 사용하여 모든 내보내기를 가져올 수 있습니다.
import * from 'module'
파괴 할당을 사용하여 이러한 내보내기 중 일부만 가져올 수 있습니다.
import { a } from 'module' import { a, b } from 'module'
편리함을 위해 as를 가져오기를 개명할 수 있다.
import { a, b as two } from 'module'
이 일반적인 React import와 같이 기본 내보내기와 이름에 의해서 비기본 내보내기를 가져올 수 있습니다.
import React, { Component } from 'react'
ES 모듈 예제는 https://glitch.com/edit/#!/flavio-es-modules-example?path=index.html에서 확인할 수 있습니다.
모듈은 CORS를 사용하여 가져옵니다. 즉, 다른 도메인의 스크립트를 참조하는 경우 크로스 사이트로드를 허용하는 유효한 CORS 헤더가 있어야합니다 (예 : Access-Control-Allow-Origin : *)
type = “module”과 nomodule의 조합을 사용하십시오.
<script type="module" src="module.js"></script> <script nomodule src="fallback.js"></script>
ES 모듈은 최신 브라우저에 도입 된 가장 큰 기능 중 하나입니다. 그것들은 ES6의 일부이지만 길들이기까지 길었습니다.
우리는 이제 그것을 사용할 수 있습니다! 그러나 모듈을 몇 개 이상 보유하면 페이지에서 성능이 저하된다는 것을 기억해야합니다. 이는 브라우저가 런타임에 수행해야하는 또 하나의 단계이기 때문입니다.
Webpack은 ES 모듈이 브라우저에 설치되어 있어도 여전히 거대한 플레이어가 될 것입니다.하지만 언어로 직접 구축된 기능은 클라이언트 측과 Node.js에서 모듈이 작동하는 방식을 통일하는 데 큰 도움이됩니다.
CommonJS 모듈 사양은 Node.js에서 모듈 작업에 사용되는 표준입니다.
브라우저에서 실행되는 클라이언트 측 JavaScript는 ES 모듈이라고하는 다른 표준을 사용합니다.
그것들은 명확하게 분리되고 재사용 가능한 기능 조각을 만들 수 있게 해줍니다. 각각의 기능은 테스트 할 수 있습니다.
거대한 npm 생태계는이 CommonJS 형식을 기반으로합니다.
모듈을 가져 오는 구문은 다음과 같습니다.
const package = require('module-name')
CommonJS에서 모듈은 동기식으로 로드되고 JavaScript 런타임에서 모듈을 찾은 순서로 처리됩니다. 이 시스템은 서버측 JavaScript를 염두에 두고 개발되었으며 클라이언트 측에 적합하지 않습니다 (이것이 ES 모듈이 도입된 이유입니다).
JavaScript 파일은 변수, 함수, 객체 인 정의 된 하나 이상의 심볼을 내보낼 때 모듈입니다.
exports.uppercase = str => str.toUpperCase()
모든 JavaScript 파일은이 모듈을 가져 와서 사용할 수 있습니다.
const uppercaseModule = require('uppercase.js') uppercaseModule.uppercase('test')
단순한 예제는 이 Glitch에서 찾을 수 있습니다.
하나이상을 내보내기 하려면:
exports.a = 1 exports.b = 2 exports.c = 3
파괴 할당을 사용하여 개별적으로 가져옵니다.
const { a, b, c } = require('./uppercase.js')
또는 단지 한 값만 내보내기를 하려면:
//file.js module.exports = value
이것 사용하려는 가져오기:
const value = require('./file.js')
끝으로, 외계인이 될 수 있는 프론트 엔드 개발에 사용된 몇 가지 용어에 대한 안내서
코드는 사용자가 무언가를 시작하고 잊어 버렸을 때 비동기식이며 결과가 준비되면 기다리지 않고 되돌릴 수 있습니다. 일반적인 예제는 AJAX 호출입니다. 이 호출은 몇 초가 걸릴 수 있으며 그 동안 다른 작업을 완료하고 응답이 준비되면 콜백 함수가 호출됩니다. promises와 async/await는 비동기를 처리하는 현대적인 방법입니다.
JavaScript에서 블록은 중괄호 ({})로 구분됩니다. if 문은 블록을 포함하고, for 루프는 블록을 포함합니다.
함수 스코핑을 사용하면 블록에 정의 된 모든 변수를 볼 수 있으며 전체 블록 내부에서 액세스 할 수 있지만 외부에서는 액세스 할 수 없습니다.
콜백은 무언가가 발생할 때 호출되는 함수입니다. 요소에 연결된 클릭 이벤트에는 사용자가 요소를 클릭 할 때 호출되는 콜백 함수가 있습니다. 가져오기 요청에는 리소스를 다운로드 할 때 호출되는 콜백이 있습니다.
선언적 접근법은 여러분이해야 할 일을 기계에 알려주고, 세부 사항을 파악하게합니다. React는 DOM을 직접 편집하지 않고 추상화를 추론 할 때 선언적으로 간주됩니다. 모든 고수준 프로그래밍 언어는 Assembler와 같은 저수준 프로그래밍 언어보다 선언적입니다. JavaScript는 C보다 선언적입니다. HTML은 선언적입니다.
대체 기능은 사용자가 특정기능에 액세스하지 않은 경우 좋은 경험을 제공하는 데 사용됩니다. 예를 들어 자바 스크립트를 사용하지 않고 탐색하는 사용자는 일반 HTML 버전의 페이지로 대체 할 수 있어야합니다. 또는 API를 구현하지 않은 브라우저의 경우 사용자의 경험을 완전히 손상시키지 않도록 대체해야합니다.
Function Scoping을 사용하면 함수에 정의 된 모든 변수를 볼 수 있으며 함수 전체에서 액세스 할 수 있습니다.
변수는 값이 생성 된 후에 변경 될 수없는 경우 불변입니다. 변경할 수있는 변수를 변경할 수 있습니다. 객체 및 배열에도 동일하게 적용됩니다.
어휘 스코핑은 상위 함수의 변수가 내부 함수에서도 사용 가능하게 만드는 특별한 종류의 범위 지정입니다. 내부 함수의 범위에는 부모 함수의 범위도 포함됩니다.
polyfill은 최신 자바 스크립트에서 사용할 수있는 새로운 기능이나 최신 브라우저 API를 구형 브라우저에 제공하는 방법입니다. polyfill은 특별한 종류의 심입니다.
부작용이 없는 (외부 리소스를 수정하지 않는) 함수이며 그 출력은 인수에 의해서만 결정됩니다. 이 함수를 수 천번 호출 할 수 있으며 동일한 인수 세트가 주어지면 출력은 항상 동일합니다.
var 및 let 선언이있는 JavaScript를 사용하면 변수를 무기한 재 할당 할 수 있습니다. const 선언를 사용하면 문자열, 정수, 부울 및 재 할당 할 수없는 객체에 대해 불변값을 효과적으로 선언 할 수 있습니다 (그러나 메서드를 통해 수정할 수는 있습니다).
범위는 프로그램의 일부에서 볼 수있는 변수 집합입니다.
범위 지정은 프로그래밍 언어에서 변수의 값을 결정하기 위해 정의된 규칙 집합입니다.
shim(틈 메우는 나무)은 기능 또는 API를 둘러싼 작은 래퍼입니다. 일반적으로 무언가를 추상화하거나 매개 변수를 미리 채우거나 일부 기능을 지원하지 않는 브라우저에 polyfill을 추가하는 데 사용됩니다. 호환성 레이어와 같은 것으로 간주 할 수 있습니다.
부작용은 함수가 다른 함수 또는 외부의 객체와 상호 작용할 때 발생합니다. 네트워크 또는 파일 시스템이나 UI와의 상호 작용은 모두 부작용입니다.
State는 일반적으로 구성 요소에 대해 이야기 할 때 작용합니다. 구성 요소는 자체 데이터를 관리하는 경우에는 상태 저장이 가능하고 그렇지 않은 경우에는 비상태 저장이 가능합니다.
상태 저장 구성 요소, 함수 또는 클래스는 자체 상태 (데이터)를 관리합니다. 그것은 배열, 카운터 또는 다른 것을 저장할 수 있습니다.
무상태 구성 요소, 함수 또는 클래스는 결정을 내릴 수 있는 자체 데이터를 가질 수 없기 때문에 멍청(dumb)하다고도 합니다. 따라서 출력 또는 발표는 전적으로 논쟁에 기초합니다.이것은 순수한 기능이 무상태라는 것을 의미한다.
Strict 모드는 ECMAScript 5.1의 새로운 기능으로, JavaScript 런타임에서 더 많은 오류를 잡아낼 수 있지만 선언되지 않은 변수와 중복 된 객체 속성 및 기타 미묘한 문제와 같은 간과 할 수있는 문제를 유발할 수있는 JavaScript 코드를 개선하는 데 도움이 됩니다. 힌트 : 그것을 사용하십시오. 대안은 우리가 준 이름을 보아도 좋지 않은 “sloppy mode”입니다.
트리 떨림은 사용자에게 제공되는 번들에서 “데드 코드”를 제거하는 것을 의미합니다. 가져 오기 명령문에서 사용하지 않는 코드를 추가하면 파일 크기 및로드 시간을 줄이기 위해 앱 사용자에게 전송되지 않습니다.
참고 :이 자바 스크립트 안내서의 PDF, ePub 또는 Mobi 버전을 참조하거나 킨들 또는 태블릿에서 읽을 수 있습니다.