자바 스크립트에서 소문자 "f"를 사용하는`new function ()`


106

제 동료는 소문자 "f"와 함께 "new function ()"을 사용하여 JavaScript에서 새 개체를 정의했습니다. 모든 주요 브라우저에서 잘 작동하는 것처럼 보이며 개인 변수를 숨기는데도 상당히 효과적입니다. 예를 들면 다음과 같습니다.

    var someObj = new function () {
        var inner = 'some value';
        this.foo = 'blah';

        this.get_inner = function () {
            return inner;
        };

        this.set_inner = function (s) {
            inner = s;
        };
    };

"this"가 사용되는 즉시 someObj의 공용 자산이됩니다. 따라서 someObj.foo, someObj.get_inner () 및 someObj.set_inner ()는 모두 공개적으로 사용할 수 있습니다. 또한 set_inner () 및 get_inner ()는 권한이있는 메소드이므로 클로저를 통해 "내부"에 액세스 할 수 있습니다.

그러나 나는이 기술에 대한 언급을 어디서도 보지 못했습니다. Douglas Crockford의 JSLint조차도 이에 대해 불평합니다.

  • 이상한 건설. '신규'삭제

우리는이 기술을 프로덕션에 사용하고 있고 잘 작동하는 것 같지만 어디에도 문서화되어 있지 않기 때문에 약간 불안합니다. 이것이 유효한 기술인지 아는 사람이 있습니까?


6
IIFE ( '즉시 호출 된 함수')보다 귀하의 구성을 선호합니다. 1 : 명시적인 '인스턴스'객체가 필요하지 않습니다. 바로 자바 스크립트에서 'this'입니다. 2 : 아무것도 반환 할 필요가 없습니다. 즉, 기억할 필요가 없습니다. 수락 된 답변의 작성자조차도 처음에 인스턴스 객체를 반환하는 것을 잊었습니다! 사람들은 일반적으로 new & this를 싫어하는 경우 IIFE를 사용하는 것을 선호합니다. 좋은 이유가 있습니다. DOM 이벤트를 처리하는 함수가있는 경우 this개체가 아닌 이벤트를 발생시킨 요소를 참조하지만 var instance = this대신 사용할 수 있습니다 .
Lee Kowalkowski 2012

1
"소문자 f"를 지정하는 것이 질문에 중요한 이유는 무엇입니까?
ClearCloud8 2013-04-03

7
Javascript에는 'Function'함수 (대문자 F 포함)도 존재하기 때문에 다른 점은 다음과 같습니다. Function 은 새로운 함수 객체를 생성 할 수있는 생성자 함수 인 반면 function 은 키워드입니다.
Stijn de Witt


@Bergi 나는 당신의 링크를 읽었습니다. 나는이 패턴을 불신 할 이유가 없다. 유효합니다. 간단 해. 그래서 무엇이 잘못되었습니다. JSLint는 : BTW 모든 것에 대해 불평
스테인 드 위트에게

답변:


64

나는 이전에 그 기술을 보았고, 유효하며, 마치 Constructor Function 인 것처럼 함수 표현식을 사용하고 있습니다 .

그러나 IMHO, 자동 호출 함수 표현식으로 동일한 결과를 얻을 수 있습니다 new. 그런 식으로 연산자 를 사용하는 요지는 실제로 보이지 않습니다 .

var someObj = (function () {
    var instance = {},
        inner = 'some value';

    instance.foo = 'blah';

    instance.get_inner = function () {
        return inner;
    };

    instance.set_inner = function (s) {
        inner = s;
    };

    return instance;
})();

new연산자 의 목적은 새 개체 인스턴스를 만들고 [[Prototype]]내부 속성을 설정하는 것입니다. 내부 속성에 의해 어떻게 만들어 지는지 확인할 수 있습니다 [Construct].

위의 코드는 동등한 결과를 생성합니다.


1
섹션 13의 ECMAScript 262 사양은이를 좀 더 공식적으로 설명합니다. 이와 같은 것은 [아마 새 함수 ()를 사용하여] 객체 function foo () {}를 생성 한 결과를 반환합니다 Function. 구문 설탕입니다.
Clinton Pierce

3
나는 당신이 return instance;마지막에 누락되었다고 생각합니다 . 그렇지 않으면, someObj단지 될 것입니다 undefined. :-)
Matthew Crumley

1
모듈 성과 정보 숨기기에 관심이 있다면 포기하고 require.js와 같은 것을 사용하기 시작하라고 제안해도 될까요? 반쯤 왔는데 왜 여기서 멈춰? 비동기 모듈 정의 (require.js가 구현하는 것)는이 사용 사례를 지원하며 범위 지정, 네임 스페이스 및 종속성 관리를 처리 할 수있는 전체 도구 세트를 제공합니다.
Stijn de Witt

함수 선언을 둘러싼 괄호는 문이 이미 존재하기 때문에 이미 표현식이기 때문에 불필요합니다.=
Explosion Pills

중간에 @StijndeWitt는 require.js를 사용하기 위해 두 배의 작업을 수행해야 함을 의미하지만 간단한 경우에는 이것이 필요한 전부일 수 있습니다.
xr280xr 2015

15

귀하의 코드는 덜 이상한 구조와 비슷합니다.

function Foo () {
    var inner = 'some value';
    this.foo = 'blah';

    ...
};
var someObj = new Foo;

9
단지 유사하지 않고 정확히 똑같은 일을합니다. 단 하나의 예외는 Foo를 재사용하여 다른 객체를 만들 수 없다는 것입니다.
kikito 2010

3
OP의 버전은 새로운 someObj.constructor 를 통해 재사용 될 수 있습니다 . 여기서 생성자는 네임 스페이스에 명시 적으로 추가됩니다. 올바른 스타일은 함수의 의도 된 목적에 따라 다릅니다. 또한이 스타일 (확실히 표준)은 Foo 이전에 새로운 것을 잊어 버린 경우 누군가가 전역 네임 스페이스를 채울 수 있도록합니다 .
J Bryan Price

@kikito 이것이 Foo를 재사용하여 다른 개체를 만드는 것을 허용하지 않는다는 것은 무엇을 의미합니까? var newObj = new Foo ()는 새 인스턴스를 만들어야합니다.
Bill Yang

1
@BillYang 5 년 전 일입니다. 몰라. 나는 그 이후로 자바 스크립트를 건드리지 않았습니다.
kikito 2015

12

몇 가지 측면을 명확히하고 Douglas Crockford의 JSLint가 귀하의 코드에 대해 불평하지 않도록하기 위해 여기에 인스턴스화의 몇 가지 예가 있습니다.

1. o = new Object(); // normal call of a constructor

2. o = new Object;   // accepted call of a constructor

3. var someObj = new (function () {  
    var inner = 'some value';
    this.foo = 'blah';

    this.get_inner = function () {
        return inner;
    };

    this.set_inner = function (s) {
        inner = s;
    };
})(); // normal call of a constructor

4. var someObj = new (function () {  
    var inner = 'some value';
    this.foo = 'blah';

    this.get_inner = function () {
        return inner;
    };

    this.set_inner = function (s) {
        inner = s;
    };
}); // accepted call of a constructor

예제 3. (...)의 표현식 값은 함수 / 생성자입니다. 다음과 같이 보입니다 : new (function () {...}) (). 따라서 예제 2에서와 같이 끝 괄호를 생략해도 표현식은 여전히 ​​유효한 생성자 호출이며 예제 4처럼 보입니다.

Douglas Crockford의 JSLint는 인스턴스가 아닌 someObj에 함수를 할당하기를 원했습니다. 결국 그것은 오류가 아니라 경고 일뿐입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.