[전단 면접] 역할 영역 과 폐쇄

1. 제목
변수 향상 에 대한 이 해 를 말씀 해 주세요.
this 의 몇 가지 다른 사용 장면 을 설명 합 니 다.
a 탭 10 개 를 만 들 고 클릭 할 때 해당 하 는 번 호 를 표시 합 니 다.
어떻게 작용 역 을 이해 합 니까
실제 개발 에서 폐쇄 적 인 응용
callapply bind 수 동 구현
2. 지식 포인트
2.1 상하 문 실행
범위: script 또는 함수
전역: 변수 정의, 함수 성명 script
함수: 변수 정의, 함수 성명, this, arguments (실행 전)
함수 성명 과 함수 표현 식 의 차이 점:
a(); //                  。
var a = function(){}

b(); //          
function b(){}

변 수 를 정의 할 때 그의 변 수 를 기본적으로 향상 시 킵 니 다. (그의 실행 컨 텍스트 에 만 한 정 됩 니 다. 예 를 들 어 script 과 함수 중)
console.log(a);
var a = 0;

사실은
var a;
console.log(a);
a = 0;

2.2 this
this 는 실행 할 때 만 확인 할 수 있 고 정의 할 때 확인 할 수 없습니다.
        var a = {
            name:'a',
            fn:function(){
                console.log(this.name);
            }
        }

        a.fn();  // a
        a.fn.apply({name:'b'});  // b  a.fn.call({name:'b'});
        var fn1 = a.fn();
        fn1();  // undefined

this 의 사용 장면
구조 함수 중 (구조의 대상 을 가리 키 는)
    function Fun(name){
        this.name = name;
    }
    var f = new Fun('a');
    console.log(f.name);

대상 속성 중 (대상 지향)
일반 함수 중 (window 지향)
call apply bind
함수 의 this 지향 을 바 꾸 는 데 사 용 됩 니 다. 용법 이 약간 다 릅 니 다.
call: 뒤의 매개 변 수 는 호출 함수 의 매개 변수 목록 입 니 다.
function greet(name) {
  console.log(this.animal,name);
}

var obj = {
  animal: 'cats'
};

greet.call(obj,'  ');

apply: 두 번 째 매개 변 수 는 호출 함수 의 매개 변수 배열 입 니 다.
function greet(name) {
  console.log(this.animal,name);
}

var obj = {
  animal: 'cats'
};

greet.apply(obj,['  ']);

bid: 바 인 딩 함수 가 호출 될 때 bid 가 들 어 오 는 매개 변 수 는 목표 함수 의 매개 변수 목록 의 시작 위치 에 삽입 되 고 바 인 딩 함수 에 전 달 된 매개 변 수 는 그 뒤 를 따 를 것 입 니 다.
var fun = function (name1,name2){
    console.log(this);
    console.log(name);
}.bind({a:1},"name1");
    fun("name2");

arguments 의 this:
var length = 10;
function fn(){
    alert(this.length)
}
var obj = {
    length: 5,
    method: function(fn) {
        arguments[0]()
    }
}

obj. method (fn) / / 출력 1 여 기 는 5 를 출력 하지 않 았 고 10 을 출력 하지 않 았 으 며 오히려 1 을 출력 했 습 니 다. 재 미 있 습 니 다.여기 arguments 는 javascript 의 내 장 된 대상 (mdn: arguments - JavaScript 참조) 으로 클래스 배열 (배열 처럼 길 지만 배열 방법 이 부족 합 니 다. slice. call 로 변환 할 수 있 고 위의 링크 를 구체 적 으로 참조 할 수 있 습 니 다) 입 니 다. 함수 의 매개 변 수 를 저장 합 니 다.즉, 여기 서 arguments [0] 는 당신 method 함수 의 첫 번 째 매개 변 수 를 말 합 니 다: fn, 그래서 arguments [0] () 의 뜻 은 fn () 입 니 다.
그런데 왜 여기에 5 를 출력 하지 않 았 는 지 의문 이다.내 method 에 this 를 사용 하 는데 obj 를 가리 키 지 말 아야 합 니까? 적어도 10 을 출력 할 수 있 습 니 다. 이 1 은 어떻게 된 겁 니까?
실제로 이 1 은 arguments. length, 즉 이 함수 매개 변수의 개수 입 니 다.왜 여기 this 가 arguments 를 가리 키 지?자바 script 에서 배열 은 숫자 로 속성 명 을 만 드 는 방법 에 불과 하기 때 문 입 니 다. 즉, arguments [0] () 의 뜻 은 arguments. 0 () 의 뜻 과 차이 가 많 지 않 기 때 문 입 니 다.
arguments = {
    0: fn, //    functon() {alert(this.length)} 
    1:      , //   
    2:      , //  
    ..., 
    length: 1 //      
}

그래서 여기 alert 가 나 온 결 과 는 1 입 니 다.
5 를 출력 하려 면 어떻게 써 야 하나 요?직접 method: fn 이면 됩 니 다.
2.3 역할 영역
블록 급 역할 영역 없 음
        if(true){
            var name = "test"
        }
        console.log(name);

블록 에 변 수 를 설명 하지 마 십시오.
함수 급 역할 영역 만
2.4 역할 영역 체인
자유 변수 현재 역할 영역 에 정의 되 지 않 은 변 수 는 자유 변수 입 니 다.
자유 변 수 는 아버지 급 역할 영역 에서 찾 습 니 다.실행 이 아 닌 부모 역할 영역 을 정의 합 니 다.
        var a = 100;
        function f1(){
            var b = 200;
            function f2(){
                var c = 300;
                console.log(a); //    
                console.log(b); //    
                console.log(c);
            }
            f2();
        };
        f1();

2.5 폐쇄
한 함수 에 다른 함 수 를 끼 워 넣 고 이 함 수 를 return 한 다음 에 이 return 에서 나 온 함 수 를 변수 에 저장 하면 닫 힌 패 키 지 를 만 듭 니 다.
닫 힌 두 개의 사용 장면
1. 함 수 를 반환 값 으로 한다
        function fun(){
            var a = 0;
            return function(){
                console.log(a); //    ,           
            }
        }

        var f1 = fun();
        a = 1000;
        f1();

2. 함 수 를 매개 변수 로 한다
        function fun(){
            var a = 0;
            return function(){
                console.log(a); //    ,           
            }
        }

        function fun2(f2){
            a = 10000
            f2();
        }

        var f1 = fun();

        fun2(f1);

구체 적 인 설명 은 고급. - 폐쇄 적 인 설명.
폐쇄 적 인 두 가지 역할:
다른 함수 내부 변 수 를 읽 을 수 있 는 함수
함수 내부 변 수 를 메모리 에 계속 저장 할 수 있 습 니 다.
실제 응용 필드 1:
패 킷 을 닫 으 면 전체 에 노출 되 기 를 원 하지 않 는 변 수 를 '개인 변수' 로 밀봉 할 수 있 습 니 다.
만약 곱셈 을 계산 하 는 함수 가 있다 면, mult 함 수 는 number 형식의 인 자 를 받 고 곱셈 결 과 를 되 돌려 줍 니 다.함수 성능 을 향상 시 키 기 위해 서 우 리 는 캐 시 체 제 를 추가 하여 이전에 계 산 된 결 과 를 캐 시 합 니 다. 다음 에 같은 매개 변 수 를 만나면 결 과 를 직접 되 돌려 줄 수 있 고 연산 에 참여 하지 않 아 도 됩 니 다.여기에 캐 시 결 과 를 저장 하 는 변 수 는 외부 에 노출 되 지 않 아 도 되 고 함수 실행 이 끝 난 후에 도 저장 되 어야 하기 때문에 패 키 지 를 닫 을 수 있 습 니 다.
상위 코드:
function calculate(param){
    var cache = {};
    return function(){
        if(!cache.parame){
            return cache.param;
        }else{
            //    ....
            //cache.param = result
            //       
        }
    }
}

실제 응용 장면 2
국부 변수의 수명 을 연장 하 다
img 대상 은 데이터 보고 에 자주 사 용 됩 니 다. 다음 과 같 습 니 다.
var report = function( src ){
    var img = new Image();
    img.src = src;
};
report( 'http://xxx.com/getUserInfo' );

그러나 배경 기록 을 조회 한 결과 일부 저 버 전 브 라 우 저의 실현 에 bug 가 존재 하기 때문에 이 브 라 우 저 에서 report 함 수 를 사용 하여 데 이 터 를 보고 하면 30% 정도 의 데 이 터 를 잃 어 버 린 다 는 것 을 알 수 있 습 니 다. 즉, report 함 수 는 매번 HTTP 요청 을 성공 적 으로 하 는 것 이 아 닙 니 다.
데 이 터 를 잃 어 버 린 이 유 는 img 이 report 함수 의 부분 변수 이기 때 문 입 니 다. report 함수 호출 이 끝 난 후에 img 부분 변 수 는 바로 소각 되 었 습 니 다. 이때 HTTP 요청 을 하지 못 했 을 수도 있 습 니 다. 그래서 이번 요청 은 잃 어 버 릴 것 입 니 다.
지금 우 리 는 img 변 수 를 폐쇄 로 닫 으 면 잃 어 버 린 문 제 를 해결 할 수 있 습 니 다.
var report = (function(){
    var imgs = [];
    return function( src ){
        var img = new Image();
        imgs.push( img );
        img.src = src;
    }
})();

폐쇄 단점: 자원 낭비!
3. 문제 풀이
3.1 변수 향상 에 대한 이 해 를 말 합 니 다.
변수 정의 와 함수 설명
함수 성명 과 함수 표현 식 의 차이 에 주의 하 십시오.
변 수 를 정의 할 때 그의 변 수 를 기본적으로 향상 시 킵 니 다. (그의 실행 컨 텍스트 에 만 한 정 됩 니 다. 예 를 들 어 script 과 함수 중)
console.log(a);
var a = 0;

사실은
var a;
console.log(a);
a = 0;

3.2 this 의 몇 가지 다른 사용 장면 설명
  • 구조 함수 중 (구 조 를 가리 키 는 대상)
  • 대상 속성 중 (해당 대상 을 가리 키 는)
  • 일반 함수 중 (window 지향)
  • call apply bind

  • 3.3 a 탭 10 개 를 만 들 고 클릭 할 때 해당 하 는 번 호 를 표시 합 니 다.
    실현 방법 1: let 성명 i
            var body = document.body;
            console.log(body);
            for (let i = 0; i < 10; i++) {
                let obj = document.createElement('i');
                obj.innerHTML = i + '
    '; body.appendChild(obj); obj.addEventListener('click',function(){ alert(i); }) }

    실현 방법 2 포장 역할 영역
        var body = document.body;
        console.log(body);
        for (var i = 0; i < 10; i++) {
            (function (i) {
                var obj = document.createElement('i');
                obj.innerHTML = i + '
    '; body.appendChild(obj); obj.addEventListener('click', function () { alert(i); }) })(i) }

    3.4 실제 개발 에서 폐쇄 적 인 응용
    다른 함수 내부 변 수 를 읽 을 수 있 는 함수
    함수 내부 변 수 를 메모리 에 계속 저장 할 수 있 습 니 다.
    패키지 변수, 권한 수렴
    응용
    var report = (function(){
        var imgs = [];
        return function( src ){
            var img = new Image();
            imgs.push( img );
            img.src = src;
        }
    })();

    변수 소각 방지 에 사용 합 니 다.
    응용
        function isFirstLoad() {
            var arr = [];
            return function (str) {
                if (arr.indexOf(str) >= 0) {
                    console.log(false);
                } else {
                    arr.push(str);
                    console.log(true);
                }
            }
        }
    
        var fun = isFirstLoad();
        fun(10);
        fun(10);

    arr 를 함수 내부 에 봉 하여 임의로 수정 하 는 것 을 금지 하고 변수 가 소각 되 는 것 을 방지 합 니 다.
    3.5 수 동 으로 callapply bind 실현
  • context 는 선택 가능 한 매개 변수 입 니 다. 전송 하지 않 으 면 기본 컨 텍스트 는 window 입 니 다.
  • context 에서 Symbol 속성 을 만 들 고 호출 후 삭제 하 며 context
  • 에 영향 을 주지 않 습 니 다.
        Function.prototype.myCall = function (context) {
          if (typeof this !== 'function') {
            return undefined; //      Function.prototype.myCall()     
          }
          context = context || window;
          const fn = Symbol();
          context[fn] = this;
          const args = [...arguments].slice(1);
          const result = context[fn](...args);
          delete context[fn];
          return result;
        }

    apply 는 유사 한 call 을 실현 하고 매개 변 수 는 배열 입 니 다.
        Function.prototype.myApply = function (context) {
          if (typeof this !== 'function') {
            return undefined; //      Function.prototype.myCall()     
          }
          context = context || window;
          const fn = Symbol();
          context[fn] = this;
          let result;
          if (arguments[1] instanceof Array) {
            result = context[fn](...arguments[1]);
          } else {
            result = context[fn]();
          }
          delete context[fn];
          return result;
        }

    1. 구조 함수 호출 여 부 를 판단 합 니 다.
    2. 매개 변 수 는 목표 함수 의 시작 위치 에 삽입 해 야 합 니 다.
        Function.prototype.myBind = function (context) {
          if (typeof this !== 'function') {
            throw new TypeError('Error')
          }
          const _this = this
          const args = [...arguments].slice(1)
          return function F() {
            //           
            if (this instanceof F) {
              return new _this(...args, ...arguments)
            }
            return _this.apply(context, args.concat(...arguments))
          }
        }

    좋은 웹페이지 즐겨찾기