>  기사  >  웹 프론트엔드  >  JS 핵심 시리즈: 기능 범위에 대한 간략한 설명

JS 핵심 시리즈: 기능 범위에 대한 간략한 설명

大家讲道理
大家讲道理원래의
2017-01-24 11:34:011021검색

1. 범위

범위는 변수가 선언된 함수 본문과 이 함수 본문이 중첩된 모든 함수 본문에 정의됩니다.

function scope(){
    var foo = "global";
    if(window.getComputedStyle){
        var a = "I'm if";
        console.log("if:"+foo); //if:global
    }
    while(1){
        var b = "I'm while";
        console.log("while:"+foo);//while:global
        break;
    }
    !function (){
        var c = "I'm function";
        console.log("function:"+foo);//function:global
    }();
    console.log(
         foo,//global
         a, // I'm if
         b, // I'm while
         c  // c is not defined
    );
}
scope();

(1) 범위 함수에 정의된 foo 변수는 자체적으로 액세스할 수 있을 뿐만 아니라 if 문, while 문 및 내장된 익명 함수에서도 액세스할 수 있습니다. 따라서 foo의 범위는 범위 함수 본문입니다.

(2) JavaScript에서는 if, while, for 및 기타 코드 블록이 독립적인 범위를 형성할 수 없습니다. 따라서 JavaScript에는 블록 수준 범위가 없고 함수 범위만 있습니다.

하지만 JS에는 특별한 경우가 있습니다.

var를 사용하여 변수를 선언하지 않으면 window에 이 속성이 있으므로 이 변수의 범위는 특정 함수 본문에 속하지 않고 창 개체에 속합니다.

function varscope(){
    foo = "I'm in function";
    console.log(foo);//I'm in function
}
varscope();
console.log(window.foo); //I'm in function

2. 스코프 체인(scope chain)

소위 스코프 체인은 다음과 같습니다. a 함수 본문에는 여러 계층의 함수 본문이 중첩되어 있으며, 동일한 변수가 다른 함수 본문에 정의되어 있습니다. 함수 중 하나가 이 변수에 액세스하면 범위 체인이 형성됩니다.

foo = "window";
function first(){
    var foo = "first";
    function second(){
       var foo = "second";
       console.log(foo);
    }
    function third(){
       console.log(foo);
    }
    second(); //second
    third();  //first
}
first();

일 때 JS 엔진은 두 번째 범위를 연결 목록의 선두에 배치하고 그 다음 첫 번째 범위, 마지막으로 창 객체를 배치하므로 다음과 같은 범위 체인이 형성됩니다.

second->first->window 이때 JS 엔진은 스코프 체인을 따라 변수 foo를 검색하고 찾은 것은 "second"

third가 실행될 때 , third: third->first->window로 구성된 범위 체인이므로 "frist"

특수 사례: with 문

JS의 with 문은 주로 다음에서 사용됩니다. 범위 체인을 확장할 때 문의 개체가 범위의 머리 부분에 추가됩니다. with 문이 끝나면 범위 체인이 정상으로 돌아갑니다.

foo = "window";
function first(){
    var foo = "first";
    function second(){
       var foo = "second";
       console.log(foo);
    }
    function third(obj){
       console.log(foo); //first
       with (obj){
           console.log(foo); //obj
       }
       console.log(foo); //first
    }
    var obj = {foo:'obj'};
    third(obj);
}
first();

third()를 실행하면 obj 객체가 전달되고 obj는 foo 속성을 갖습니다. with 문을 실행할 때 JS 엔진은 obj를 원래 연결 목록의 선두에 배치하여 범위를 형성합니다. 체인은 다음과 같습니다:

obj->third->first->window. 이때 발견된 foo는 obj의 foo이므로 출력은 "obj"이고 before 및 with 이후에는 원래 연결 목록을 따라 검색되는데, 이는 with 문이 끝난 후 범위 체인이 정상으로 돌아왔음을 보여줍니다.

3. 이 키워드

함수에서는 항상 현재 함수의 소유자 개체를 가리킵니다. this는 런타임 시 특정 포인터와 호출 개체만 확인할 수 있습니다.

이 문장은 이것에 대한 모든 것을 요약합니다, 기억하세요, 기억하세요, 기억하세요! (ps: 중요한 것을 세 번 말하세요!)

window.name = "window";
function f(){
    console.log(this.name);
}
f();//window

var obj = {name:'obj'};
f.call(obj); //obj

f()를 실행할 때 f()의 호출자는 window 객체이므로 "window"를 출력한다는 것은

f.call(obj)은 obj 객체에 f()를 배치하는 것을 의미합니다. 이때 f의 this는 obj이므로 출력은 "obj"

입니다. 4. 실제 적용

code1:

var foo = "window";
var obj = {
    foo : "obj",
    getFoo : function(){
        return function(){
            return this.foo;
        };
    }
};
var f = obj.getFoo();
f(); //window

code2:

var foo = "window";
var obj = {
    foo : "obj",
    getFoo : function(){
        var that = this;
        return function(){
            return that.foo;
        };
    }
};
var f = obj.getFoo();
f(); //obj

code1과 code2는 이 내용과 범위에 대한 가장 좋은 요약입니다. 실행 결과에 대한 의문이 있으면 토론하십시오!

코드 분석:

code1:
执行var  f = obj.getFoo()返回的是一个匿名函数,相当于:
var f = function(){
     return this.foo;
}
f() 相当于window.f(), 因此f中的this指向的是window对象,this.foo相当于window.foo, 所以f()返回"window" 

code2:
执行var f = obj.getFoo() 同样返回匿名函数,即:
var f = function(){
     return that.foo;
}
唯一不同的是f中的this变成了that, 要知道that是哪个对象之前,先确定f的作用域链:f->getFoo->window 并在该链条上查找that,此时可以发现that指代的是getFoo中的this, getFoo中的this指向其运行时的调用者,从var f = obj.getFoo() 可知此时this指向的是obj对象,因此that.foo 就相当于obj.foo,所以f()返回"obj"


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.