2016-08-19 7 views
1

내 동료와 나는이 토론을 여러 번했다. 클래스 메소드를 정의하는 두 가지 방법이 있습니다. 첫 번째 방법은 함수 선언 함께 :클래스 메서드에 대한 함수 선언 또는 표현식?

class Action { 
    public execute(): void { 
     this.doSomething(); 
    } 
    ... 
} 

기능 선언을 쉽게 읽을 경향이있다. Action의 인스턴스마다 하나의 함수 객체 만 사용되므로 더 친숙합니다.

번째 함수 함께 :

class Action { 
    public execute:() => void =() => { 
     this.doSomething(); 
    }; 
    ... 
} 

함수 표현식 개 입력 (특히 유형 정의)와, 읽기 어렵게하고, Action의 각 인스턴스에 대한 새로운 기능 오브젝트를 생성 할 필요. 그리고 많은 양의 객체를 생성한다면 그것은 나쁘다. 그러나

, 함수 표현식은 하나의 작은 이익을 가지고 : 함수 표현식이 예상대로 작동으로 선언

var instance = new Action(); 
setTimeout(instance.execute); 

하는 방법에있어서, 그들은 상관없이 그들을 호출 자합니다 (Action 예를 IE) this의 컨텍스트를 보존 케이스. 함수 선언은 비참하게 실패하지만, 쉽게 대신이 일을 해결할 수 있습니다 : 그래서

var instance = new Action(); 

setTimeout(() => instance.execute()); 
// or 
setTimeout(instance.execute.bind(instance)); 

, 하나는 다른 통해 더 나은 연습 간주됩니다, 또는 우대 /이 순전히 상황입니까?

답변

3

내 생각에 화살표 함수는 this (예 : 이벤트 처리기로 전달 된 경우)에 다른 컨텍스트로 함수를 호출 할 수 있다는 것을 알고있을 때만 클래스 메서드로 사용해야하며 사용자는 Function.prototype.bind을 사용하지 마십시오.

코드 가독성을 위해 쓴 것처럼 여러 가지 이유가 있지만 주된 이유는 상속입니다. 당신이 화살표 기능을 사용하는 경우 당신은 단순히 구성원으로 인스턴스에 기능을 할당하지만,이 함수는 프로토 타입에 추가되지 않습니다 :

// ts 
class A { 
    fn1() {} 

    fn2 =() => {} 
} 

// js 
var A = (function() { 
    function A() { 
     this.fn2 = function() { }; 
    } 
    A.prototype.fn1 = function() { }; 
    return A; 
}()); 

그래서 당신은이 클래스를 확장하려는 경우 발생 및 fn2 메소드를 재정의 하시겠습니까?

class A { 
    fn1() {} 

    fn2() {} 
} 

class B extends A { 
    fn2() { 
     super.fn2(); 
    } 
} 

가 있습니다에 비해 단지 끔찍

class B extends A { 
    private oldFn2 = this.fn2; 

    fn2 =() => { 
     this.fn2(); 
    } 
} 

:이 프로토 타입의 속성이 아닌 부분이기 때문에
, 당신은 같은 일을해야합니다 익명 기능보다 bind 방법을 사용하는 것을 선호하는 몇 가지 이유. 정확히 같은 기능이지만 특정 this에 바인딩되어 있기 때문에 더 암시 적이라는 것을 알았습니다. 반면 익명 함수에서는 실제 함수를 호출하는 것 외에 다른 코드를 추가 할 수 있습니다.fn

function fn(one, two, three) {} 
fn.bind(null, 1, 2)(3); 
fn(1, 2, 3); 

두 호출 여기에 동일합니다

또 다른 한가지는 bind 기능 this으로 간주됩니다 객체뿐만 아니라 매개 변수를 결합 할뿐만 아니라 바인드 할 수 있다는 것입니다.
익명의 기능을 사용하여 수행 할 수 있지만 항상 그런 것은 아닙니다.

var a = ["zero", "one", "two", "three", "four", "five"]; 
function fn(value, index) { 
    console.log(value, index); 
} 

// works 
a.forEach((item, index) => { 
    setTimeout(() => { 
     fn(item, index); 
    }, 45); 
}); 

// works 
for (let i = 0; i < a.length; i++) { 
    setTimeout(() => { 
     fn(a[i], i); 
    }, 45); 
} 

// doesn't work as i is undefined when the function is invoked 
for (var i = 0; i < a.length; i++) { 
    setTimeout(() => { 
     fn(a[i], i); 
    }, 45); 
} 

// works because the value of i and the value of a[i] are bound 
for (var i = 0; i < a.length; i++) { 
    setTimeout(fn.bind(null, a[i], i), 45); 
} 
+0

우수. 상속/프로토 타입 시나리오도 고려하지 않았습니다. 메소드가 이벤트 핸들러로 사용될지라도, 위에서 설명한대로 익명 함수 랩퍼를 사용하여 대부분의 상황을 완화 할 수 있다고 생각합니다. – Craxal

+0

@Craxal 익명의 함수 대신에'bind' 함수를 사용하는 편이 낫지 만 어느 쪽의 경우 든 엉성한 것이 아닙니다. –

+0

'bind '를 선호한다면 어떤 이점이 있습니까? 명시 적으로 인수를 처리하고 전달하는 것에 대해 걱정할 필요가 없다고 가정합니다. – Craxal