본문으로 건너뛰기

JS 학습 노트 3_함수 표현식

무료2015-04-07#JS#js函数表达式

함수 표현식에 대해 이야기할 수 있는 것은 많다: 클로저, this, 스코프 체인, 프라이빗 속성。。더 깊이 파고들면: context, 변수 객체, 활성 객체, 내부 속성。。。

##1. 함수 표현식과 함수 선언의 차이##

함수 선언에는 "호이스팅"(hoisting) 특성이 있지만 함수 표현식에는 없습니다. 즉, 함수 선언은 코드 로드 시 미리 context 에 로드되지만, 함수 표현식은 식 문을 실행할 때만 로드됩니다

##2. 클로저##

다른 함수 스코프 내의 변수에 접근할 수 있는 함수. 클로저는 다른 스코프 내의 변수에 접근할 수 있으므로 클로저로 얻은 변수 값은 최종값이며, 해당 변수의 어느 시점의 값이 아닙니다. 매우 고전적인 예가 있습니다:

function createFuns(){
  var result = new Array();
  for(var i = 0;i < 10;i++){
    result[i] = function(){
      return i;
    };
    
    /*
    result[i] = function(arg){
      return function(){
        return arg;
      }
    }(i);//此处匿名函数立即执行的 () 可以省略,因为 function 在等号右边出现,不存在歧义(一般形式是 (function(){})())
    */
  }
  
  return result;
}

createFuns 함수는 한 세트의 함수를 반환합니다. 이 함수들의 실행 결과는 모두 10 입니다 (클로저로 얻은 변수 값은 최종값). 그러나 주석 중의 방식으로 반환된 함수의 실행 결과는 i 의 현재 값입니다. 값 전달이기 때문입니다

##3. 함수 표현식에서의 this##

내부 함수는 외부 함수 내의 this 와 arguments 객체에 직접 접근할 수 없습니다. 내부 함수가 이 두 변수를 검색할 때 해당 활성 객체까지만 검색하기 때문입니다

P.S. 활성 객체는 스코프 체인의 실체이며, 스코프 체인은 추상 개념이지만, 활성 객체는 이 개념의 구체적 구현입니다. 사실 스코프 체인은 코드에 매핑하면 변수 객체 체인이며, 또 변수 객체가 나왔지만 두려워하지 마십시오. 전혀 복잡하지 않습니다:

실행 환경 (context) 에서 정의된 모든 변수와 함수는 변수 객체에 저장됩니다. 실행 환경이 함수라면 해당 함수의 활성 객체를 변수 객체로 하고, 변수 객체 체인의 한 고리, 즉 스코프 체인의 한 고리로 합니다.

처음에 함수의 활성 객체에는 속성이 하나뿐입니다——arguments 객체. 함수 내부에서 커스텀 속성을 하나 선언할 때마다 해당 함수의 활성 객체에 속성을 하나 추가합니다。。。

네, 이만큼 이야기했지만, 사실 한 마디입니다:this 란 활성 객체/변수 객체의 참조입니다.

아직 잘 모르겠다면 선배의 블로그 글 을 참조하십시오.顺便에이 선배의 다른 블로그 글도 추천합니다. js 에 관한 것은 모두 훌륭합니다

##4. 변수의 중복 선언##

구문 오류를 일으키지 않습니다.余分한 선언은 자동으로 무시되지만, 선언 동시의 초기화 조작실행됩니다. 예를 들어:

var x = 1;
var x = 2;//var 선언은 무시되므로 에러가 나지 않지만, 대입은 실행됨
alert(x);//2

##5. 블록 레벨 스코프를 구현하는思路##

무명 함수를 선언하여 즉시 호출하면 무명 함수 내부가 블록 레벨 스코프가 됩니다. 구체적 구현:

(function(){/*블록 레벨 스코프*/})();

주의: 함수 표현식과 함수 선언의 모호함을 없애기 위해 둥근 괄호가 필요합니다 (인터프리터의 관점에서 보면 그렇습니다). 함수 선언 뒤에 직접 둥근 괄호를 붙일 수 없지만 함수 표현식은 가능합니다.

P.S. 示例 중의 코드는 IIFE 를 구현하는 방식 중 하나일 뿐입니다. 다른 것도 몇 가지 있습니다. 상세한 내용은 [javascript]IIFE 즉시 실행하는 함수 표현식 을 참조하십시오. 이 블로그 글에는 상세한 비교가 기재되어 있습니다

##6. 프라이빗 변수##

함수 내부에서 var 또는 function 으로 선언된 변수는 프라이빗 변수입니다. (인스턴스는 직접 접근할 수 없지만, 공개 함수를 정의하여 접근 인터페이스를 제공할 수 있습니다)

한편, this.attr = value; 방식으로 선언된 변수는 공개 변수입니다. (인스턴스는 직접 접근할 수 있습니다)

##7. 클로저, 무명 함수, 내부 함수, 내부 무명 함수의 차이##

  • 클로저: 다른 함수 스코프 내의 변수에 접근할 수 있는 함수

  • 무명 함수: 이름이 없는 함수 표현식

  • 내부 함수: 함수 내부에서 선언된 함수, 즉 클로저

  • 내부 무명 함수: 함수 내부에서 선언된 무명 함수. 물론, 이것도 클로저입니다

P.S. 클로저를 남용하면 대량의 메모리를 점유할 수 있습니다. 클로저가 바깥쪽 함수 스코프 내의 변수에 접근할 수 있는 것은 클로저의 활성 객체가 바깥쪽 함수의 활성 객체에 대한 참조를 보유하기 때문입니다

클로저가 파기된 후에야 바깥쪽 함수 내의 변수를 파기할 수 있습니다. 적시에파기할 수 없으므로 대량의 메모리를 점유할 수 있습니다

##8. 함수를 실행하는 전 과정##

  1. 실행 환경 context 를 생성.context 에는 내부 속성 [[Scope]] 이 있습니다

  2. 스코프 체인 ScopeChain 을 업데이트

  3. 활성 객체를 생성

  4. 활성 객체의 this, arguments, 형식 매개변수 등의 각 속성을 초기화

  5. 함수 본문을 실행

  6. 활성 객체를 파기 (클로저가 존재할 경우 파기할 수 없음)

  7. 스코프 체인을 업데이트

##9.js 싱글톤 패턴과 모듈 패턴##

  • 싱글톤 패턴: 인스턴스가 하나뿐인 객체를 생성하는 패턴의 일종.说白了, 패턴이란 방법이며, 디자인 패턴이란 선배가 정리한 좋은 방법입니다. js 에서 싱글톤 패턴을 구현하는 것은 특히簡単합니다:

     var singleton = {attr1: value1, attr2: value2};
    

맞습니다, 객체 리터럴입니다. 즉 무명 객체를 생성한 것으로, 생성자의 이름을 모르므로 당연히 2 번째 인스턴스를 생성할 수 없습니다

  • 모듈 패턴: 더글라스가 싱글톤을 강화하기 위해 제안한 방법. 싱글톤에 프라이빗 속성과 공개 속성을 추가할 수 있습니다 (때로는 특권 속성이라고도 하며, 프라이빗 속성을 수정할 권한이 있는 속성을 나타냅니다). 예를 들어:

     var singleton = function(){
       //프라이빗 속성
       var privateStr = 'secret';
       function addPrefix(){
         privateStr = 'this is my ' + privateStr;
       }
       
       //공개 속성 (특권 속성)
       return{//무명 객체를 반환
         getStr : function(){
           addPrefix();
           return privateStr;
         }
       };
     }();//또 다시 무명 함수의 즉시 실행
     
     alert(singleton.getStr());
     
    

P.S. 싱글톤이 필요 없고 프라이빗 속성만 보호하면 된다면 이렇게 할 수 있습니다:

function Cat(){
  //프라이빗 속성
  var privateStr = 'secret';
  function addPrefix(){
    privateStr = 'this is my ' + privateStr;
  }
  
  //공개 속성 (특권 속성)
  this.getStr = function(){
    addPrefix();
    return privateStr;
  }
}
var obj = new Cat();
alert(obj.getStr());

###참고 자료###

댓글

아직 댓글이 없습니다

댓글 작성