2014-06-19 9 views
2

이 질문의 제목을 지정하는 방법은 확실하지 않지만 생성자와 함께 공개 모듈 패턴을 사용하고 있으며 혼란스러워하는 행동을 발견했습니다. 이 코드의 실제 목적은 내 질문과 관련이 없으며, 내가 본이 동작을 이해하고 싶습니다. 이제 전화이 함수 정의의 동작을 이해하려고 시도합니다.

var ajaxModule = (function() { 
    //private 
    var data,callBack,type,dataType,url, 
    //public 
    constructor; 

    constructor = function(callBack,data,type,dataType,url) { 
     //Required 
     callBack = callBack || null; 
     data = data || null; 
     //Defaults 
     type = type || 'POST'; 
     dataType = dataType || 'json'; 
     url = url || 'DBConnect.php'; 
    }; 

    //methods 
    function setAjaxQuery() { 
     log('in setAjaxQuery') 
     dir(callBack); 
     dir(data); 
     dir(type); 
     dir(dataType); 
     dir(url); 
    }; 

    constructor.prototype = { 
     constructor: ajaxModule, 
     setAjaxQuery: setAjaxQuery, 
    }; 

    return constructor; 
}()); 

:

var ajax = new ajaxModule('someObject','someData'); 
ajax.setAjaxQuery(); 

지금은) 내가 그 console.dir (모두를위한 정의되지 않은보고 있었다이 일에 명령을 여기

내가 문제를 가지고 코드입니다 setAjaxQuery 함수.

문제는 매개 변수 이름이 로컬 변수와 동일하다는 것입니다. 나는 이런 식으로 문제를 해결했다 :

constructor = function(zcallBack,zdata,ztype,zdataType,zurl) { 
    //Required 
    callBack = zcallBack || null; 
    data = zdata || null; 
    //Defaults 
    type = ztype || 'POST'; 
    dataType = zdataType || 'json'; 
    url = zurl || 'DBConnect.php'; 
} 

나의 질문은 왜 그런가? 이름이 같은 경우 JavaScript가이 문제를 일으키는 이유는 무엇입니까?

+0

'dir'은 아마도'console.dir'로 작성되어야합니다. 그 문제에 대해서'log'와 동일합니다. – Robbert

답변

1

인수를 추가하면 입력 한 이름의 로컬 범위가 예약됩니다. 외부 범위에는 액세스하려는 이름의 버전이 있으므로 해당 이름을 다시 사용할 수 없으면 충돌로 인해 로컬 범위 만 사용됩니다. 두 번째 호출 함수는 외부 범위에만 액세스 할 수 있으므로 내부 범위에 설정된 값을 검색 할 방법이 없습니다.

어휘 범위 지정 이상한 갔지만의이 예를 살펴 보자 수 있습니다

var ajaxModule = (function() { 
    //private 
    var inner = { 
     data: null, 
     callBack: null, 
     type: 'POST', 
     dataType: 'json', 
     url: 'DBConnect.php' 
    }, 
    //public 
    constructor; 

    constructor = function(callBack,data,type,dataType,url) { 
     //Required 
     inner.callBack = callBack || null; 
     inner.data = data || null; 
     //Defaults 
     inner.type = type || 'POST'; 
     inner.dataType = dataType || 'json'; 
     inner.url = url || 'DBConnect.php'; 
    }; 

    //methods 
    function setAjaxQuery() { 
     log('in setAjaxQuery') 
     dir(inner.callBack); 
     dir(inner.data); 
     dir(inner.type); 
     dir(inner.dataType); 
     dir(inner.url); 
    }; 

    constructor.prototype = { 
     constructor: ajaxModule, 
     setAjaxQuery: setAjaxQuery, 
    }; 

    return constructor; 
}()); 

동시에 유지하는이 방법 : 이러한 경우에 대한

function x(){ 
    var a = 5; // scoped to x 
    var b = 10; // scoped to x 
    function c() { 
    var a = 10; // scoped to c, this is equivalent to having an argument named a 
    return a + b; // b is scoped to x 
    } 
    return c; // scoped to x 
} 

내 조언은 문제를 해결하기 위해 파라미터를 사용하는 것 명명 규칙을 사용하고 명시 적으로 (내부)를 통해 범위를 선언하십시오.

+0

나는 이해한다고 생각한다. 그렇다면 역동적으로 범위가 지정된 언어에서 이와 같은 것을 빠져 나갈 수 있습니까? – red888

+0

동적 스코프 란 무엇을 의미하는지 확실하지 않습니다. 블록 범위와 어휘 범위가 있습니다. 내 충고는이 모든 것을 사적인 영역의 객체 인터페이스 뒤에 두는 것이다. – Gabriel

1

생성자 함수는 범위를 만듭니다. 생성자의 매개 변수는 해당 범위의 로컬 변수를 정의합니다. 따라서 "callback"변수에 값을 할당하면 생성자의 범위에있는 변수를 참조하고 부모 범위에있는 변수는 참조하지 않습니다.

setAjaxQuery 메서드는 자체 범위를 정의합니다. 이 범위에서 "콜백"에 액세스 할 때 부모 범위에있는 변수는 그대로 유지되고 정의되지 않은 채로 남아 있습니다.

function(){ 
    var abc = null;//scope outer 

    function A(abc){ 
     abc = "something"; 
     //abc here refers to the variable in the local scope i.e. parameter of function A. 
     //abc variable in outer scope is still null. 
    } 

    function B(){ 
     console.log(abc); 
     //abc here refers to the variable in the outer scope which was never changed. 
    } 
}