자바스크립트 스크롤 이벤트

스크롤 이벤트

  • document view나 element가 스크롤될 때 이벤트가 발생.
  • 스크롤 이벤트는 빈번히 발생하기 때문에 DOM 수정과 같은 연산이 많은 작업은 하지 않아야 함.
  • requestAnimationFrame, setTimeout, customEvent를 사용하여 이벤트 호출 조절을 추천.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Reference: http://www.html5rocks.com/en/tutorials/speed/animations/

var last_known_scroll_position = 0;
var ticking = false;

function doSomething(scroll_pos) {
// do something with the scroll position
}

window.addEventListener('scroll', function(e) {

last_known_scroll_position = window.scrollY;

if (!ticking) {

window.requestAnimationFrame(function() {
doSomething(last_known_scroll_position);
ticking = false;
});

ticking = true;

}

});

자바스크립트

이벤트 선임 Event Delegation

Attribute Property

  • Attribute: HTML 요소. 사용자 인테렉션에 변하지 않음
  • Property: HTML DOM Tree 요소. 사용자 인터렉션에 의해 값이 변함

document Road, DOM Ready

  • ready: DOM Tree가 완료
  • load: css,js,image,iframe들이 메모리에 올라간다음 실행

자바스크립트 객체

  • Built-in Object 자바스크립트 내장 객체
    Global,Object, String, Number, Boolean, Date, Array, Math, RegExp, Error 등
    자바스크립트 엔진이 구동되는 시점에 바로 제공

  • Native Objet 브라우저 내장 객체
    DOM, BOM

  • Host Object 사용자 정의 객체
    사용자가 생성한 객

jsonp

  • GET 요청만 가능
  • 무조건 비동기 처리. async:false 가 되지 않음리
  • JSONP 요청시 Browser UI Thread가 멈춤

프로토타입 Prototype

  • 함수 정의시 같이 생성
  • 해당 참조 타입의 인스턴스가 가져야할 프로퍼티와 메서드를 담고 있는 객체

얕은 복사, 깊은 복사 shallow copy , deep copy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 배열 deep copy
var array = [1,2,3];
var shallow = array;
var deepArray = Array.prototype.slice.call(array);


// 함수에서 deep copy
var func = function() {
...
}

var deepFunc = func.bind(this);


// 객체에서 deep copy

function clone(obj) {
if (obj === null || typeof(obj) !== 'object') {
return obj;
}

var deepObj = {};
for (var attr in obj) {
// prototype에 있는 상속된 객체의 속성도 반복 되기 때문에
// 해당 객체의 속성만 복사
if (obj.hasOwnProperty(attr)) {
deepObj[attr] = clone(obj[attr]);
}
}

return deepObj;
}

var obj = {foo: 'boo'};
var deepObj = clone(obj);

유사배열

Array.isArray로 배열 여부 판단

Function arguments, dom select시 []안에 있지만 배열은 아님

그래서 배열 prototype에 있는 forEach같은 메서드를 바로 사용 불가

실행 컨텍스트 Execution Context

스코프 Scope

부동소수점 계산

호이스팅 Hoisting

var 변수 선언은 최상위에 선언된 것과 동일함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var x = 'outer scope';
(function() {
console.log(x); // undefined
var x = 'inner scope';
}());

// 위는 아래와 같은 의미를 가진다.

var x = 'outer scope';
(function() {
var x;
console.log(x); // undefined
x = 'inner scope';
}());
1
2
3
4
5
6
7
foo = 'bar';
var foo;

// 위는 아래와 같은 의미를 가진다.

var foo;
foo = 'bar';
1
2
3
// const, let은 
console.log(x); // throws a ReferenceError
const x = 'hey';

TDZ (Temporal Dead Zone)

함수 Function

함수 끌어 올림 Function Hoisting

  • 함수 선언부를 함수 호출보다 먼저 읽고 실행
  • 함수 표현식은 해당하지 않음

함수 call, apply, bind

  • call(this, 1,2,3) 함수 호출
  • apply(this, [1,2,3]) 함수 호출
  • bind(this): 호출은 하지 않고 컨텍스트 변환된 함수 반환

클로저 Closure

  • 내부함수에서 외부함수의 인자를 접근할 수 있는 것

자바스크립트 컨텍스트

원시값, 참조값

  • 변수는 원시 값과 참조 값 두 가지 타입을 저장
  • 원시 값: Undefined, Null, Boolean, Number, String, 스택 영역에 저장
  • 참조 값: 메모리에 저장된 객체, 자바스크립트는 메모리에 직접 접근 불가, 힙 영역에 저장

동적 프로퍼티

  • 참조 값을 다룰 때는 언제든지 프로퍼티와 메서드를 조작할 수 있다

값 복사

  • 원시 값을 다른 변수로 복사할 때는 현재 저장된 값을 새로 생성한 다음 새로운 변수에 복사
  • 참조 값을 다른 변수로 복사하면 원래 변수에 들어있던 힙에 저장된 객체를 가리키는 포인터가 복사

힙: 어플리케이션이 운영체제로 부터 미리 할당받는 메모리 (브라우저가 쓰는 메모리)

실행 컨텍스트(execution context)와 스코프(scope)

변수 객체 (variable object)

  • 실행 컨텍스트에는 변수 객체(variable object)가 연결되어 있으며 해당 컨텍스트에서 정의된 모든 변수와 함수는 이 객체에 존재
  • 코드에서 접근할 수 없지만 이면에서 데이터를 다룰 때 사용

전역 컨텍스트(Global Context)

  • 전역변수와 전역함수는 전역 컨텍스트(window)의 프로퍼티 및 메서드로 생성
  • 웹브라우저가 종료될 때까지 유지

    실행 컨텍스트(Execution Context)

  • 실행 컨텍스트가 포함된 코드가 모두 실행될 때 파괴 , 해당 컨텍스트 내부에서 정의된 변수와 함수도 파괴
  • 변수에 할당된 메모리를 언제 해제할 수 있는지 판단하는데 도움

스코프 체인(Scope Chain)

  • 컨텍스트에서 코드를 실행하면 변수 객체에 생성
  • 실행 컨텍스트가 접근할 수 있는 모든 변수와 함수에 순서를 정의
  • 스코프 체인의 앞쪽은 항상 코드가 실행되는 컨텍스트의 변수 객체
  • 컨텍스트가 함수라면 활성화 객체(Activation Object)를 변수 객체로 사용
  • 활성화 객체는 argument 변수 단 하나로 시작 (전역 컨텍스트에서는 존재하지 않음)
  • 변수 객체의 다음 순서는 부모 컨텍스트 그 다음은 부모의 부모 컨텍스트 최종 전역 컨텍스트
  • 전역 컨텍스트의 변수 객체는 항상 스코프 체인의 마지막에 존재
  • 각 컨텍스트는 스코프 체인을 따라 상위 컨텍스트에서 변수나 함수를 검색 반대로는 안됨

블록 레벨 스코프가 없다

  • var를 사용해 선언한 변수는 자동으로 가장 가까운 컨텍스트에 추가
    1
    2
    3
    4
    for(var i=0; i < 10; i++){
    doSomething(i);
    }
    alert(i); //10

자바스크립트 프로토타입

프로토타입

  • 모든 함수는 prototype 프로퍼티를 가짐
  • prototype은 해당 참조 타입의 인스턴스가 가져야할 프로퍼티와 메서드를 담고 있는 객체
  • prototype의 프로퍼티와 메서드는 객체 인스턴스 전체에서 공유

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function Person() {

    }

    Person.prototype.name = "Nicholas";
    Person.prototype.age = 29;
    Person.prototype.job = "Software Engineer";
    Person.prototype.sayName = function() {
    alert(this.name);
    }

    var person1 = new Person();
    person1.sayName(); // Nicholas

    var person2 = new Person();
    person2.sayName(); // Nicholas

    alert(person1.sayName == person2.sayName); // true
  • constructor 프로퍼티는 프로토타입에만 존재

  • 객체 인스턴스에서 프로토타입의 값은 읽을 수 있지만 수정 불가
  • 프로토타입의 프로퍼티와 같은 이름의 프로퍼티를 인스턴스에 추가하면 해당 프로퍼티는 프로토타입까지 가지 않음

프로토타입2

  • 모든 객체의 조상은 함수
  • 함수 정의시 prototype object도 같이 생성
  • prototype object는 constructor와 prototype link(proto)를 가지고 있음

-https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67

자바스크립트 함수

Parameter와 Argument

  • parameter는 함수를 정의할 대 사용.
1
2
3
function foo(param1, param2) {
...
}
  • Argument 는 함수를 호출할 때 사용.
1
foo(3, 7);

함수 정의 방법 2가지

  • 함수 선언 (Function Declarations)

    1
    2
    3
    function functionName(){

    }
  • 함수 표현식 (Function Expression)
    함수 표현식에서의 함수는 익명함수로 간주됨 ( 람다 함수라고 부르기도 함 )
    반드시 호출 하기전에 할당해야 함

    1
    2
    3
    4
    var functionName = function(){


    }

함수 호이스팅(hoisting)

  • 함수 선언부를 함수 호출보다 먼저 읽고 실행

    1
    2
    3
    4
    sayHi();
    function sayHi() {
    alert('Hi');
    }

  • 함수 표현식에서는 에러 발생

    1
    2
    3
    4
    sayHi(); // 에러 발생
    var sayHi = function(){
    alert('Hi');
    }
  • 절대 해서는 안되는 방식
    함수 선언은 호이스팅이 되기 때문에 브라우저마다 처리되는 방식이 다름

    1
    2
    3
    4
    5
    6
    7
    8
    9
    if(condition){
    function sayHi() {
    alert('Hi');
    }
    }else{
    function sayHi() {
    alert('Yo');
    }
    }
  • 함수 표현식을 할당을 통한 방식은 안전함

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // condition에 따라 함수 표현식 할당
    var sayHi;

    if(condition){
    sayHi = function() {
    alert('Hi');
    }
    }else{
    sayHi = function() {
    alert('Yo');
    }
    }

재귀

arguments.callee는 현재 실행중인 함수를 가리키는 포인터
재귀함수를 사용할 때 항상 자신을 호출하는 이름대신 arguments.callee를 써야 안전함
실행 중 호출하는 함수가 지워지거나 변경 되었을 때를 예방

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num-1);
}
}

// 스트릭 모드에서는 arguments.callee 값에 접근할 수 없어 에러가 발생
// 함수 표현식으로 사용해야 함
var factorialExpression = (function f(num){
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num-1);
}
})

클로저

  • 다른 함수의 스코프에 있는 변수에 접근 가능한 함수
  • 함수 호출시 실행 컨텍스트와 스코프 체인이 생성

자바스크립트 프로퍼티

6. 객체 지향 프로그래밍

  • ECMAScript에는 클래스라는 개념이 없으며 ECMAScript의 객체는 다른 클래스 기반 언어와 다름
  • ECMA-262는 객체를 “프로퍼티의 순서 없는 컬렉션이며 각 프로퍼티는 원시 값이나 객체 함수를 포함한다”라고 정의
  • 객체가 특별한 순서가 없는 값의 배열
  • 각 프로퍼티와 메서드는 이름으로 구별, 값에 대응
  • 해시테이블 , 이름-값 쌍의 그룹이며 각 값은 데이터나 함수가 될 수 있음
  • 모든 객체는 참조 타입을 바탕으로 생성

프로퍼티 타임

1. 데이터 프로퍼티

[[Configurable]]
  • default: true
  • delete를 통해 삭제, 프로퍼티 속성 변경, 접근자 프로퍼티로 변환 여부
  • false로 설정하면 다시는 수정할 수 없음
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var person = {};
    Object.defineProperties(person, "name", {
    configurable: false,
    value: "Nicholas"
    });

    alert(person.name); // Nicholas
    delete person.name;
    alert(person.name); // Nicholas

    Object.defineProperties(person, "name", {
    configurable: true,
    value: "Nicholas"
    });
    // 에러 발생
[[Enumerable]]
  • default: true
  • for-in 루프에서 해당 프로퍼티를 반환 여부
[[Writable]]
  • default: true
  • 프로퍼티의 값을 바꿀 수 있음
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var person = {};
    Object.defineProperties(person, "name", {
    writable: false,
    value: "Nicholas"
    });

    alert(person.name); // Nicholas
    person.name = "Greg";
    alert(person.name); // Nicholas
[[Value]]
  • default: undefined
  • 프로퍼티의 실제 데이터 값을 포함

접근자 프로퍼티

  • 데이터 값이 들어 있지 않고 getter, setter 함수로 구성
  • 접근자 프로퍼티를 명시적으로 정의할 수는 없음
  • 반드시 Object.definedProperty()를 사용, 지원하지 않는 경우 [[Configurable]] [[Enumerable]]을 수정할 수 없음
  • 이전 버전 –defineGetter. __defineSetter
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var book = {
    _year: 2004,
    edition: 1
    }

    Object.defineProperty(book, "year", {
    get: function(){
    return this._year;
    },
    set: function(newValue) {
    if(newValue > 2004){
    this._year = newValue;
    this.edition += newValue - 2004;
    }
    }
    });

    book.year = 2005;
    alert(book.edition); //2

프로토타입 패턴

  • 모든 함수는 prototype 프로퍼티를 가짐
  • 프로토타입의 프로퍼티와 메서드는 객체 인스턴스 전체에서 공유됨

reference

  • 프론트엔드 개발자를 위한 자바스크립트 프로그래밍

front-v8

V8 엔진

JIT(just-in-time)

자바스크립트 엔진은 자바스크립트 코드를 실행하는 인터프리터 입니다.
자바스크립트 엔진은 표준 인터프리터로 구현될 수 있으며, 혹은 바이트코드로 컴파일 하는 just-in-time 컴파일러입니다.

다음은 인기있는 자바스크립트 엔진 목록입니다.

  • V8 — open source, developed by Google, written in C++
  • Rhino — managed by the Mozilla Foundation, open source, developed entirely in Java
  • SpiderMonkey — the first JavaScript engine, which back in the days powered Netscape Navigator, and today powers Firefox
  • JavaScriptCore — open source, marketed as Nitro and developed by Apple for Safari
  • KJS — KDE’s engine originally developed by Harri Porten for the KDE project’s Konqueror web browser
  • Chakra (JScript9) — Internet Explorer
  • Chakra (JavaScript) — Microsoft Edge
  • Nashorn, open source as part of OpenJDK, written by Oracle Java Languages and Tool Group
  • JerryScript — is a lightweight engine for the Internet of Things

V8 엔진이 만들어진 이유는 무엇일까요?

구글이 만든 V8엔진은 오픈소스이며 C++로 작성되었습니다.
이 엔진은 구글 크롬 브라우저에서 사용됩니다. 나머지 엔진들과 달리 노드 JS 런타입으로도 사용됩니다.
최초 v8 엔진은 웹 브라우저안에서 자바스크립트 실행 속도를 향상 시키기 위해 만들어 졌습니다.
속도를 얻기 위해서 V8 엔진은 인터프리터를 쓰는 대신 자바스크립트 코드를 보다 효율적인 기계어로 변환합니다.
SpiderMonkey 나 Rhino (모질라)와 같은 많은 최신 자바 스크립트 엔진처럼 JIT (Just-In-Time) 컴파일러를 구현하여 실행시 JavaScript 코드를 기계 코드로 컴파일합니다.
주된 차이점은 V8이 바이트 코드 또는 중간 코드를 생성하지 않는다는 것입니다.

Hidden class

V8은 런타임에 객체를 처리하기 위해 내부적으로 hidden class를 만들어서 가지고 있고,
같은 hidden class를 가지고 있는 객체는 다음 번에도 동일한 최적화된 코드를 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
function Point(x, y) {
this.x = x;
this.y = y;
}

var p1 = new Point(11, 22);
var p2 = new Point(33, 44);
// 여기에서 p1과 p2는 hidden class를 공유합니다.
p2.z = 55;
// 경고! p1과 p2는 이제 다른 hidden class를 갖습니다.

객체 인스턴스 p2에 멤버 “.z”를 추가하기 전까지, p1과 p2는 내부적으로 같은 hidden class를 갖습니다. 이로써 V8은 p1이나 p2를 다루는 JavaScript 코드에 대한 단일 버전의 최적화된 어셈블리어를 만들 수 있습니다. 같은 JavaSript 코드의 hidden class가 서로 달라지는 원인을 찾아서 막을 수 있다면, 더 좋은 성능을 얻을 수 있습니다.

모든 객체 멤버를 생성자 함수 안에서 초기화하세요(그래야 나중에 인스턴스가 멤버의 데이터 타입을 변경하지 않습니다).
항상 같은 순서로 객체 멤버를 초기화합니다.

Numbers

일반적으로 적합하다면, 31비트 부호있는 정수를 사용하는 것이 최적입니다.

1
2
var i = 42;  // 31비트 부호있는 정수입니다.
var j = 4.2; // 이 값은 double 타입의 부동 소수점 숫자 데이터입니다.

Arrays

large 과 sparse 배열 처리를 위한 두 가지 유형의 배열 저장소가 내부에 있습니다.

  • Fast Elements: linear storage for compact key sets
  • Dictionary Elements: hash table storage otherwise

배열 저장소가 한 유형에서 다른 유형으로 변경되지 않게 하는 것이 가장 좋습니다.

배열의 경우 0부터 시작하는 연속 키 사용
대규모 배열 (예 :> 64K 요소)을 최대 크기로 사전 할당
배열 삭제
초기화된지 않거나 삭제된 요소를 로드

Rreference

자바스크립트 이벤트

이벤트

  • 자바스크립트와 HTML의 상호작용은 이벤트에 의해 처리된다.
  • 이벤트는 리스너(핸들러)로 추적하며 이벤트가 일어날 때만 실행되는 옵저버 패턴이다.
  • 이벤트를 처음 도입한 브라우저는 익스플러러 3, 넷스케이프 2
  • 익스플러러4와 넷스케이프4가 출시 되면서 다른 이벤트 API를 도입
  • 주요 브라우저 중에서 전용 이벤트 시스템만 사용한 브라우저는 인터넷 익스플로러 8이 마지막
  • DOM레벨3로 확장과 DOM과 BOM이벤트 사이의 관계를 정의한 문서가 없어 계속 복잡함.
  • 익스플로러는 이벤트 버블링, 넷스케이프는 이벤트 캡처링 지원