본문 바로가기
Study/모던 자바 스크립트 Deep Dive

Day3. 13장 스코프 ~ 18장 함수와 일급 객체

반응형

사내 스터디로 진행되는 "모던 자바 스크립트 Deep Dive" 리딩 관련 정리입니다

깊이 있는 프론트 지식 공유보단 기본적으로 알아야할 지식 중심으로 키워드와 라이프싸이클을 중심으로 기술하려고합니다

http://www.yes24.com/Product/Goods/92742567

 

모던 자바스크립트 Deep Dive - YES24

『모던 자바스크립트 Deep Dive』에서는 자바스크립트를 둘러싼 기본 개념을 정확하고 구체적으로 설명하고, 자바스크립트 코드의 동작 원리를 집요하게 파헤친다. 따라서 여러분이 작성한 코드

www.yes24.com


13장. 스코프

  • 스코프
    • 식별자가 유효한 범위를 나타낸다
    • 모든 식별자(변수 이름, 함수 이름, 클래스 이름 등등)는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정된다
  • 식별자 결정
    • 자바 스크립트 엔진은 이름이 같은 두 개의 변수 중에서 어떤 변수를 참조해야 할 것인지를 결정하는데 이를 식별자 결정이라 한다
    • 식별자는 어떤 값을 구별할 수 있어야 하므로 유일 해야한다
    • 식별자인 변수 이름은 중복될 수 없다, 즉 하나의 값은 유일한 식별자에 연결되어야한다 ( 같은 스코프 내에서 )
    •  스코프는 네임스페이스
      // 13-1
      var x = 'global';
      
      function foo() {
          var x = 'local';
          console.log(x); // 'local'
      }
      
      foo();
      
      console.log(x); // 'global'
  • ※ var 키워드의 예외적인 중복 선언 가능
    // 13-2
    function foo() {
        var x = 1;
        var x = 2; // var 키워드로 선언된 변수는 같은 스코프내에서 중복 선언을 허용한다
        // 자바 스크립트 엔진을 통해 x = 2; 처럼 동작
        
        console.log(x); // 2
    }
    
    foo();
    
    
    function bar() {
        let x = 1;
        let x = 2; // SyntaxError: Identifier 'x' has already been declared
    }
    
    bar();​
     
  • 스코프의 종류
    • 전역 스코프, 지역 스코프로 나뉜다
      // 13-3
      var x = "global x";
      var y = "global y";
      
      function outer() {
          var z = "outer's local z";
          
          console.log(x); // 1.global x
          console.log(y); // 2.global y
          console.log(z); // 3.outer's local z
          
          function inner() {
          	var x = "inner's local x";
              
              console.log(x); // 4.inner's local x
              console.log(y); // 5.global y 
              console.log(z); // 6.outer's local z
          }
         	
          inner();
      }
      outer();
      
      console.log(x); // global x
      console.log(z); // ReferenceError: z is not defined​
      • outer 함수 내부 범위와 inner 함수 내부의 {} 로 둘러쌓인 코드 블럭을 지역 스코프라고 한다
      • 가장 밖의 var x, y 등을 전역 스코프라고 한다
      • 전역 변수는 어디서든 참조 가능
      • 지역 변수는 자신의 지역 스코프와 하위 지역 스코프에서 유효
  • 스코프 체인
    • 스코프가 함수의 중첩에 의해 계층적 구조를 갖는다 ( 스코프 체인 )
    • 함수 몸체 내부에서 함수가 정의된 것을 함수의 중첩이라고 한다
    • 함수 몸체 내부에서 정의한 함수를 중첩 함수, 중첩 함수를 포함하는 함수를 외부 함수라고 한다
    • 변수를 참조할 때 자바 스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다 ( 스코프 체인에 의한 변수 검색 )
  • 스코프 체인에 의한 변수 검색
    • 상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조할 수 있지만 하위 스코프에서 유효한 변수를 상위 스코프에서 참조할 수 없다
    • 함수를 검색하는 방식도 동일하다
  • 함수 레벨 스코프
    • 대부분의 프로그래밍 언어는 함수 몸체만이 아니라 모든 코드 블록 (if, for, while 등)이 지역 스코프를 만든다
      ( 블록 레벨 스코프 )
    • 하지만 var 키워드로 선언된 변수는 오로지 함수의 코드 블록(함수 몸체)만을 지역 스코프로 인정한다.
      ( 함수 레벨 스코프 )

      // 13-4
      var x = 1;
      
      if (true) {
          var x = 10;
      }
      
      console.log(x); // 10
      var의 특성으로 if문 코드블록안에서 생성되었을지라도 전역변수이다 ( x = 10; 이랑 동일 )

      // 13-5
      var i = 10; 
      
      for (var i = 0; i < 5; i++) { 
          console.log(i); // 0, 1, 2, 3, 4 
      } 
      
      console.log(i); // 5 << 10을 기대했다면 var의 특성으로 인해 의도치않게 값이 변경됐다​
  • 렉시컬 스코프
    • 함수를 어디서 호출했는지에 따라 함수의 상위 스코프를 결정 ( 동적 스코프 )
    • 함수를 어디서 정의했는지에 따라 함수의 상위 스코프를 결정 ( 렉시컬 스코프 )
    • 자바 스크립트는 렉시컬 스코프를 따르므로 함수를 어디서 호출했는지가 아니라 함수를 어디서 정의했는지에 따라 상위 스코프를 결정
    • 함수가 호출된 위치는 상위 스코프 결정에 어떠한 영향도 주지않는다
      // 13-6
      var x = 1;
      
      function foo() {
          var x = 10;
          bar();
      }
      
      function bar() {
          console.log(x);
      }
      
      foo(); // 1
      bar(); // 1

 

14장. 전역 변수의 문제점

  • 전역 변수의 무분별한 사용은 위험하다
  • 지역 변수의 생명 주기는 함수의 생명 주기와 일치한다 ( 함수가 끝나면 변수도 소멸된다 )
  • 변수의 생명 주기는 메모리 공간이 확보된 시점부터 메모리 공간이 해제되어 가용 메모리 풀에 반환되는 시점까지
  • 일반적으로 함수가 종료하면 함수가 생성한 스코프도 소멸, 하지만 누군가 스코프를 참조하고 있다면 스코프는 해제되지않고 생존
  • 호이스팅
    • 스코프를 단위로 동작
    • 변수 선언이 스코프의 선두로 끌어 올려진 것 처럼 동작하는 자바스크립트 고유의 특징
    • 변수 선언이 끌어 올려지는 것, 초기화랑 같이 끌어올려지는게 아니다
// 14-1
var x = 'global';

function foo() {
    console.log(x); // undefined
    var x = 'local';
}

foo();
console.log(x); // 'global'

 

  • 전역 변수의 생명주기
    • 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체
    • 코드의 마지막 문이 실행될때까지 유지된다
    • var 키워드로 선언한 전역 변수의 생명 주기는 전역 객체의 생명 주기와 일치한다

 

  • 전역 변수의 문제점
    • 암묵적 결합
      • 전역 변수를 선언한 의도는 전역, 즉 코드 어디서든 참조하고 할당할 수 있는 변수를 사용하겠다는 것
      • 이는 모든 코드가 전역 변수를 참조하고 변경할 수 있는 암묵적 결합을 허용하는 것이다
      • 변수의 유효 범위가 크면 클수록 코드의 가독성은 나빠지고, 의도치 않게 상태가 변경될 위험성도 높아진다
    • 긴 생명주기
      • 전역 변수는 생명 주기가 길다 ( 메모리 리소스도 오랜 기간 소비한다 )
      • 지역 변수는 전역 변수보다 생명 주기가 훨씬 짧고, 메모리 리소스도 짧은 기간만 소비한다
    • 스코프 체인 상에서 종점에 존재
      • 전역 변수의 검색 속도가 가장 느리다 ( 큰 차이는 없지만, 느리긴 제일 느리다 )
    • 네임 스페이스 오염
      • 파일이 분리되어 있더라도, 하나의 전역 스코프를 공유한다
      • 같은 이름을 쓸 경우 예상치 못한 결과를 가져올 수 있다 ( 같은 이름을 쓰는지 조차 잘 몰를 수도 있다 )

  • 전역 변수의 사용을 억제하는 방법
    • 반드시 전역 변수를 사용해야할 이유를 찾지 못한다면, 지역 변수를 사용하자
    • 변수의 스코프는 좁을 수록 좋다
    • 즉시 실행 함수
      • 함수 정의와 동시에 호출되는 즉시 실행 함수는 단 한번만 호출
      • 모든 코드를 즉시 실행 함수로 감싸면 모든 변수는 즉시 실행 함수의 지역 변수가 된다
        // 14-2
        ( function () {
        	var foo = 10; // 즉시 실행 함수의 지역 변수
            // ...
        }());
        
        console.log(foo) // ReferenceError: foo is not defined
    • 네임 스페이스 객체
      • 전역에 네임스페이스 역할을 담당할 객체를 생성하고 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가하는 방법
      • 네임스페이스를 분리해서 식별자 충돌을 방지하는 효과는 있으나, 네임 스페이스 객체 자체가 전역변수에 할당되므로 크게 유용해보이진 않는다
    • 모듈 패턴
      • 클래스를 모방해서 관련이 있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈을 만든다
      • 클로저를 기반으로 동작
      • 전역 변수 억제 효과는 물론 캡슐화까지 구현 가능하다
      • 클래스 외부에는 제한된 접근 권한을 제공하며, 원하지 않는 외부의 접근으로부터 내부를 보호하는 기능을 한다
        // 14-3
        var Counter = (function() {
        
            // private 변수
            var num = 0;
            
            // 외부로 공개할 데이터나 메서드를 프로퍼티로 추가한 객체를 반환
            return {
                increase() {
                    return ++num;
                },
                decrease() {
                    return --num;
                }
        }());
        
        console.log(Counter.num) // undefined, private 변수는 외부에서 접근 불가
        
        console.log(Counter.increase()); // 1
        console.log(Counter.increase()); // 2
        console.log(Counter.decrease()); // 1
        console.log(Counter.decrease()); // 0​

 

15장. let, const 키워드와 블록 레벨 스코프

  • var 키워드로 선언한 변수의 문제점
    • 변수의 중복 선언 허용
      • 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작
    • 오직 함수의 코드 블록만을 지역 스코프로 인정
      • 함수 외부에서 var 키워드로 선언된 변수는 코드 블록 내에서 선언해도 모두 전역 변수이다 
    • 변수 호이스팅
      • var 키워드로 변수를 선언하면 변수 호이스팅에 의해 변수 선언문이 스코프의 선두로 끌어 올려진 것처럼 동작
      • 할당문(초기화문) 이전에 변수를 참조하면 언제나 undefined가 된다
      • 변수 선언문 이전에 변수를 참조하는 것은 에러를 발생시키진 않지만, 가독성을 떨어뜨리고 오류 발생 여지를 남긴다
  • let 키워드
    • 변수 중복 선언 금지 ( 중복 선언시 SyntaxError 발생 )
    • 블록 레벨 스코프
    • 변수 호이스팅 ( 변수 선언문 이전에 참조하면 참조 에러가 발생 )
      • let 키워드로 선언한 변수는 선언 단계와 초기화 단계가 분리되어 진행된다
      • 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적 사각지대라고 부른다
      • let 키워드로 선언한 변수도 여전히 호이스팅이 발생한다
      • 단 ES6에서 도입된 let, const, class를 사용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작한다
        // 15-1
        let foo = 1;
        
        {
            console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
            let foo = 2;
        }​
    • 전역 객체와 let
      // 15-2
      var x = 1; // 전역 변수
      y = 2; // 암묵적 전역
      function foo() {} // 전역 함수
      
      let z = 3;
      
      console.log(window.x); // 1
      console.log(x); // 1
      console.log(window.y); // 2
      console.log(y); // 2
      console.log(window.foo); // f foo() {}
      console.log(foo); // f foo() {}
      
      console.log(window.z); // undefined
      console.log(z); // 3​
    • const 키워드
      • const 키워드는 상수를 선언하기 위해 사용한다
      • 선언과 초기화를 반드시 동시에 해야한다 ( SyntaxError )
        • let 키워드와 마찬가지로 블록 레벨 스코프를 가지며, 변수 호이스팅이 발생하지 않는 것처럼 동작
      • 재할당 금지
      • const 키워드로 선언한 변수에 원시 값을 할당한 경우 변수 값을 변경할 수 없다 ( immutable value )
      • const 키워드로 선언된 변수에 객체를 할당한 경우 값을 변경할 수 있다 ( 재할당만 금지, 불변은 아님 )
    • 정리
      • ES6를 사용한다면 var 키워드는 사용하지 않는다
      • 재할당이 필요한 경우에 한정해 let 키워드를 사용, 변수의 스코프는 최대한 좁게 설정한다
      • 읽기 전용으로 사용하는 원시 값과 객채에는 const 키워드를 사용한다, 보다 더 안전하게 사용할 수 있다

 

16장. 프로퍼티 어트리뷰트

  • 내부 슬롯과 내부 메서드
    • ECMAScript 사양부터 등장한 이중 대괄호 ( [[...]] )로 감싼 이름들을 지칭
    • 개발자가 직접 접근할 수 있도록 외부로 공개된 객체의 프로퍼티는 아니다 ( 자바스크립트 엔진의 내부 로직이다 )
    • 일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근은 가능하다
  • 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체
    • 자바 스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다
    • 프로퍼티 상태
      • 프로퍼티의 값
      • 값의 갱신 가능 여부
      • 열거 가능 여부
      • 재정의 가능 여부
    • 프로퍼티 디스크립터 객체 받아오기
      • Object.getOwnPropertyDescriptor(접근할 객체, 프로퍼티 "key" 값 )
      • Object.getOwnPropertyDescriptors(접근할 객체, 프로퍼티 "key" 값 )
  • 데이터 프로퍼티와 접근자 프로퍼티
    • 데이터 프로퍼티
      • 키와 값으로 구성된 일반적인 프로퍼티
      • [[value]] : 프로퍼티 값
      • [[Writable]] : 프로퍼티 값의 변경 가능 여부, boolean
      • [[Enumerable]] : 프로퍼티의 열거 가능 여부, boolean
      • [[Configurable]] : 프로퍼티의 재정의 가능 여부, boolean
    • 접근자 프로퍼티
      • 자체적으로 값을 갖지 않고, 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성
      • [[Get]] : 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수다
      • [[Set]] : 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수다
      • [[Enumerable]] : 데이터 프로퍼티의 Enumerable과 같다
      • [[Configurable]] : 데이터 프로퍼티의 Configurable과 같다 
    • 프로토 타입(prototype)
      • 어떤 객체의 상위(부모) 객체 역할을 하는 객체이다.... ( 그냥 부모역할 객체... 말을 너무 어렵게 써놨.. )
      • 하위 객체에게 자신의 프로퍼티와 메서드를 상속한다
      • 상속 받은 하위 객체는 자신의 프로퍼티 또는 메서드인 것처럼 자유롭게 사용 할 수 있다
  • 프로퍼티 정의
    • 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나, 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의 하는 것을 말한다
    • Object.defineProperty: 한번에 하나의 프로퍼티만 정의
    • Object.defineProperties: 여러 개의 프로퍼티를 한번에 정의
  • 객체 변경 방지
    • 객체는 변경 가능한 값이므로, 재할당 없이 직접 변경할 수 있다
    • 프로퍼티를 추가, 삭제, 갱신등을 직접 할 수 있으며, 프로퍼티 정의 메서드를 통해 프로퍼티 어트리뷰트를 재정의할 수도 있다
    • 객체 변경 방지 메서드
      구분 메서드 프로퍼티 추가 프로퍼티 삭제 프로퍼티 값 읽기 프로퍼티 값 쓰기 프로퍼티 어트리뷰트 재정의
      객체 확장 금지 Object.preventExtensions X O O O O
      객체 밀봉 Object.seal X X O O X
      객체 동결 Object.freeza X X O X X
    • 객체 확장 금지
      • Object.preventExtensions
      • 확장이 금지된 객체는 프로퍼티 추가가 금지된다
      • Object.isExtensible 메서드로 확장이 가능한 객체인지 확인할 수 있다
    • 객체 밀봉
      • Object.seal
      • 프로퍼티 추가 및 삭제와 프로퍼티 어트리뷰트 재정의 금지를 의미
      • 밀봉된 객체는 읽기와 쓰기만 가능하다
      • Object.isSealed 메서드로 확인 가능하다
    • 객체 동결
      • Object.freeze
      • 읽기만 가능하다
      • Object.isFrozen 메서드로 확인 가능하다
    • 불변 객체 만들기
      • 지금까지 살펴본 변경 방지 메서드들은 얕은 변경 방지(shallow only)로 직속 프로퍼티만 변경이 방지되고 중첩 객체까지는 영향을 주지 못한다
      • 객체의 중첩 객체까지 동결하여 변경이 불가능한 읽기 전용의 불변 객체를 구현하려면 객체를 값으로 갖는 모든 프로퍼티에 대해 재귀적으로 Object.freeze 메서드를 호출해야한다
// 16-1
function deepFreeze(target) {

    if (target && typeof target === 'object' && !Object.isFrozen(target)) {
    	Object.freeze(target);
        Object.keys(target).forEach(key => deepFreeze(target[key]));
    }
    return target;
}

const person = {
    name: 'Lee',
    address: { city: 'Seoul' }
};

deepFreeze(person);

console.log(Object.isFrozen(person)); // true
console.log(Object.isFrozen(person.address)); // true

person.address.city = 'Busan';
console.log(person); // { name: "Lee", address: {city: "seoul"}}

 

 

17장. 생성자 함수에 의한 객체 생성

  • 객체 리터럴에 의한 객체 생성 방식은 가장 일반적이고 간단한 객체 생성 방식이다
  • new 연산자와 함께 Object 생성자 함수를 호출하면 빈 객체를 생성하여 반환한다 ( 프로퍼티, 메서드등을 추가로 넣어 객체를 완성 )
  • Object 생성자 함수 이외에도 String, Number, Boolean, Function, Array, Date, Promise 등의 빌트인 생성자 함수를 지원
  • 객체 리터럴에 의한 객체 생성 방식의 문제점
    • 객체 리터럴에 의한 객체 생성 방식은 직관적이고 간편하다
    • 하지만 매번 비슷하거나 동일한 프로퍼티를 갖는 객체를 여러 개 생성해야 하는 경우 같은 프로퍼티를 기술해야한다
    • 즉 불필요한 코딩 양이 늘어난다
      // 17-1
      const circle1 = {
          radius: 5,
          getDiameter() {
              return 2 * this.radius;
          }
      };
      
      console.log(circle1.getDiameter()); // 10
      
      const circle2 = {
          radius: 10,
          getDiameter() {
              return 2 * this.radius;
          }
      }
      console.log(circle2.getDiameter()); // 20​
  • 생성자 함수에 의한 객체 생성 방식의 장점
    • 템플릿(클래스)처럼 생성자 함수를 사용하여 프로퍼티 구조가 동일한 객체 여러 개를 간편하게 생성할 수 있다
      // 17-2
      function Circle(radius) {
          this.radius = radius;
          this.getDiameter = function () {
              return 2 * this.radius;
          };
      }
      
      const circle1 = new Circle(5);
      const circle2 = new Circle(10);
      
      console.log(circle1.getDiameter()); // 10
      console.log(circle2.getDiameter()); // 20
       
  • 생성자 함수의 인스턴스 생성 과정
    • 자바 스크립트 엔진은 생성자 함수(new 키워드)를 호출하는 순간 암묵적으로 빈 객체를 생성하고 반환한다
    • 생성 과정 
      • new 키워드를 통해 생성자 함수 호출
      • 인스턴스 생성과 this 바인딩( 바인딩이란 식별자와 값을 연결하는 과정을 의미 )
      • 인스턴스 초기화 ( 개발자가 직접 기술하는 내용 )
      • 인스턴스 반환 ( 위 처리가 모두 끝나면 완성된 인스턴스가 바인딩된 this를 반환 )
  • 내부 메서드 [[Call]] 과 [[Construct]]
    • 함수는 객체이므로 일반 객체와 동일하게 동작할 수 있다
    • 일반 객체는 호출이 불가능하지만 함수 객체는 호출이 가능하다
      • 일반 객체가 가지고 있는 내부 슬롯과 내부 메서드를 가진다
      • 함수로서 동작하기 위해 함수 객체만을 위한 [[Environment]], [[FormalParameters]]
      • 내부 슬롯과 [[Call]], [[Construct]] 같은 내부 메서드를 추가로 가지고 있다
        // 17-3
        function foo() {}
        
        // 일반적인 함수로서 호출: [[Call]]이 호출된다
        foo();
        
        // 생성자 함수로서 호출: [[Construct]]가 호출된다
        new foo();​
  • constructor와 non-constructor의 구분
    • constructor: 함수 선언문, 함수 표현식, 클래스(클래스도 함수다)
    • non-constructor: 메서드(ES6 메서드 축약 표현), 화살표 함수
      // 17-3
      function foo() {}
      const bar = function () {};
      
      const baz = {
          x: function() {}
      };
      
      new foo(); // -> foo {}
      new bar(); // -> bar {}
      new baz.x(); // -> x {}
      
      const arrow = () => {};
      
      new arrow(); // TypeError: arrow is not a constructor
      
      const obj = {
          x() {}
      };
      
      new obj.x(); // TypeError: obj.x is not a constructor​
    • 함수가 어디에 할당되어 있는지에 따라 메서드인지를 판단하는 것이 아니라, 함수 정의 방식에 따라 constructor와 non-constructor를 구분한다
    • 즉 함수 선언문과 함수표현식으로 정의된 함수만이 constructor이다
  • new 연산자
    • new 연산자와 함께 함수를 호출하면 해당 함수는 생성자 함수로 동작한다
    • 함수 객체의 내부 메서드 [[Call]]이 호출되는 것이 아니라, [[Construct]]가 호출된다
    • 단, new 연산자와 함께 호출되는 함수는 constructor 이어야한다
    • new.target 
      • 생성자 함수로서 역할을 더 명확히 하기위해 쓴다
      • new 연산자 없이 호출되는 것을 방지하고, 강제로 new를 호출할 수도 있다
        // 17-4
        function Circle(radius) {
            if (!new.target) {
                return new Circle(radius);
            }
            this,radius = radius;
            this.getDiameter = function () {
                return 2 * this.radius;
            };
        }
        
        const circle = Circle(5); // new 키워드 없이도 생성자 함수 호출​
      • new.target은 ES6에서 도입된 최신 문법이라 IE에서는 지원하지 않는다. 
      • 스코프 세이프 생성자 패턴을 이용하면 된다
        // 17-5
        function Circle(radius) {
            if ( !(this instanceof Circle)) {
                return new Circle(radius);
            }
            this,radius = radius;
            this.getDiameter = function () {
                return 2 * this.radius;
            };
        }
        
        const circle = Circle(5); // new 키워드 없이도 생성자 함수 호출​​

 

18장. 함수와 일급 객체

  • 일급 객체
    • 조건
      • 무명의 리터럴로 생성할 수 있다. 즉 런타임에 생성이 가능하다
      • 변수나 자료구조(객체,배열 등)에 저장할 수 있다
      • 함수의 매개변수에 전달할 수 있다
      • 함수의 반환값으로 사용할 수 있다
    • 가장 큰 특징은 일반 객체와 같이 함수의 매개변수에 전달할 수 있으며, 함수의 반환값으로 사용할 수도 있다는 것
    • 함수형 프로그래밍을 가능케하는 초석이 된다
  • 함수 객체의 프로퍼티
    • arguments 프로퍼티
      • 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한 유사 배열 객체
      • 함수 내부에서 지역 변수처럼 사용되며, 외부에서는 참조 불가능
      • 자바 스크립트는 함수의 매개변수와 인수의 갯수가 일치하는지 확인하지 않는다. ( 함수 호출시 매개변수 개수 만큼 인수를 전달하지 않아도 에러가 발생하지 않음 )
      • arguments 객체는 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 용이하다
    • caller 프로퍼티
      • 함수 자신을 호출한 함수를 가르킴
    • length 프로퍼티
      • 함수를 정의할 때 선언한 매개변수의 개수를 가르킨다
    • name 프로퍼티
      • 함수 이름을 나타냄
    • __proto__ 접근자 프로퍼티
      • 간접적으로 프로토타입 객체에 접근할 수 있게 해준다
    • prototype 프로퍼티
      • 생성자 함수로 호출할 수 있는 함수 객체, 즉 constructor만이 소유한 프로퍼티이다
      • 생성자 함수가 생성할 인스턴스의 프로토타입 객체를 가르킨다

 

728x90
반응형