타쿠꺼

16.05.29 본문

Daily Study

16.05.29

kimtaku 2016. 5. 29. 00:23

상단 네이게이션 바 만들기


1. delay += 100 구문을 통해 each가 하나씩 돌 때마다 delay의 값을 100씩 증가시킨다.


2. 스크립트로 hover 애니메이션을 구현할 수도 있지만, 구현할 수 있다면 css를 이용하는게 좋다. (속도면에서)


3. css에서 margin-top에 !important가 있는 이유는, html이 로드되면 스크립트가 인라인스타일로 margin-top값을 주기 때문에 우선순위에 의하여 인라인스타일이 더 높아서 hover의 css가 먹히지 않기 때문이다. 따라서 !important로 우선순위를 높여준다.




this


자바스크립트에서 this는


1. 메서드에서 호출되는 경우, 해당 메서드를 호출한 객체에 바인딩됨.

2. 함수에서 호출되는 경우, 전역객체에 바인딩됨(js에선 window)


2의 경우가 문제인데, 만약 메서드 내에 함수를 정의하는 경우 해당 함수의 this는 메서드가 있는 객체에 바인딩되는게 아니라 전역객체에 바인딩 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var value = 100;
 
var myObject = {
    value: 1,
    func1: function() {
        this.value += 1;
        console.log('func1() called. this.value: ' + this.value);
        
        var func2 = function() {
            this.value += 1;
            console.log('func2() called. this.value: ' + this.value);
            
            var func3 = function() {
                this.value += 1;
                console.log('func3() called. this.value: ' + this.value);
            }
            
            func3();
        }
        
        func2();
    }
};
myObject.func1();

cs


위의 결과는 


func1() called. this.value: 2

func2() called. this.value: 101

func3() called. this.value: 102


와 같이 나타난다. this.value가 2, 3, 4로 나오는게 자연스럽지만 func1의 this는 myObject에 바인딩되고, 내부함수인 func2, 3은 myObject가 아닌 window에 바인딩되기 때문이다. 따라서 객체 밖의 변수 value에 접근하는 것이다.

따라서 이런 객체의 메서드의 내부함수에서 객체에 접근하려면 this를 따로 참조할 수 있게 해줘야 한다.


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
var value = 100;
 
var myObject = {
    value: 1,
    func1: function() {
        var that = this;
        that.value += 1;
        console.log('func1() called. that.value: ' + that.value);
        
        var func2 = function() {
            that.value += 1;
            console.log('func2() called. that.value: ' + that.value);
            
            var func3 = function() {
                that.value += 1;
                console.log('func3() called. that.value: ' + that.value);
            }
            
            func3();
        }
        
        func2();
    }
};
myObject.func1();

cs


위의 결과는


func1() called. that.value: 2

func2() called. that.value: 3

func3() called. that.value: 4


와 같이 나타난다. 원하는 결과를 보여준다.




생성자 함수


자바스크립트에서 생성자 함수는 함수에 new를 붙이면 그것이 생성자 함수가 된다. 가령, 어떤 함수 func이 선언되었다면


var foo = new func();


과 같이 사용하면 func함수가 생성자함수로 작동하여 객체를 반환시킨다.

이 때, 생성자 함수에 return을 명시할 필요는 없다. 다만, 명시적으로 객체를 반환시키는 경우엔 해당 객체를 반환시키며, 객체가 아닌 String, Number, Boolean 등을 반환시키면 해당 반환은 무시하고 this가 바인딩된 객체를 반환시킨다.

작동 메커니즘은 다음과 같다.


1. 함수가 new와 함께 호출되면, 빈 객체를 생성한다.

2. 해당 객체에 this를 바인딩 시킨다.

3. 함수가 실행된다.

4. 해당 객체를 반환한다.


따라서 생성자 함수는 내부적으로 this를 사용하여 매개변수를 처리하면 된다.


1
2
3
function func(name) {
    this.name = name;
}
cs



위와 같이 작성하면, 빈 객체를 생성하고 해당 객체의 name프로퍼티에 매개변수로 받은 name을 넣는 것이다.

생성자 함수는 어떤 함수에도 사용이 되므로, 생성자 함수로 설계되지 않은 함수가 생성자 함수로 사용될 여지가 있다.

따라서 보통 생성자 함수는 첫글자를 대문자로 하는 관습이 있다.

또, 생성자 함수임에도 불구하고 new 키워드를 사용하지 않아 일반 함수처럼 호출하면 return값이 없기 때문에 undefiend가 반환되므로, 이를 막기 위해 다음과 같이 작성한다.


1
2
3
4
5
function A(arg) {
    if (!(this instanceof A))
        return new A(arg);
    this.value = arg ? arg : 0;
}
cs


2라인을 보자. 생성자 함수로 사용되지 않은 경우, this는 전역객체인 window로 바인딩 된다. 따라서 this instanceof A는 false가 되기 때문에, 강제적으로 A를 생성자 함수로써 사용하고 그 값을 리턴해준다.

그리고 생성자함수로써 제대로 사용이 되었다면, 매개변수 값인 arg를 반환하고 만약 매개변수가 없으면 0값을 반환하는 조치도 취해놓은 것을 4라인에서 볼 수 있다.


여기서 2라인의 A는 arguments.callee 로써 표현될 수도 있다. arguments.callee가 호출되는 함수 정보를 갖고 있기 때문에, 여러 함수에 걸쳐 사용할 수 있다.




프로토타입, 그리고 프로토타입 체이닝.


모든 객체는 생성됨과 동시에 __proto__프로퍼티를 갖게 되는데, 이는 프로토타입 객체를 가리킨다.

객체의 기본은 Object.prototype이다.

함수의 경우 __proto__는 Function.prototype을, 배열의 경우에는 Array.prototype을 가리킨다. (그 외 Boolean, Number등이 있다)

여기서 Function.prototype, Array.prototype도 객체이므로 결국 이들의 __proto__는 Object.prototype을 가리킨다.

따라서 결국 모든 객체는 Object.prototype으로 귀결되며, Object.prototype만이 __proto__프로퍼티가 없다.

함수를 새로 정의하는 경우, 함수이름.prototype 프로퍼티를 갖게 된다.

그리고 이 함수를 생성자함수로 사용하게 된다면, 생성된 객체는 이 함수의 prototype프로퍼티를 __proto__프로퍼티로 갖게 된다.


즉 함수가 아닌 객체는 prototype프로퍼티를 갖고 있지 않다. 함수가 prototype프로퍼티를 갖고 있다.


여기서 프로토타입 체이닝의 개념이 발생하는데, 어떤 프로퍼티를 호출했을 때


1. 호출된 객체에서 찾는다.

2. 없으면 __proto__에서 찾는다.

3. 없으면 __proto__의 __proto__에서 찾는다.

4. 결국 Object.prototype에도 없으면 오류를 발생시킨다.


이것이 프로토타입 체이닝의 개념이다.

'Daily Study' 카테고리의 다른 글

16.06.01  (0) 2016.06.01
16.05.31  (0) 2016.05.31
16.05.30  (0) 2016.05.30
16.05.28  (0) 2016.05.28
16.05.22  (0) 2016.05.22
Comments