ES6 노트 깊이 이해 (3) 함수

주요 지식 점 은 함수 매개 변수 기본 값, 나머지 매개 변수, 확장 연산 자, new. target 속성, 블록 급 함수, 화살표 함수 와 꼬리 호출 최적화 입 니 다.
《 ES6 깊이 이해 》 노트 목록.
함수 의 기본 매개 변수
ES5 에서 우 리 는 함수 에 인 자 를 전달 한 다음 에 함수 내 에 기본 값 을 설정 합 니 다. 예 를 들 어 아래 와 같은 방식 입 니 다.
function a(num, callback) {
  num = num || 6
  callback = callback || function (data) {console.log('ES5: ', data)}
  callback(num * num)
}
a() //ES5: 36,        

//        callback
a(10, function(data) {
  console.log(data * 10) // 1000,        
})

단점: 이곳 의 num 의 유효 치 는 실제 적 으로 0 일 수 있 지만 0 이 가짜 이기 때문에 num 의 값 은 이런 상황 에서 6 으로 대 체 될 수 있 습 니 다.type: of 로 매개 변수의 종 류 를 검사 할 수 있 습 니 다.
function a(num, callback) {
  num = (typeof num!== "undefined") ? num: 6;
  callback = (typeof callback !== "undefined") ? callback : function (data) {console.log('ES5: ', data)};
  callback(num * num)
}

이런 방법 은 더욱 안전 하지만 기본 적 인 수 요 를 실현 하기 위해 너무 많은 코드 를 썼 다.그것 은 공공 모델 을 대표 하 는데 유행 하 는 JS 라 이브 러 리 에는 모두 비슷 한 모델 이 가득 하 다.
ES6 의 인자 기본 값
function a(num = 6, callback = function (data) {console.log('ES6: ', data)}) {
  callback(num * num)
}

a() //ES6: 36,         

a(10, function(data) {
  console.log(data * 10) // 1000,       
})

ES6 의 기본 값 표기 법 을 사용 하면 함수 체 내부 의 코드 를 더욱 간결 하고 우아 하 게 할 수 있다
매개 변수 기본 값 은 arguments 대상 에 어떻게 영향 을 줍 니까?
  • ES5 의 비 엄격 모드 에서
  • function mixArgs(first, second) {
        console.log(first === arguments[0]);
        console.log(second === arguments[1]);
        first = "c";
        second = "d";
        console.log(first === arguments[0]);
        console.log(second === arguments[1]);
    }
    mixArgs("a", "b");
    //  
    true
    true
    true
    true
  • ES5 의 엄격 한 모델 에서
  • function mixArgs(first, second) {
        "use strict";
        console.log(first === arguments[0]);
        console.log(second === arguments[1]);
        first = "c";
        second = "d"
        console.log(first === arguments[0]);
        console.log(second === arguments[1]);
    }
    mixArgs("a", "b");
    //  
    true
    true
    false
    false
  • ES6

  • arguments 대상 의 표현 은 항상 ES5 의 엄격 한 모델 과 일치 합 니 다. 이때 함수 가 엄격 한 모드 에서 명확 하 게 실행 되 든 안 되 든 간 에.
    //      
    function mixArgs(first, second = "b") {
        console.log(arguments.length);
        console.log(first === arguments[0]);
        console.log(second === arguments[1]);
        first = "c";
        second = "d"
        console.log(first === arguments[0]);
        console.log(second === arguments[1]);
    }
    mixArgs("a");
    //  
    1
    true
    false
    false
    false

    이때 arguments. length = 1 은 mixArgs () 에 하나의 인자 만 전 달 했 기 때 문 입 니 다.이것 은 arguments [1] 의 값 이 undefined 이 고 하나의 매개 변 수 를 함수 에 전달 할 때의 기대 에 부합 한 다 는 것 을 의미한다.이 는 first 와 arguments [0] 가 같다 는 뜻 이다.first 와 second 의 값 을 바 꾸 는 것 은 arguments 대상 에 영향 을 주지 않 습 니 다. 엄격 한 모드 에서 도 arguments 대상 에 따라 초기 호출 상 태 를 반영 할 수 있 습 니 다.
    기본 매개 변수 표현 식
    매개 변 수 는 기본 값 을 문자열, 숫자, 배열 또는 대상 으로 설정 할 수 있 을 뿐만 아니 라 함수 일 수도 있 습 니 다.
    function add() {
      return 10
    }
    function a(num = add()){
      console.log(num)
    }
    a() // 10

    기본 매개 변수의 임시 사각 지대
    제1장 에서 우 리 는 let 와 const 의 어떤 변수의 임시 사구 (TDZ) 를 언급 했다. 기본 매개 변 수 는 매개 변수 인 이상 임시 사구 도 있다. 함수 의 작용 역 은 독립 적 이 고 a 함 수 는 b 함수 의 작용 역 파 라미 터 를 공유 할 수 없다.
    //              ,    a ,b     ,        b        。
    function add(a = b, b){
      console.log(a + b)
    }
    add(undefined, 2) // b is not define

    이름 없 는 매개 변수 처리
    위 에서 말 한 매개 변 수 는 모두 이름 을 가 진 매개 변수 이 고 이름 이 없 는 매개 변 수 는 함수 전달 에 자주 사용 된다.들 어 오 는 매개 변수 가 대상 이 고 구체 적 인 매개 변수 이름 이 아니면 이름 없 는 매개 변수 입 니 다.
    function add(object){
      console.log(object.a + object.b)
    }
    let obj = {
      a: 1,
      b: 2
    }
    add(obj) // 3

    부정 확 한 매개 변수
    ... (연산 자 를 펼 치 는) 매개 변 수 를 사용 하 는 것 은 부정 확 한 매개 변수 입 니 다. 배열 을 표시 합 니 다.
    function add(...arr){
      console.log(a + b)
    }
    let a = 1,b = 2
    add(a, b) // 3

    부정 확 한 매개 변수의 사용 제한:
  • 함수 에 남 은 매개 변수 만 있 을 수 있 고 마지막 에 두 어야 합 니 다
  • //     1
    function add(...arr, c){
      console.log(a + b)
    }
    let a = 1,b = 2,c = 3
    add(a, b, c)
  • 남 은 매개 변 수 는 대상 글자 의 setter 속성 에서 사용 할 수 없습니다
  • //     2
    let obj = {
      set add(...arr) {
      
      }
    }

    나머지 매개 변 수 는 arguments 대상 arguments 대상 이 함수 가 호출 될 때 들 어 오 는 매개 변 수 를 어떻게 영향 을 미 치 는 지, 나머지 매개 변수 와 협동 하여 작업 할 수 있 습 니 다. 다음 프로그램 이 보 여 준 것 과 같 습 니 다.
    function checkArgs(...args) {
        console.log(args.length);
        console.log(arguments.length);
        console.log(args[0], arguments[0]);
        console.log(args[1], arguments[1]);
    }
    checkArgs("a", "b");
    //  
    2
    2
    a a
    b b

    arguments 대상 은 들 어 오 는 함수 의 인 자 를 정확하게 반영 하고 나머지 매개 변수의 사용 을 무시 합 니 다.
    ES6 의 구조 함수 Function 은 기본 매개 변수 와 부정 확 한 매개 변 수 를 지원 합 니 다.
    확장 연산 자
    Math. max () 방법 을 고려 해 보 세 요. 임의의 매개 변 수 를 받 아들 이 고 최대 값 을 되 돌려 줍 니 다.
    //       
    let value1 = 25,
    value2 = 50;
    console.log(Math.max(value1, value2)); // 50
    //          (es5)
    let values = [25, 50, 75, 100]
    console.log(Math.max.apply(Math, values)); 
    //es6
    let values = [25, 50, 75, 100]
    //     console.log(Math.max(25, 50, 75, 100));
    console.log(Math.max(...values)); // 100

    확장 연산 자 전달 매개 변수
    //       Math.max()          0 (          ),       0     ,               
    let values = [-25, -50, -75, -100]
    console.log(Math.max(...values, 0)); // 0

    ES6 이름 속성
    ES6 는 모든 함수 에 name 속성 을 추가 합 니 다.
    적당 한 이름 선택
    //    
    function doSomething() {
    // ...
    }
    //       
    var doAnotherThing = function() {
    // ...
    };
    console.log(doSomething.name); // "doSomething"
    console.log(doAnotherThing.name); // "doAnotherThing"

    명칭 속성의 특수 한 상황
    //doSomethingElse      doSomething 
    var doSomething = function doSomethingElse() {
    // ...
    };
    //person.firstName       getter   ,         "get firstName"
    var person = {
        get firstName() {
            return "Nicholas"
        },
        sayName: function() {
            console.log(this.name);
        }
    }
    console.log(doSomething.name); // "doSomethingElse"
    console.log(person.sayName.name); // "sayName"
    var descriptor = Object.getOwnPropertyDescriptor(person, "firstName");
    console.log(descriptor.get.name); // "get firstName"

    다른 두 가지 특수 한 상황
  • bind () 를 사용 하여 만 든 함 수 는 이름 속성 값 전에 "bound" 접두사 가 있 습 니 다
  • Function 구조 기 를 사용 하여 만 든 함수 입 니 다. 이름 속성 은 "anonymous" 접두사
  • 가 있 습 니 다.
    var doSomething = function() {
    // ...
    };
    console.log(doSomething.bind().name); // "bound doSomething"
    console.log((new Function()).name); // "anonymous"

    함수 의 이중 용 도 를 명 확 히 하 다.
    JS 는 함수 에 두 가지 다른 내부 방법 을 제공 했다. [Call] 과 [Construct].함수 가 new 를 사용 하지 않 고 호출 되 었 을 때 [call] 방법 이 실 행 됩 니 다. 코드 에 표 시 된 함수 체 를 실행 합 니 다.함수 가 new 를 사용 하여 호출 할 때 [Construct] 방법 은 실 행 됩 니 다. 새로운 목표 라 고 불 리 는 새로운 대상 을 만 들 고 이 새로운 목 표를 this 로 함수 체 를 실행 합 니 다.[Construct] 방법 을 가 진 함 수 를 구조 기 라 고 합 니 다.
    ES5 에서 함수 가 어떻게 호출 되 는 지 판단 합 니 다.
    instanceof 사용
    function Person(name) {
        if (this instanceof Person) {
            this.name = name; //    new
        } else {
            throw new Error("You must use new with Person.")
        }
    }
    var person = new Person("Nicholas");
    var notAPerson = Person("Nicholas"); //     

    그러나 이런 상황 에서 믿 을 수 없다.
    function Person(name) {
        if (this instanceof Person) {
            this.name = name; //    new
        } else {
            throw new Error("You must use new with Person.")
        }
    }
    var person = new Person("Nicholas");
    var notAPerson = Person.call(person, "Michael"); //    !

    new. target 메타 속성
    new. target 이 정의 되 었 는 지 확인 함으로써 이 새로운 메타 속성 은 함수 가 new 를 사용 하여 호출 되 었 는 지 여 부 를 안전하게 판단 할 수 있 습 니 다.
    function Person(name) {
        if (typeof new.target !== "undefined") {
            this.name = name; //    new
        } else {
            throw new Error("You must use new with Person.")
        }
    }
    var person = new Person("Nicholas");
    var notAPerson = Person.call(person, "Michael"); //   !

    new. target 이 특정 구조 기 를 사용 하여 호출 되 었 는 지 확인 할 수 있 습 니 다. 예 를 들 어 다음 코드:
    function Person(name) {
        if (new.target === Person) {
            this.name = name; //    new
        } else {
            throw new Error("You must use new with Person.")
        }
    }
    function AnotherPerson(name) {
        Person.call(this, name);
    }
    var person = new Person("Nicholas");
    var anotherPerson = new AnotherPerson("Nicholas"); //   !

    경고: 함수 외 에 new. target 을 사용 하면 문법 오류 가 발생 할 수 있 습 니 다.
    블록 급 함수
    엄격 한 패턴 의 블록 급 함수
    "use strict";
    if (true) {
        //   ES5        , ES6    
        function doSomething() {
        // ...
        }
    }

    블록 급 함 수 는 정 의 된 코드 블록의 맨 위로 올 라 갑 니 다:
    "use strict";
    if (true) {
        console.log(typeof doSomething); // "function"
        function doSomething() {
        // ...
    }
    doSomething();
    }
    console.log(typeof doSomething); // "undefined"

    let 함수 식:
    "use strict";
    if (true) {
        console.log(typeof doSomething); //     
        let doSomething = function () {
            // ...
        }
    doSomething();
    }
    console.log(typeof doSomething);

    엄격 하지 않 은 모드 의 블록 급 함수
    ES6 는 엄격 하지 않 은 모드 에서 도 블록 급 함 수 를 사용 할 수 있 지만 행동 은 미세 하 게 다르다.블록 급 함수 의 역할 영역 은 코드 블록 의 상단 이 아 닌 함수 나 전역 환경의 상단 으로 향 상 됩 니 다.
    // ES6 behavior
    if (true) {
        console.log(typeof doSomething); // "function"
        function doSomething() {
        // ...
        }
    doSomething();
    }
    console.log(typeof doSomething); // "function"

    화살표 함수
    화살표 함수 와 전통 적 인 JS 함수 의 차이 점:
  • this, super, arguments 도 없고 new. target 바 인 딩 도 없습니다
  • new 호출 을 사용 할 수 없습니다
  • 원형 이 없습니다. 화살표 함수 에 new 를 사용 할 수 없 으 니 원형 도 필요 없습니다. 즉, prototype 속성 이 없습니다.
  • this: this 의 값 은 함수 내부 에서 수정 할 수 없습니다. 함수 의 전체 생명 주기 내 에 그 값 은 변 하지 않 습 니 다
  • 인수 대상 없 음
  • 중복 되 지 않 는 서명 인자
  • 화살표 함수 문법
  • 매개 변수 없 음
  • var getName = () => "Nicholas";
    //      :
    var getName = function() {
        return "Nicholas";
    };
  • 단일 매개 변수
  • var reflect = value => value;
    //      :
    var reflect = function(value) {
        return value;
    };
  • 여러 매개 변수
  • var sum = (num1, num2) => num1 + num2;
    //      :
    var sum = function(num1, num2) {
        return num1 + num2;
    };
  • 여러 함수 문체
  • var sum = (num1, num2) => {
        return num1 + num2;
    };
    //      :
    var sum = function(num1, num2) {
        return num1 + num2;
    };
    
    //            ,                  。
    var getTempItem = id => ({ id: id, name: "Temp" });
    //      :
    var getTempItem = function(id) {
        return {
            id: id,
            name: "Temp"
        };
    };

    즉시 호출 함수 표현 식 만 들 기
  • 전통 함수
  • let person = function(name) {
        return {
            getName: function() {
                return name;
            }
        };
    }("Nicholas");
    console.log(person.getName()); // "Nicholas"
  • 화살표 함수
  • let person = ((name) => {
        return {
        getName: function() {
            return name;
        }
    };
    })("Nicholas");
    console.log(person.getName()); // "Nicholas"

    번역: 전통 함 수 를 사용 할 때 (function () {/
    함수 체 /} ();(function () {/
    함수 체 /} ();
    이 두 가지 방식 은 모두 실행 가능 하 다.
    그러나 화살표 함 수 를 사용 하면 아래 의 쓰기 만 유효 합 니 다: () = > {/
    함수 체 /} ();
    꼬리 호출 최적화
    꼬리 호출 이란 함수 return 때 새로운 함 수 를 호출 하 는 것 을 말 합 니 다. 꼬리 호출 의 실현 으로 인해 메모리 에 저장 해 야 하기 때문에 순환 체 에 함수 의 꼬리 호출 이 존재 하면 메모리 가 가득 차 거나 넘 칠 수 있 습 니 다.
    ES6 에서 엔진 은 마지막 호출 의 최적화 작업 을 도와 줄 것 입 니 다. 당신 은 스스로 최적화 할 필요 가 없 지만 다음 세 가지 요 구 를 만족 시 켜 야 합 니 다.
    1. 함 수 는 폐쇄 가 아 닙 니 다.
    2. 꼬리 호출 은 함수 의 마지막 문장 입 니 다.
    3. 끝 호출 결 과 를 함수 로 되 돌려 줍 니 다.
    상기 요 구 를 만족 시 키 는 함 수 는 다음 과 같다.
    "use strict";   
    function a() {
      return b();
    }

    아래 의 것 은 모두 불만족 한 표기 법 이다.
    //  return   
    "use strict";
    function a() {
      b();
    }
    
    //           
    "use strict";
    function a() {
      return 1 + b();
    }
    
    //                 
    "use strict";
    function a() {
      const s = b();
      return s
    }
    
    //     
    "use strict";
    function a() {
      const num = 1
      function b() {
        return num
      }
      return b
    }
    

    마지막 호출 실제 용도 - 재 귀 함수 최적화
    ES5 시대 에는 재 귀 가 성능 에 영향 을 미 치기 때문에 재 귀 를 추천 하지 않 습 니 다.그러나 꼬리 호출 최적화 이후 재 귀 함수 의 성능 이 향상 되 었 다.
    //       
    "use strict";  
    function a(n, p = 1) {
      if(n <= 1) {
        return 1 * p
      }
      let s = n * p
      return a(n - 1, s)
    }
    //  1 x 2 x 3   
    let sum = a(3)
    console.log(sum) // 6

    좋은 웹페이지 즐겨찾기