자체 참조 익명 폐쇄 : JavaScript가 불완전합니까?


18

익명의 자체 참조 함수 클로저가 JavaScript에서 매우 널리 사용된다는 사실은 JavaScript가 불완전한 스펙임을 암시합니까? 우리는 이것의 많은 것을 본다 :

(function () { /* do cool stuff */ })();

그리고 모든 것이 맛의 문제라고 생각하지만 원하는 모든 것이 개인 네임 스페이스 일 때 이것이 kludge처럼 보이지 않습니까? JavaScript가 패키지 및 적절한 클래스를 구현할 수 없습니까?

ECMAScript를 기반으로하는 ActionScript 3과 비교해보십시오.

package com.tomauger {
  import bar;
  class Foo {
     public function Foo(){
       // etc...
     }

     public function show(){
       // show stuff
     }

     public function hide(){
       // hide stuff
     }
     // etc...
  }
}

JavaScript에서 수행하는 컨벌루션과 대조적으로 ( jQuery 플러그인 저작 문서에서 제공 ) :

(function( $ ){

  var methods = {
    init : function( options ) { // THIS },
    show : function( ) { // IS   },
    hide : function( ) { // GOOD },
    update : function( content ) { // !!! }
  };

  $.fn.tooltip = function( method ) {

    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    

  };

})( jQuery );

이 질문이 환경 설정 및 프로그래밍 스타일에 대한 불만으로 쉽게 변질 될 수 있음을 알고 있지만 실제로는 숙련 된 프로그래머가 이에 대해 어떻게 느끼는지, 새로운 언어에 대한 다른 특유성을 배우는 것과 같은 자연 스러움을 느끼는지 궁금합니다. 구현되지 않은 기본 프로그래밍 언어 구성 요소에 대한 해결 방법처럼?


22
"자바 스크립트를 구현할 수 없습니다 ... 적절한 클래스?" 아니요 . 이미 올바른 프로토 타입이 있습니다. 프로토 타입은 클래스보다 열등하지 않습니다. 그들은 다르다. 사람들은 다양한 시간에 JavaScript에 클래스를 추가하려고 시도했지만 다소 성공하지 못했습니다.
Rein Henrichs

5
@Rein : 그리고 어쨌든 ActionScript는 그것을 관리했습니다 ...
Mason Wheeler

8
@Tom에는 "내장 클래스"가 없습니다. 프로토 타이핑 언어 의 수업은 없습니다 . 당신은 두 패러다임을 계속 혼란스럽게합니다.
Rein Henrichs

1
나는 개인적으로 익명 함수 언어 기능이 클래스보다 더 유연하다는 것을 알았습니다. 그러나 나는이 관용구가 일반적인 기능적 프로그래밍을 좋아한다.
dietbuddha

1
다른 사람들을 위해, 여기 : brianodell.net/?page_id=516 은 프로토 타입 언어 인 JavaScript의 훌륭한 입문서입니다.
Tom Auger

답변:


9

나는 모든 것이 맛의 문제라고 생각하지만 원하는 모든 것이 개인 네임 스페이스 일 때 이것이 kludge처럼 보이지 않습니까? JavaScript가 패키지 및 적절한 클래스를 구현할 수 없습니까?

대부분의 의견은 "시제품이 가난한 사람의 계급이다"라는 신화에 반대한다. 그래서 나는 단지 프로토 타입 기반 OO가 클래스 기반 OO보다 열등하지 않다는 것을 반복 할 것이다.

다른 점은 "개인 네임 스페이스를 원할 때 혼란"이라는 점입니다. Scheme이 똑같은 kludge를 사용하여 범위를 정의한다는 것을 알고 놀랄 것입니다. 그것은 어휘 범위 지정의 전형적인 예가되는 것을 멈추지 않았습니다.

물론, Scheme에서 'kludge'는 매크로 뒤에 숨겨져 있습니다 ....


1
Scheme이 어휘 범위 지정의 주요 예이거나 Scheme이 범위를 정의하기 위해 함수를 사용하는 방법과 관련이 있다는 주장을 뒷받침하는 증거는 없습니다.
DeadMG

Scheme이 모범이되었지만 JS 공동 제작자 Brendan Eich가 Scheme이 JS 디자인에서 중요한 역할을
한다고 설명하는 사례는

7

우선, 몇 가지 사항 :

  1. JavaScript를 보는 또 다른 방법은 함수로 구성 할 수있는 백만 및 1 가지 작업입니다. 당신이 그것을 찾으면 모든 것이 있습니다. 그것은 결코 기능에서 멀지 않습니다.

  2. 그 jQuery 플러그인 제작은 끔찍합니다. 그들이 왜 그런 주장을하는지 모르겠습니다. $ 확장은 $가 이미 잘 완성 된 위젯 방법으로는 다루지 않은 일반적인 용도의 것이어야합니다. DOM-API 정규화 도구입니다. 사용은 자신의 물건 안에 가장 잘 묻혀 있습니다. 완전한 UI 라이브러리 리포지토리로 사용한다는 호소력이 없습니다.

클라이언트 측 웹의 패키지는 의미가 없습니다

클라이언트 측 웹의 패키지에 대해 개인적으로 싫어하는 점은 기본적으로 우리가 실제로하지 않는 일을하는 척하는 것입니다. 포스트 .NET 웹 양식과 Java 친구와는 거리가 멀지 않은 무시 무시한 물건 세계에서 링크 된 리소스가있는 HTML 덩어리가 실제로 무엇인지 생각하고 싶습니다. 새로운 것을 막기 위해 학습에 강한 새로운 OS 앱 개발자를 유혹하지 마십시오. 클라이언트 측 웹의 JS에서는 브라우저 캐싱을 무시하고 작동하는 Ajax로 끔찍한 일을하지 않고 "가져온"것도 없습니다. 많은 사람들이 시도했습니다. 브라우저에 중요한 것은 브라우저가로드되어 해석되었거나 그렇지 않은 것입니다. "경우에 따라"사용할 수있는 클라이언트에 더 많은 코드가 숨겨져 있지 않습니다. 좋은 이유가 있습니다. # 1 : 웹 애플리케이션에 대한 플러그인 및 브라우저 플러그인 종속성을 현상이 일반적으로 너무 잘 해결되지 않았기 때문에 방금 설명했습니다. 우리는 지금 웹을 원합니다. 이번 주 세 번째로 Adobe 또는 Sun이 업데이트 된 후에는 아닙니다.

언어에는 구조에 필요한 것이 있습니다

JS 객체는 변경이 매우 쉽습니다. 우리는 이름 공간의 분기 트리를 어느 정도 나 가질 수 있으며 그렇게하는 것이 유용하고 매우 쉽습니다. 그러나 그렇습니다. 재사용 가능한 것은 전역 공간의 모든 라이브러리의 근본을 고수해야합니다. 어쨌든 모든 종속성은 동시에 연결되고로드되므로 다른 작업의 요점은 무엇입니까? 전역 네임 스페이스를 피하는 것은 나쁜 점이 없다는 것입니다. 네임 스페이스 충돌의 위험이 있거나 실수로 핵심 언어 기능을 덮어 쓰기 때문에 나쁜 점이 너무 많습니다.

인기가 있다고해서 우리가 올바르게하고 있다는 의미는 아닙니다.

이제 클라이언트 측 웹 앱에서이 모든 것을 볼 수 있습니다.

(function(){
//lots of functions defined and fired and statement code here
})()

문제는 우리가 앱을 구성 할 도구가 부족하다는 것이 아니라 사람들이 구조를 평가하지 않는다는 것입니다. 디자인 에이전시에서 2-3 페이지의 일회성 일시 중단 사이트에 대해서는 실제로 문제가 없습니다. 추악한 곳은 유지 관리 가능하고 읽기 쉽고 수정하기 쉬운 것을 만들어야 할 때입니다.

그러나 재사용 가능한 모든 객체와 팩토리를 구현할 때가되었을 때 한두 개의 새로운 임시 변수가 해당 프로세스에 영향을 줄 수 있습니다.

그러나 패키지 / 모듈을 사용한 JS 구현이 있습니다

Node.js에서는 이러한 것들이 훨씬 더 의미가있는 곳에 모듈이 있다는 것을 명심하십시오. JS는 다른 언어를 괴롭히는 uber-config-hell을 피할 수 있다고 가정하면 방정식의 유일한 요소이며 실행 된 각 파일은 자체 격리 범위입니다. 그러나 웹 페이지에서 js 파일을 연결하는 것은 그 자체로 import 문입니다. 리소스를 가져 오려면 다른 페이지에서 다시 필요할 경우 브라우저에 캐시 될 것임을 알고 파일에 대한 링크를 추가하는 것보다 훨씬 많은 노력이 필요하기 때문에 더 많은 가져 오기를 수행하는 것은 시간과 리소스를 낭비하는 것입니다. 따라서 jQuery와 같은 어댑터 객체 팩토리 또는 주어진 도메인에서 대규모 작업 하위 세트를 다루는 전역 객체를 차지하는 기존 객체와 같은 어댑터 객체 팩토리를 만드는 것 이외의 다른 작업을 수행하여 글로벌 공간을 분할하려고합니다. 그곳에'http://wiki.ecmascript.org/doku.php?id=harmony:modules

따라서 자동 호출자가 전역 네임 스페이스 오염을 피하는 데 사용되는 것은 아무 문제가 없습니다. 그리고 우리는 객체에 개인과 동등한 속성을 가지고 있습니다 (생성자에서 var를 정의하고 속성으로 노출시키지 마십시오).

그러나 우리가 그러한 일을 할 수 있다는 사실은 굉장합니다. 과중한 사용은 JS 개발자가 아직 성숙하고 있다는 신호이지만, 여기서 이해가되지 않는 클라이언트 측 웹에 패러다임을 강요하지 않는 사람에게는 언어의 허점이 아닙니다.


Down-Voter에게 이유를 설명해 주시겠습니까? 누군가가 그렇게 많이 쓰면 설명이 필요하다고 생각합니다!
Songo

+1 정답, 왜 다운 투표를했는지 잘 모르겠습니다.
pllee

멋진 글쓰기와 훌륭한 관점. 또한 "트로프이기 때문에 그것이 옳다는 것을 의미하지는 않습니다." 제 문제는 더 엄격한 언어에 더 익숙하다는 것입니다. (IMO) 여러 가지 방법으로 개발 효율성을 향상시킵니다. JavaScript는 많은 수표와 균형을 갖추지 않은 채 정말 소름 끼치는 것처럼 보입니다. 원하는대로 무엇이든 할 수 있기 때문에 관용구와 관행이 엉망입니다. 코딩 구조에 접근하는 "올바른"방법을 정하기는 어렵습니다. 빠른 일회성 작업의 경우 이는 큰 문제가되지 않는다는 데 동의합니다.
Tom Auger 2019

1
IMO, 당신은 교수형 이외에 많은 밧줄로 할 수있는 일이 많으며 더 나은 습관을 개발할 때 자주 발생하지 않는 가끔씩 발생하는 자체 행잉에서 강력한 코드를 더 빨리 작성하는 법을 배웁니다. 모든 직업 또는 모든 직업에 이상적인 후보자. 그러나 더 많이 배울수록 더 견딜 수있을 것으로 생각됩니다. JS와 같이 일류 기능이나 객체가 유연하지 않고 언어가없는 언어로 일을하려고 할 때 뇌의 절반이 빠져있는 것처럼 느낍니다.
Erik Reppen

4

누락 된 또 다른 것은 javscript가 이전 버전과 호환되어야한다는 것입니다. 패키지 구문을 도입하려고 시도하면 실제로 웹을 망가뜨릴 수 있습니다. 그것은 나쁠 것입니다! 더그 크록 포드 (Dug Crockford)는 여러 가지 점에서 이에 대해 이야기했고 왜 그것을 추가하려는 시도가 실패했는지에 대해 이야기했습니다.


그건 좋은 지적이야. 그러나 ActionScript는 단순히 새 버전을 만들어서 관리했습니다. 스크립트 태그를 정의 할 때 항상 JavaScript 버전을 지정할 수 있었으므로 기존 사이트를 "중단"하는 것은 문제가되지 않아야합니다.
Tom Auger

1
실제로 인터넷상의 대부분의 스크립트 태그에는 버전 번호가 없습니다. 솔직히 말해서 나는 이것에 관한 모든 문제를 확신하지 못하지만,이 물건에 대해 생각하는 사람들은 그것이 불가능하다고 결정했다고 알고 있습니다.
Zachary K

1
@Tom : Adobe는 Flash 플랫폼을 완벽하게 제어합니다. 어느 엔티티도 모든 JS 플랫폼을 완전히 제어 할 수 없습니다. 또한 브라우저에서 JS 스크립트의 버전 번호를 확인하면 이전 브라우저를 지원하지 않거나 두 개의 스크립트를 작성해야합니다. 그래서, 그것은 이다 문제.
Jeremy Heiler

2

그렇습니다.

많은 사람들이 "시제품이 수업보다 열등하지 않다"고 말합니다. 나는 동의하지 않지만 그것은 선호의 문제입니다. 그러나 그것은 JavaScript의 실제 문제조차 아닙니다. 문제는 원래 애니메이션 버튼과 같은 것을 만들기 위해 빠르고 더러운 스크립트 언어로 설계되었다는 것입니다. 90 년대 중반에는 JavaScript가 현재하고있는 몇 가지 미친 일을하라는 요청을받은 사람이 아무도 없었습니다.


6
JavaScript가 실제로 정말 훌륭하다는 것에 동의하지 않습니다. 불명확하고 상호 호환되지 않는 DOM과 함께 모든 문제가 시작된 곳입니다.
Dean Harding

2
이것이 프로토 타입과 어떤 관련이 있습니까?
Erik Reppen

2

익명의 자체 호출 함수는 클래스보다 모듈과 더 유사합니다. 자바 스크립트의 기본값이 전역 범위에서 실행된다는 것은 성가신 일입니다. JS.next에 관한위원회는 모듈을 추가하는 것을 진지하게 고려하고 있으므로 지역 변수를 전역 범위에 버리지 않습니다. 운 좋게도 Javascript의 함수에는 편리한 의미론이있어 익명 함수를 비교적 쉽게 개인 범위로 사용할 수 있습니다.

클래스가 많은 언어에서 최상위 범위 지정 구문이라는 점을 제외하고 클래스가 실제로 토론에 어떻게 참여하는지 보지 못합니다. 더 나은 모듈 / 패키지 / 제발-제발-지역-범위-그래서-내-가변-내-세계-환경 구성 구조는 매우 좋을 것입니다.


1

네임 스페이스를 잘 구현 한 ExtJS 3 및 4를 살펴볼 수 있습니다.

--1 이후에 추가됨

내 요점은이 모든 '컨볼 루션'을 숨기고 여전히 매우 친숙한 코드를 가질 수 있다는 것입니다.

Ext.ns('com.tomauger');
Ext.Loader.load('bar.js'); //unfortunately filname needs to be used
MyNameSpace.Foo = {
   //...
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.