[javascript] JS 객체를 정의하는이 방법에는 어떤 목적이 있습니까?

일부 레거시 코드를 유지하고 있는데 객체를 정의하는 데 다음 패턴이 사용되는 것을 발견했습니다.

var MyObject = {};

(function (root) {

    root.myFunction = function (foo) {
        //do something
    };

})(MyObject);

이것에 어떤 목적이 있습니까? 다음을 수행하는 것과 동일합니까?

var MyObject = {

    myFunction : function (foo) {
        //do something
    };

};

나는 전체 코드베이스를 내 취향에 맞게 리팩토링하는 신성한 탐구에 착수하지 않지만 객체를 정의하는 로터리 방식의 이유를 정말로 이해하고 싶습니다.

감사!



답변

모듈 패턴 http://toddmotto.com/mastering-the-module-pattern/ 이라고합니다.

주된 이유는 진정한 개인 메서드와 변수를 만드는 것입니다. 귀하의 경우에는 구현 세부 정보를 숨기지 않기 때문에 의미가 없습니다.

다음은 모듈 패턴을 사용하는 것이 합당한 예입니다.

var MyNameSpace = {};

(function(ns){
    // The value variable is hidden from the outside world
    var value = 0;

    // So is this function
    function adder(num) {
       return num + 1;
    }

    ns.getNext = function () {
       return value = adder(value);
    }
})(MyNameSpace);

var id = MyNameSpace.getNext(); // 1
var otherId = MyNameSpace.getNext(); // 2
var otherId = MyNameSpace.getNext(); // 3

당신은 그냥 직선 객체를 사용하는 경우 반면 addervalue공공 될 것

var MyNameSpace = {
    value: 0,
    adder: function(num) {
       return num + 1;
    },
    getNext: function() {
       return this.value = this.adder(this.value);
    }
}

그리고 당신은 다음과 같은 일을함으로써 그것을 부술 수 있습니다.

MyNameSpace.getNext(); // 1
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 1 again
delete MyNameSpace.adder;
MyNameSpace.getNext(); // error undefined is not a function

하지만 모듈 버전으로

MyNameSpace.getNext(); // 1
 // Is not affecting the internal value, it's creating a new property
MyNameSpace.value = 0;
MyNameSpace.getNext(); // 2, yessss
// Is not deleting anything
delete MyNameSpace.adder;
MyNameSpace.getNext(); // no problemo, outputs 3


답변

목적은 다른 스크립트 가 코드를 실행하는 것을 방지하기 위해 클로저 내에서 함수의 접근성 을 제한 하는 것입니다. 을 주위에 포장하여 폐쇄 하면 다시 정의하는 범위 내 모든 코드 실행을 폐쇄 하고 효과적으로 개인 범위를 생성. 자세한 내용은이 문서를 참조하십시오.

http://lupomontero.com/using-javascript-closures-to-create-private-scopes/

기사에서 :

JavaScript에서 가장 잘 알려진 문제 중 하나는 전역 범위에 대한 의존성입니다. 이는 기본적으로 함수 외부에서 선언하는 모든 변수가 동일한 이름 공간, 즉 불길한 창 개체에 있음을 의미합니다. 웹 페이지의 특성으로 인해 서로 다른 소스의 많은 스크립트가 공통 전역 범위를 공유하는 동일한 페이지에서 실행될 수 있고 실행될 수 있으며 이름 충돌 (동일한 이름의 변수 덮어 쓰기) 및 보안 문제. 문제를 최소화하기 위해 JavaScript의 강력한 클로저를 사용하여 변수가 페이지의 다른 스크립트에 보이지 않는지 확인할 수있는 개인 범위를 만들 수 있습니다.


암호:

var MyObject = {};

(function (root) {
    function myPrivateFunction() {
       return "I can only be called from within the closure";
    }

    root.myFunction = function (foo) {
        //do something
    };

    myPrivateFunction(); // returns "I can only be called from within the closure"

})(MyObject);


myPrivateFunction(); // throws error - undefined is not a function


답변

장점 :

  1. 개인 범위에서 변수를 유지합니다.

  2. 기존 개체의 기능을 확장 할 수 있습니다.

  3. 성능이 향상됩니다.

위의 세 가지 간단한 요점은 그 규칙을 따르기에 충분하다고 생각합니다. 그리고 그것을 단순하게 유지하려면 내부 함수를 작성하는 것뿐입니다.


답변

당신이 보여주는 특별한 경우에는 기능이나 가시성 측면에서 의미있는 차이가 없습니다.

원래 코더는이 접근 방식을 일종의 템플릿으로 채택하여 다음과 같은 정의에 사용할 수있는 개인 변수를 정의 할 수 있습니다 myFunction.

var MyObject = {};
(function(root) {
    var seconds_per_day = 24 * 60 * 60;   // <-- private variable
    root.myFunction = function(foo) {
        return seconds_per_day;
    };
})(MyObject);

이렇게하면 seconds_per_day함수가 호출 될 때마다 계산을 피하고 전역 범위를 오염시키지 않습니다.

그러나 본질적으로 그와 다른 것은 없습니다.

var MyObject = function() {
    var seconds_per_day = 24 * 60 * 60;
    return {
        myFunction: function(foo) {
            return seconds_per_day;
        }
    };
}();

원래 코더는 root.myFunction = function의 개체 / 속성 구문 대신 의 선언적 구문을 사용하여 개체에 함수를 추가 할 수있는 것을 선호했을 수 있습니다 myFunction: function. 그러나 그 차이는 주로 선호도의 문제입니다.

그러나 원래 코더가 취한 구조는 속성 / 메소드를 코드의 다른 곳에 쉽게 추가 할 수 있다는 이점이 있습니다.

var MyObject = {};
(function(root) {
    var seconds_per_day = 24 * 60 * 60;
    root.myFunction = function(foo) {
        return seconds_per_day;
    };
})(MyObject);

(function(root) {
    var another_private_variable = Math.pi;
    root.myFunction2 = function(bar) { };
})(MyObject);

요컨대, 필요하지 않은 경우이 접근 방식을 채택 할 필요가 없지만 완벽하게 잘 작동하고 실제로 몇 가지 장점이 있기 때문에 변경할 필요도 없습니다.


답변

  1. 첫 번째 패턴은 개체를 가져와 일부 수정을 통해 해당 개체를 반환하는 모듈로 사용할 수 있습니다. 즉, 이러한 모듈을 다음과 같이 정의 할 수 있습니다.

    var module = function (root) {
        root.myFunction = function (foo) {
            //do something
        };
    }
    

    그리고 다음과 같이 사용하십시오.

    var obj = {};
    module(obj);
    

    따라서 나중에 사용하기 위해이 모듈을 재사용 할 수 있다는 장점이 있습니다.


  1. 첫 번째 패턴에서는 개인 속성 및 메서드와 같은 개인 정보를 저장할 개인 범위 를 정의 할 수 있습니다 . 예를 들어 다음 스 니펫을 고려하십시오.

    (function (root) {
    
        // A private property
        var factor = 3;
    
        root.multiply = function (foo) {
            return foo * factor;
        };
    })(MyObject);
    

  1. 이 패턴은 배열, 개체 리터럴, 함수와 같은 모든 유형의 개체에 메서드 또는 속성을 추가하는 데 사용할 수 있습니다.

    function sum(a, b) {
        return a + b;
    }
    
    (function (root) {
        // A private property
        var factor = 3;
        root.multiply = function (foo) {
            return foo * factor;
        };
    })(sum);
    
    console.log(sum(1, 2)); // 3
    console.log(sum.multiply(4)); // 12
    

내 생각에 주요 이점은 두 번째 (개인 범위 생성) 일 수 있습니다.


답변

이 패턴은 전역 범위에 표시되지 않는 도우미 함수를 정의 할 수있는 범위를 제공합니다.

(function (root) {

    function doFoo() { ... };

    root.myFunction = function (foo) {
        //do something
        doFoo();
        //do something else
    };

})(MyObject);

doFoo 익명 함수에 로컬이므로 외부에서 참조 할 수 없습니다.


답변