2012-08-07 7 views
2

이전에 JavaScript로 요소를 사라지게하는 방법을 찾고 있었는데이 함수 (객체)를 발견했습니다. 나는 그것이 어떻게 작동하는지 궁금해하기 시작했다?이 JavaScript는 어떻게 작동합니까?

var fadeEffect=function(){ 
return{ 
    init:function(id, flag, target){ 
     this.elem = document.getElementById(id); 
     clearInterval(this.elem.si); 
     this.target = target ? target : flag ? 100 : 0; 
     this.flag = flag || -1; 
     this.alpha = this.elem.style.opacity ? parseFloat(this.elem.style.opacity) * 100 : 0; 
     this.si = setInterval(function(){fadeEffect.tween()}, 20); 
    }, 
    tween:function(){ 
     if(this.alpha == this.target){ 
      clearInterval(this.elem.si); 
     }else{ 
      var value = Math.round(this.alpha + ((this.target - this.alpha) * .05)) + (1 * this.flag); 
      this.elem.style.opacity = value/100; 
      this.elem.style.filter = 'alpha(opacity=' + value + ')'; 
      this.alpha = value 
     } 
    } 
} 
}(); 

이 방법은 자체 호출이며 두 가지 방법으로 하나의 개체 만 반환한다는 것을 알고 있습니다. 내 주요 관심사는 왜이 키워드를 사용합니까? 'this'키워드가 "fadeEffect"라는 개체 이름의 자리 표시 자라고 가정합니다. 'this'가 여러 객체를 만드는 데 사용 되었다면 이해 하겠지만 왜 여기에 사용됩니까?

한가지 괴롭 히고 나입니다이 삼항 연산자 ... 도대체 그 작업을 수행하는 방법

this.target = target ? target : flag ? 100 : 0; 

? 두 개의 삼항 연산자가 내가 결코 생각할 수없는 것으로 결합 된 것과 같은 것입니까?

답변

3

생각합니다. this 키워드는 자체 호출 함수가 리턴하는 오브젝트 리터 2을 다시 참조합니다. 즉, 이라는 전역 이름 공간 (또는 fadeEffect이 정의 된 범위)에서 에 액세스 할 수 있지만 외부 범위에있을 수있는 다른 변수와 간섭하지 않습니다.

두 메서드는 반환 된 개체의 새 속성을 설정합니다. 그게 전부입니다. 개인적으로 나는이 될, 음, 나쁜 코드를 찾을 ... 폐쇄는이 예에서 더 나은 선택이었을 것입니다 :

var fadeEffect=function(){ 
    var elem,target,flag,alpha,si;//make private 
    return{ 
     init:function(id, flag, target){ 
      elem = document.getElementById(id); 
      clearInterval(elem.si); 
      target = target ? target : flag ? 100 : 0; 
      flag = flag || -1; 
      alpha = elem.style.opacity ? parseFloat(elem.style.opacity) * 100 :0; 
      si = setInterval(function(){fadeEffect.tween()}, 20); 
     }, 
     tween:function(){ 
      if(alpha == target){ 
       clearInterval(si);//this.elem.si doesn't add up, init defines it as this.si 
      }else{ 
       var value = Math.round(alpha + ((target - alpha) * .05))+ (1 * flag); 
       elem.style.opacity = value/100; 
       elem.style.filter = 'alpha(opacity=' + value + ')'; 
       alpha = value 
      } 
     } 
    } 
}(); 

이 같은 일을하지만, 다른 코드가 대상의 값을 방해 할 수 없습니다 , 또는 엉망진창 등등 ...이 경우에는 this 키워드가 필요하지 않다고 말하는 것은 맞습니다.하지만이 글을 쓰는 사람은 JS 폐쇄에 익숙하지 않거나 적어도 작업. 이 코드는 효과적으로 싱글 톤 패턴을 시뮬레이트하거나 객체 리터럴을 클래스의 인스턴스로 취급합니다. 내 생각에, 저자는 고전적인 OOP에 익숙하지만 프로토 타입 상속에 익숙하지 않다. 어쨌든, 위의 코드는 안전하고, 안전이 이럴

당신의 중첩 된 원의 문제에

더, 나는 JSLint를 사용하여 아래의 코드를 확인한 결과는 더 짧은, 아직 명확한 대안을 제안 : 사용 삼항 다음에 기본 연산자, 어쨌든

//JSLint recommends this 
target = argTarget || argFlag ? 100 : 0; 
//over nested ternary 
target = argTarget ? argTarget : argFlag ? 100 : 0; 

, 여기에만 위험 this 구조를 사용하지 않는,하지만 놀라 울 정도로 강력한 기능 BTW 폐쇄, 자바 스크립트 중 하나를 사용하여 가치가 좀 더 자세히 살펴 본다, 동일한 코드입니다 당신이 그들과 함께 할 수있는 일!그들이, 외부 조작에 의해를 오버라이드 (override) 할 수 없다

var fadeEffect=(function() 
{ 
    var elem,target,flag,alpha,si;//make private 
    //define private 'methods': functions will be available, but only to return object 
    //tween shouldn't be callable, it's a callback for the interval, which is set in init 
    function tween() 
    { 
     if(alpha === target) 
     { 
      clearInterval(si);//this.elem.si doesn't add up, init defines it as this.si 
     } 
     else 
     { 
      alpha = Math.round(alpha + ((target - alpha) * 0.05))+ (1 * flag); 
      //don't know why 1*flag is needed here, suggest: 
      //alpha = Math.round(alpha + ((target - alpha) * 0.05)) + (+flag); +flag coerces to numeric 
      elem.style.opacity = alpha/100; 
      elem.style.filter = 'alpha(opacity=' + alpha + ')'; 
     } 
    } 
    return{ 
     init:function(id, argFlag, argTarget)//arguments !== closure scope 
     { 
      if (si !== undefined && si !== null) 
      { 
       clearInterval(si); 
      } 
      elem = document.getElementById(id); 
      //JSLint recommends this: 
      target = argTarget || argFlag ? 100 : 0; 
      //over nested ternary 
      target = argTarget ? argTarget : argFlag ? 100 : 0; 
      flag = argFlag || -1; 
      alpha = elem.style.opacity ? parseFloat(elem.style.opacity) * 100 :0; 
      si = setInterval(tween, 20);//just a reference to the tween function will do 
     } 
    }; 
})(); 
fadeEffect.init('someId',1,50);//will set things in motion 
fadeEffect.tween();//undefined 
console.log(fadeEffect.target); 
fadeEffect.target = document.getElementById('someOtherId');//no problem, but won't change the value of var target 

이 방법은 tween 방법은 호출 할 수 없습니다 있지만, 간격 및 요소에 의해되는 객체, 그 방법/기능은 자신의 마법을 노력하고 있습니다 물체에 내재되어있다. 이것은 더 안전한 구조를 만들어냅니다. 더 많은 것은 무엇입니까? .init 메서드를 오버라이드하면 객체가 쓸모 없지만 무해하게 렌더링됩니다. 이를 두 메소드를 엉망으로 만들 수있는 코드와 비교해보십시오. 그러나 간격을 유지하십시오 ... 나쁜 소식입니다. 간격이 너무 짧아 콜백 함수가 너무 많이 삭제되어 코드가 비참하게 실패 할 수 있습니다. :

//asume your code using this.tween(); 
fadeEffect.init('id',1,123); 
delete fadeEffect.tween; 
//inside fadeEffect: 
setInterval(function(){fadeEffect.tween()}, 20); 
//should be written as: 
setInterval(fadeEffect.tween,20); 
    // === setInterval(undefined,20); === :-(
+0

그래, 그게 내가 생각하고 있었던거야. 이 경우에는 필요하지 않지만이 네임 스페이스에 변수 (속성)를 만들 때 즉시 사용됩니다. this.elem.si는 내가 생각하기에 오류입니다. 왜냐하면 그것은 나에게도 부합하지 않기 때문입니다. this.si로 정의되었습니다. 나는이 코드를 작성한 사람이 사용한 것보다 당신의 코드 방법이 더 좋다고 생각합니다. 클로저와 네임 스페이스에 대한 노출이 있습니다. 나는 아직 그 주제에 관해서는 편안하게 말할 수 없다. – W3Geek

+0

"이"는 필요하지 않다고 말하면 돈이 옳다. 게시 한 코드는 객체 리터럴을 생성하지만 생성자 함수로 작성됩니다. 그것은 단지 혼란스럽고 나쁜 습관 일뿐입니다. 어떤 변수가 필요한지 알고 있다면 클로저를 사용하십시오. 객체가 작동하는 방식에 따라 실수로 'target'속성을 변경하여 다른 요소에서 간격이 갑자기 사라 지도록하여 2 개의 반투명 요소로 끝납니다. 폐쇄 장치를 사용하면 보호 할 수 있습니다. 이 코드를 사용 가능하고 안전한 버전으로 조금 더 작업 할 것입니다. (이 코드는 여전히 해결해야 할 몇 가지 문제가 있습니다) –

+0

이 대답이 받아 들여지기에는 너무 좋은지 궁금합니다 ... – ted

4

두 번째 질문은. 이렇게하면 더 명확 해집니다.

this.target = (target ? target : (flag ? 100 : 0)); 

그래, 중첩 된 삼항 연산자! 단어로 작성 :

this.target = (목표가 true 값입니까? 그렇다면 목표를 사용하십시오. 그렇지 않으면 마지막 부분의 결과를 사용하십시오 -> (진위 값을 사용합니까? 사용하십시오. 0)). this.target = target ? target : flag ? 100 : 0;에 대한

+0

어떻게 작동합니까? – W3Geek

+1

당신을 위해 그것을 밖으로 쓴다. 분명히해야합니다 ... –

2

한 번 더 설명 : 네임 스페이스로의

if(target){ 
    this.target = target; 
} 
else{ 
    if(flag){ 
    this.target = 100; 
    } else { 
    this.target = 0; 
    } 
} 
관련 문제