[BB-JS] 3. 언어의 기초

본 글은 자바스크립트 공부를 위해 프론트엔드 개발자를 위한 자바스크립트 프로그래밍를 정리한 글입니다.

들어가며

ECMA-262 3판 기준에서 5판에서 바뀐점을 포함하여 정리

문법

  • 대소문자 구분
  • 식별자
    • 카멜 케이스
  • 주석
    • //
    • /**/
  • 스트릭트 모드(5판)
    • "use strict";  * 스트릭트 모들르 지원하는 자바스크립트 엔진은 이를 인식하고 스트릭트 모드로 전환(3판에서는 무시)
    • 함수 단 하나만 스트릭트 모드로 실행하려면, 함수 본문 맨 앞에 추가
  • 문장
    • 세미콜론
      • 문법 에러 방지나 성능 측면에서 붙이는 것이 좋음
    • 코드 블록
      • 의도를 명확하게 표현 및 에러 방지 측면에서 사용하는 것이 좋음

키워드와 예약어

  • 식별자 이름에 키워드를 사용하면 3판에서는 “Identifier Expected” 에러
  • 식별자 이름에 예약어를 사용하면 에러가 발생할 수 있음
  • 객체의 프로퍼티 이름으로 키워드와 예약어를 사용할 수 있으나 권장하지 않음(5판)

변수

  • 느슨한 타입이기 때문에 어떤 타임의 데이터라도 저장
  • 모든 변수는 값에 대한 이름 붙은 플레이스홀더
  • var는 키워드이며, 변수 이름은 식별자
  • 초기화하지 않으면 undefined가 할당
  • 선언과 동시에 초기화 가능
  • 변수의 데이터 타입을 바꾸는 행위는 권장하지 않음
  • var를 쓰지 않는다면 변수를 전역으로 정의
    • 안티 패턴
    • 스트릭트 모드에서는 ReferenceError에러가 발생
  • 한 문장에서 여러 개 변수를 선언할 경우 각 변수는 쉼표로 구분

데이터 타입

  • 원시(primitive) 데이터 타입
    • Undefined
    • Null
    • Boolean
    • Number
    • String
  • 복잡한 데이터 타입
    • Object
  • typeof 연산자
    • 값(변수)에 typeof 연산자를 적용하면 다음 문자열 중 하나를 반환
      • 정의되지 않은 변수: "undefined"
      • 불리언: "boolean"
      • 문자열: "string"
      • 숫자: "number"
      • 함수를 제외한 객체 또는 null: "object"
      • 함수: "function"
    • typeof는 함수가 아니라 연산자이기 때문에 괄호를 생략해도 됨
    • null은 빈 객체를 참조하는 특별한 값이므로 "object"를 반환
  • undefined 타입
    • var를 사용하여 변수를 정의했지만 초기화하지 않았다면 변수에 undefined가 할당
    • null: 빈 객체를 가리키는 포인터
    • undefined: 초기화되지 않은 변수
      • 명시적으로 undefined를 할당하는 것은 지양
    • typeof는 정의하지 않은 변수를 실행 가능
      • 변수가 정의되었는지 확인할 때 사용(typeof value === "undefined")
      • 초기화되지 않은 변수에 typeof 연산자를 호출하면 "undefined" 반환
      • 정의하지 않은 변수에 typeof 연산자를 호출하면 "undefined" 반환
    • delete의 경우는 에러가 발생하지는 않지만 스트릭트 모드에서는 발생하며 사용하는 것을 지양해야됨
  • Null 타입
    • 값 하나만을 가짐
    • Null 타입의 값은 특별한 값인 null
    • null은 빈 객체를 참조하는 특별한 값이며, typeof를 호출하면 "object"를 반환
    • 변수를 정의할 때, 변수가 객체를 가리킬 예정이라면 null로 초기화를 권장
    • undefinednull에서 파생했기 때문에 ECMA-262에서는 표면적으로 동일한 것으로 정의
    • undefinednull을 구분하여 사용할 것
  • Boolean 타입
    • truefalse 두 가지 리터럴 값을 가짐
    • 모든 타입을 Boolean값으로 표현 가능
      • Boolean()함수 호출
      • 어떤 타입의 데이터에서도 호출할 수 있으며, 항상 Boolean 값을 반환
      • if문 같은 제어문은 자동으로 불리언으로 바뀜
  • Number 타입
    • IEEE-784 형식을 통해 정수와 부동소수점 숫자를 나타냄
    • 정수
      • 스트릭트 모드에서는 8진법 리터럴을 허용하지 않으며 문법 에러를 반환
      • 숫자는 진수와 관계없이 항상 10진수로 변환하여 계산
    • 부동소수점 숫자
      • 부동소숫점 숫자를 저장할 때는 정수를 저장할 때에 비해 메모리를 두 배로 소모
      • 소수점 뒤에 숫자가 없다면 정수로 변환됨
      • 전체 숫자 표기법(1.0, 100.0 등)도 정수로 변환됨
      • 큰 숫자를 표현할 때는 e-표기법을 사용
      • 소수점 뒤에 0이 6개 이상 있는 모든 부동소수점 숫자를 지수 표기법으로 변환됨
      • 부동소수점 숫자는 소수점 아래 17자리까지 정확하기는 하지만 사칙 연산에 있어서는 전체 숫자보다 부정확
    • 숫자 범위
      • 최솟값: Number.MIN_VALUE
      • 최댓값: Number.MAX_VALUE
      • 양의 무한대: Infinity, Number.POSITIVE_INFINITY
      • 음의 무한대: -Infinity, Number.NEGATIVE_INFINITY
      • isFinite(): 최솟값과 최댓값 사이에 있는지 확인
    • NaN(Not a Number)
      • 숫자를 반환한 것으로 의도한 조작이 실패했을 때 반환됨(에러가 아닌 것에 유의, 예 0으로 나눈 경우 등)
      • NaN이 포함된 조작은 항상 NaN을 반환(어느 단계에서 문제가 발생했는지 파악하기 어려움, 예 NaN/10)
      • NaN은 어떠한 값과도 일치하지 않으며, NaN끼리도 일치하지 않음(NaN == NaN // false)
      • isNaN()
        • 매개 변수가 ‘숫자가 아닌 값’인지 검사
        • 매개 변수를 숫자로 형변환이 시도됨(예 "10"은 문자열로 변환되어 처리됨)
        • NaN뿐만이 아니라 "blue"와 같이 숫자가 아니거나, 숫자로 변환할 수 없는 값은 true로 반환
        • 사용에 유의해야하며, ES2015에 추가된 함수를 사용하거나, polyfill을 사용하길 권장
        • ES2015에서는 Number.isNaN()을 사용하면 좀 더 명확함
    • 숫자 변환
      • Number()
        • 모든 타입에 사용 가능
      • parseInt()
        • 문자열을 숫자로 바꾸는 용도
        • 빈 문자열도 NaN을 반환(Number()와 차이점 유의)
        • 첫 문자가 숫자, + 또는 - 기호라면 문자열의 끝 또는 숮자가 아닌 문자를 만날 때까지 변환 진행
        • 두 번째 매개변수에 진법을 나타내는 변수를 넘길 수 있음
        • 진법 매개변수를 명시해서 에러 예방하는 것을 권장
      • parseFloat()
        • 문자열을 숫자로 바꾸는 용도
        • 10진수만 사용가능 하기 때문에 진법 매개변수는 무시됨
        • 소수점 뒤에 숫자가 없다면 정수로 변환됨
        • 전체 숫자 표기법(1.0, 100.0 등)도 정수로 변환됨
  • String 타입
    • ””, ‘’ 혹은 ``(ES2015)을 사용
    • 문자열의 성질
      • 문자열은 불변
    • 문자열 변환
      • toString() 메서드
        • 거의 모든 값에 존재
        • 숫자, 불리언, 객체, 문자열 존재
        • nullundefined에는 존재하지 않음
        • 숫자에서 호출할 때 전달하는 매개변수는 진법을 나타내는 숫자
      • String()
        • toString() 메서드를 호출할 값이 null이나 undefined일 가능성이 있는 경우
        • 값의 타입에 관계없이 항상 문자열을 반환
        • toString()메서드가 존재한다면 매개변수 없이 호출
        • null일 경우 "null" 반환
        • undefined일 경우 "undefined" 반환
  • Object 타입
    • 객체는 데이터와 기능의 집합
    • new 연산자 다음에 새로 만들 객체 타임의 이름을 써서 생성(예 new Object())
    • 생성자에 매개변수를 넘기지 않는다면 괄호는 생략 가능(예 new Object, 권장하지 않음)
    • Object는 모든 객체의 원형, Object 타입의 인스턴스는 Object타입의 프로퍼티와 메서드를 전부 상속
      • contructor
        • 객체를 생성하는데 쓰인 함수
      • hasOwnProperty(propertyName)
        • 해당 프로퍼티가 객체 인스턴스에 고유하며 프로토타입 상속에서 상속하지 않읐음을 확인
        • 프로퍼티 이름은 반드시 문자열
      • isPrototype(object)
        • 해당 객체가 다른 객체의 프로토타입인지 확인
      • propertyIsEnumerable(propertyName)
        • 해당 프로퍼티를 for-in문에서 나열할 수 있는지 확인
        • 프로퍼티 이름은 반드시 문자열
      • toLocaleString()
        • 객체를 지역에 맞게 표현한 문자열을 반환
      • toString()
        • 객체를 문자열로 변환해 반환
      • valueOf()
        • 객체를 나타내는 문자열이나 숫자, 불리언을 반환
        • toString()과 같은 값을 반환할 때가 많음
    • DOM이나 BOM 같은 호스트 객체는 ECMA-262를 따르지 않아도 되어서 Object를 상속하지 않아도 됨

연산자

  • 단항 연산자
    • 단 하나의 값에만 적용되는 연산자
    • 증감 연산자(++, --)
      • 부작용에 주의하여 사용
      • 숫자, 문자열, 불리언 및 객체에 사용 가능
    • 단항 플러스와 마이너스(+, -)
      • 숫자가 아닌 값에 적용하면 Number()와 마찬가지로 동작
      • 변환 용도로 사용할 수 있음
  • 비트 연산자
    • 숫자를 표현하는 비트를 직접 조작하는 저수준 연산자
    • 모든 숫자는 IEEE-754 64비트 형식으로 저장되지만, 비트 연산자는 64비트 표현을 직접 조작하지는 않음
    • 32비트 정수로 변환하여 비트 연산자를 적용한 후 결과를 다시 64비트로 바꿈
    • 음수는 2의 보수
    • 음수를 절댓값의 2진 표현에 마이너슬르 부호를 붙인 값으로 반환
    • 비트 연산에서는 NaNInfinity0과 같이 처리하는 부작용이 있음
    • 숫자가 아닌 값은 숫자로 변환해서 처리
    • 비트 NOR
      • 틸데(~)로 나타내며 피연산자의 1의 보수를 반환
      • 저수준 연산이라 빠름
    • 비트 AND
      • 앰퍼샌드(&)로 나타내며 피연산자를 두 개 취하여 AND 연산을 수행
    • 비트 OR
      • 파이프(|)로 나타내며 피연산자 두 개를 취하여 OR 연산을 수행
    • 비트 XOR
      • 캐럿(^)으로 나타내며 피연산자 두 개를 취하여 XOR 연산을 수행
    • 왼쪽 시프트
      • <<로 나타내며 좌항의 모든 비트를 우항의 숫자만큼 왼쪽으로 이동
      • 빈 비트는 0으로 채움
      • 부호비트는 유지
    • 부호있는 오른쪽 시프트
      • >>로 나타내며 32비트 숫자의 모든 비트를 오른쪽으로 움직이되 부호(양수 또는 음수)는 그대로 유지
      • 부호비트 오른쪽에 부호비트 값으로 채움
    • 부호없는 오른쪽 시프트
      • >>>로 나타내며 32비트 숫자의 모든 비트를 오른쪽으로 움직임
      • 부호비트와 관계없이 0으로 채움
      • 음수의 2진 표현을 양수로 간주
  • 불리언 연산자
    • 논리 NOT
      • 느낌표(!)로 표시하며 모든 값에 적용할 수 있음
      • 데이터 타입에 관계 없이 항상 불리언 값을 반환
      • 값을 불리언 타입으로 바꾸는데 유용
      • !!Boolean()함수를 쓴 것과 동일
    • 논리 AND
      • 앰퍼샌드 2개(&&)로 나타내며 값 두개에 적용
      • 피연산자가 불리언 값이 아니어도 사용
      • 피연사 중 하나가 불리언이 아니라면 불리언 값을 반환하지 않을 수도 있음
        • 첫 번째 피연산자가 객체라면 항상 두 번째 피연산자를 반환
        • 두 번째 피연산자가 객체라면 첫 번째 피연산자를 true로 평가할 수 있을 때만 두 번째 피연산자를 반환
        • 두 피연산자가 모두 객체라면 두 번째 피연산자를 반환
        • 피연산자 둘 중 하나라도 null이라면 null을 반환
        • 피연산자 둘 중 하나라도 NaN이라면 NaN을 반환
        • 피연산자 둘 중 하나라도 undefined이라면 undefined를 반환
      • 첫 번째 피연산자에서 결과를 결정할 수 있다면 두 번째 피연산자를 평가하지 않음(단축 연산)
    • 논리 OR
      • 파이프 2개(||)로 포현
      • 피연산자 중 하나가 불리언이 아니라면 불리언 값을 반환하지 않을 수도 있음
        • 첫 번째 피연산자가 객체라면 첫 번째 피연산자를 반환
        • 첫 번째 피연산자가 false로 평가된다면 두 번째 피연산자를 반환
        • 두 피연산자가 모두 객체라면 첫 번째 피연사자를 반환
        • 두 피연산자가 모두 null이라면 null을 반환
        • 두 피연산자가 모두 NaN이라면 NaN을 반환
        • 두 피연산자가 모두 undefined라면 undefined를 반환
        • 첫 번쨰 연산자가 true로 평가된다면 두 번쨰 피연산자를 평가하지 않음(단축 연산)
  • 곱셈 관련 연산자
    • 숫자가 아닌 값은 자동으로 숫자로 타입 변환
    • 곱셈(*)
    • 나눗셈(/)
    • 나머지(%)
  • 덧셈 관련 연산자
    • 데이터 타입에 따라 이면에서 변환이 일어남
    • 덧셈(+)
      • 피연산자 중 하나가 문자열이라면 다른 피연산자를 문자열로 변환하고 두 문자열을 합침
        • 객체나 숫자, 불리언이라면 toString()메서드를 호출해 문자열 값을 얻음
        • undefinednull에서는 String()함수를 호출해 문자열 값을 얻음
      • 덧셈 연산자 주위의 데이터 타입을 착각에 유의
    • 뺄셈(-)
  • 관계 연산자
    • 미만(<), 초과(>), 이하(<=), 이상(>=)
    • 피연산자가 모두 문자열이면 문자열에서 서로 대응하는 문자의 문자 코드를 비교
      • 알파벳 순서로 비교하지 않음
      • 소문자의 문자코드가 대문자보다 큼
      • 알파벳 순으로 비교하고자 한다면 toLowerCase()로 변환후 비교
    • 피연산자 중 하나가 숫자라면 다른 피연산자를 숫자로 변환 후 비교
    • 피연산자 중 하나가 객체라면 valueOf()메서드(없으면 toString())를 호출 후 비교
    • 피연산자 중 하나가 불리언이라면 숫자로 변환 후 비교
    • 피연산자 중 문자열인 숫자를 비교시에는 숫자로 변환해서 비교해야 함(예 "23" < "3" // true)
    • NaN과 비교하면 항상 false(예 NaN < 3 // false; NaN >= 3 // false)
  • 동일 연산자
    • 동일과 비동일
      • 동일 연산자(==)로 표시하며 두 피연산자가 동일하면 true를 반환
      • 비동일 연산자(!=)로 표시하며 두 피연산자가 동일하지 않으면 true를 반환
      • 피연산자를 비교하기 전에 변환(타입 강제 type coercion)
        • nullundefined는 동일
        • nullundefined는 변환하지 않음
        • 피연산자 중 하나가 NaN이라면 동일 연산자는 false를 반환하며, 비동일 연산자는 true를 반환
        • 피연산자 모두 NaN이라도 동일 연산자는 항상 false를 반환(예 NaN == NaN // false)
        • 피연산자 모두 객체라면 같은 객체인지 비교(객체에 대한 참조 비교)
    • 일치와 불일치
      • 동일/비동일 연산자와 같은 일을 하지만 피연산자의 타입을 변환하지 않고 있는 그대로 비교
      • 일치 연산자는 ===로 나타내며 불일치 연산자는 !==로 나타낸다
      • nullundefined는 불일치
      • 동일/비동일 연산자보다 일치/불일치 연산자를 쓰길 권장
  • 3항 연산자
    • variable = boolean_expression ? true_value : false_value
  • 할당 연산자
    • 단순한 할당은 =로 나타내며 값을 변수에 할당
    • 복합 할당은 연산자와 = 기호를 합쳐서 나타내며 연산자에는 사칙연산 전체와 다른 일부 연사자를 쓸 수 있음
      • 단축 표기 목적이며 성능적 이점은 없음
  • 쉼표 연산자
    • 여러 문장을 한 문장으로 합칠 때 사용(예 var num1=1, num2=2, num3=3;)
    • 값 할당에 사용하면 항상 표현식의 마지막 값을 반환(예 var num = (5, 1, 4, 8, 0); // num == 0)

문장

  • ECMA-262에는 몇 가지 문장이 정의되어 있는데, 이를 ‘제어문’이라 부르기도 함
  • ECMAScript 문법 대부분이 문장을 통해 정의되며 일반적으로 키워드와 연결
  • if 문
    • if(condition) statement1 else statement2
    • condition에는 어떤 표현식이든 사용할 수 있으며 불리언 값이 아니라면 불리언 값으로 변환하여 평가
    • 코드 블록은 반드시 사용하는 것을 권장
  • do-while 문
    • 평가전 루프로서 루프의 종료 조건을 평가하기 전에 루프 본문을 실행
    • 루프 본문이 최소 한 번은 실행
    • do {statement} while(expression);
  • while 문
    • 평가 후 루프로서 루프 본문을 실행하기 전에 종료 조건을 평가
    • 루프 본문을 단 한번도 실행하지 않을 수도 있음
    • while(expression) statement
  • for 문
    • 평가 후 루프이며 루프에 들어가기 전에 변수를 초기화 할 수 있으며 루프 후 코드도 지정할 수 있음
    • for (initializtion; expression; post-loop-expression) statement
    • while에 루프 제어와 과련된 코드를 한곳에 모은 것이기 때문에 while이 할 수 없는 것은 못함
    • for문 밖에서 초기화한 변수에 접근 할 수 있음
    • 초기화, 조건 표현식, 루프 후 코드는 옵션
  • for-in 문
    • 객체의 프로퍼티를 나열하는 데 사용하는 엄격한 반복문
    • for (property in expression) statement
    • 제어부에 var 키워드를 사용하는 것은 옵션이지만 지역 변수를 이용하도록 var 키워드를 사용하는 것을 권장
    • 객체 프로퍼티에 순서가 없으므로 어떤 순서로 프로퍼티 이름을 반환할지 예측할 수 없음
    • 프로퍼티를 나열할 객체를 가리키는 변수가 null이나 undefined라면 에러 발생(단, 5판에서는 이를 수정하여 루프 본문을 실행하지 않음)
  • 문장 레이블
    • 문장에 레이블을 붙였다 나중에 사용할 수 있음
    • label: statement
    • start: for(var i=0; i<count, i++){}와 같이 작성
    • break 문이나 continue문에서 참조 가능
  • break 문과 continue 문
    • break 문은 즉시 루프에서 빠져나가 루프 다음 문장을 실행
    • continue 문은 루프를 즉시 빠져나가긴 하지만 루프 실행은 계속
    • 문장 레이블과 사용 가능하며 다중 루프에서 많이 사용
    • 문장 레이블과 사용하면 루프를 유연하게 만들 수 있지만 과용하면 디버그에 문제가 생길 수 있음
    • 레이블 이름은 항상 해당 레이블의 의도를 설명할 수 있도록 정하고 루프 중첩을 피하는 것을 권장
    • continue 문은 자바스크립트 엔진에서 별도의 실행 컨텍스트를 만들고 관리해야 하므로 성능 문제를 야기할 수 있으며 루프는 전체적인 성능에 많은 영향을 미치므로 가능한 최적화가 필요
  • with 문
    • 코드의 스코프를 특정 객체에 고정
    • with (expression) statement;
    • 특정 객체를 코드에서 매우 자주 참조할 때 편리하게 작성하지는 의도
    • 스트릭트 모드에서는 금지하며 문법 에러로 간주
    • 성능 및 디버그 등 악영향을 미치어 사용을 지양해야함
  • switch 문
    • switch(expresstion) {case value: statement; break; case value: statement; break; default: statement}
    • 복함 if-else문과 동일한 역할을 하며 긴 코드를 줄여줌
    • case 문마다 break 문을 넣어서 다음 case 문까지 진행하지 않게 하여야하며, 만약 case 문이 다음 case 문까지 징행하게 해야한다면, 주석을 달아 break 문을 의도적으로 생략했음을 나타내주는 것을 권장
    • 모든 데이터 타입에서 동작하므로 문자열과 객체에서도 사용 가능한 점은 다른 언어와 구별되는 특징
    • 값은 상수일 필요가 없으며 변수나 표현식도 사용 가능
    • 일치 연산자(===)로 값을 비교하므로 타입 변환은 일어나지 않음

함수

  • 문장을 캡슐화하여 어디서든, 언제든 실행할 수 있게 하므로 모든 언어의 핵심
  • function functionName(arg0, arg1,.., argN) {statements}
  • return 문을 사용하여 값을 반환할 수 있으며 이는 옵션이며 값을 반환한다는 특별한 선언은 없음
  • return 문을 만나면 즉시 실행을 멈추고 빠져나오므로 뒤는 절대 실행되지 않음
  • 반환값이 없거나 return 문 뒤에 반환 값을 쓰지 않으면 undefined를 반환
  • 함수는 항상 값을 반환하거나 항상 반환하지 않게 만들어 반환에 일관성이 있도록하여 혼란을 줄이는 것을 권장
  • 스트릭트 모드에서는 아래 사항은 제한을 받음
    • 함수 이름에 eval이나 arguments는 사용할 수 없음
    • 매개 변수 이름에도 eval이나 arguments를 쓸 수 없음
    • 서로 다른 매개변수에 결코 같은 이름을 쓸 수 없음
  • 매개변수의 이해
    • 매개변수 숫자를 따지지 않으며 데이터 타입도 체크하지 않음
    • 매개변수가 내부적으로는 배열로 표현되기 때문
    • arguments라는 객체를 갖으며 이 객체를 통해 매개변수의 값에 접근할 수 있음
      • length 프로퍼티를 통해 매개변수의 개수를 알 수 있음
      • 배열과 유사하지만 Array의 인스턴스는 아님
    • 이름 붙은 매개변수의 유효성 검사를 하지 않음
    • arguments 객체의 length 프로퍼티를 사용하여 함수가 받는 매개변수 숫자에 제한을 두지 않고 넘겨받은 매개변수 개수에 맞게 반응할 수 있음
    • arguments 객체의 프로퍼티 값을 변경하면 이에 대응하는 이름 붙은 매개변수에 자동으로 반영됨
      • 이 둘이 같은 메모리 공간을 사용하는 것은 아니며 각기 다른 메모리 공간을 사용
      • 동기화가 아닌 단방향 반영
      • 이름 붙은 매개변수의 값을 바꾸더라도 arguments의 값이 바뀌지 않음(Node와 Chrome에서 테스트할 때는 동기화되고 있어서 확인이 필요)
      • 매개변수를 이름 붙은 매개변수 개수보다 적게 전달하면 전달받지 못한 이름 붙은 매개변수는 arguments로 변경이 불가능
      • arguments 객체의 length 프로퍼티는 함수 정의에서 정의한 매개변수 숫자를 따르지 않고 함수를 호출할 때 넘긴 매개변수 목록을 따름
      • 함수를 정의할 때 함께 정의한 매개변수를 넘기지 않으면 해당 매개변수에는 자동으로 undefined가 할당
      • 스트릭트 모드에서 arugments를 통한 할당 방식이 동작하지 않음
      • 스트릭트 모드에서 arguments를 덮어쓰려고 하면 문법 에러를 발생
  • 오버로딩 없음
    • 힘수의 매개변수는 배열이기 때문에 그 값이 제한이 없어 시그니처가 없음
    • 시그니처가 없기 때문에 오버로딩이 불가능
    • 같은 이름으로 함수를 여러 번 정의하면 마지막 함수가 해당 이름을 소유
    • 매개변수의 타입과 숫자를 체크해서 오버로딩을 흉내낼 수 있음

SmileCat

SmileCat
How do you define yourself?

[Openlayers] Render Event 정리

## 이벤트### [Map](http://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html)| event | module | note || :--: | -- | -- || [postcompose](...… Continue reading