自己参照の匿名クロージャー:JavaScriptは不完全ですか?


18

JavaScriptで匿名の自己参照関数のクロージャーが非常に優れているという事実は、JavaScriptが不完全な仕様であることを示唆していますか?これの多くを見る:

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

そして、私はすべてが好みの問題だと思いますが、あなたが望むのはプライベートな名前空間だけであるとき、これは手品のように見えませんか?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は適切なクラスを実装できませんでしたか?」番号。。すでに適切なプロトタイプがあります。プロトタイプはクラスに劣りません。彼らは異なっている。人々は、JavaScriptにクラスを何度も追加しようとしましたが、かなり失敗しました。
ラインヘンリッヒス

5
@Rein:それでも、どういうわけかActionScriptはそれを管理していました...
Mason Wheeler

8
@Tomには「組み込みクラス」はありません。プロトタイプ言語のクラスのようなものはありません。2つのパラダイムを融合し続けます。
ラインヘンリッヒス

1
個人的には、匿名関数言語機能はクラスよりも柔軟性が高いと感じています。しかし、このイディオムが一般的な関数型プログラミングが好きです。
-Dietbuddha

1
他の人は、こちら:brianodell.net/?page_id=516は、プロトタイプ言語としてのJavaScriptの素晴らしい入門書です。
トム・オージェ

回答:


9

私はすべてが好みの問題だと思いますが、プライベートな名前空間だけが必要な場合、これは見苦しいようには見えませんか?JavaScriptはパッケージと適切なクラスを実装できませんでしたか?

ほとんどのコメントは「プロトタイプは貧乏人のクラス」であるという神話に反しているので、プロトタイプベースのオブジェクト指向がクラスベースのオブジェクト指向に劣らないことを繰り返します。

もう1つのポイントは、「プライベートな名前空間が必要なときは気を散らすこと」です。Schemeはスコープを定義するためにまったく同じクラッジを使用していることを知って驚くかもしれません。それは、字句解析の優れた典型的な例になりました。

もちろん、Schemeでは、 'kludge'はマクロの後ろに隠れています。...


1
Schemeが字句解析の主要な例であり、Schemeがスコープを定義するために関数を使用した方法と関係があるという主張を裏付ける証拠はありません。
DeadMG

Schemeは模範ではありませんが、JSの共同作成者Brendan EichがJSの設計でSch​​emeの役割を果たしていることを議論する一例はこちらです: readwrite.com/2011/07/22/javascript-was-no-accident
Erik Reppen

7

まず、いくつかのこと:

  1. JavaScriptを見るもう1つの方法は、関数を構成要素として使用して実行できる100万と1つのことです。あなたがそれを探すなら、それはすべてそこにあります。機能から決して遠くはありません。

  2. jQueryプラグインのオーサリングはひどいものです。なぜ彼らがそれを主張しているのか、私にはわかりません。$拡張機能は、build-me-a-complete-widgetメソッドではなく、すでに十分にカバーされている汎用のものである必要があります。これはDOM-API正規化ツールです。それの使用は、あなた自身のオブジェクトの中に埋めることが最善です。完全なUIライブラリリポジトリとして使用することの魅力は見当たりません。

クライアント側Web上のパッケージは無意味です

クライアント側のWeb上のパッケージについて私が個人的に好きではないことは、基本的に、私たちが本当にしていないことをしているふりをするということです。ポスト.NET Webフォームと、Javaフレンドから決してパニングアウトされない恐ろしいもののゴブの世界では、リンクされたリソースを持つHTMLの塊を、それが本当にあるものだと思いますそして、何か新しいもののふりをして、新しいことを学ぶことに抵抗するOSアプリ開発者をなだめようとしないでください。クライアント側のWeb上のJSでは、ブラウザキャッシュを無視して動作するAjaxでひどいことをしなければ、「インポート」されるものは何もありません。ブラウザにとって重要なことは、ブラウザにロードされて解釈されたか、そうでないかです。「万が一に備えて」使用できるコードがクライアントに隠されていない 正当な理由で。#1は、現象が一般的にうまく機能していないため、Webアプリのプラグインとブラウザープラグインの依存関係を説明しただけです。今、ウェブが欲しい。AdobeまたはSunが今週3回目の更新を完了した後ではありません。

言語には構造に必要なものがあります

JSオブジェクトは非常に変更可能です。名前空間のツリーを枝分かれさせることは、そのようにするのが便利であると思う程度まで持つことができ、とても簡単です。しかし、はい、再利用可能なものはすべて、ライブラリのルートをグローバルスペースに固定する必要があります。とにかくすべての依存関係が同時にリンクされてロードされるので、他に何かをする意味は何ですか?グローバルな名前空間を回避することのポイントは、そこに何も悪いことではありません。名前空間が衝突したり、コア言語機能を誤って上書きしたりする危険があるため、あまりにも多くのものが悪いのです。

人気があるからといって、それが正しいとは限らない

これをクライアント側のWebアプリ全体で見ると:

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

問題は、アプリを構造化するためのツールが不足していることではなく、問題は人々が構造を重視していないことです。設計会社の2〜3ページの一時的な使い捨てサイトについては、実際には問題はありません。見苦しいのは、保守可能で読みやすく、簡単に変更できるものを構築する必要がある場合です。

しかし、再利用可能なオブジェクトとファクトリーをすべて実装する時が来たところで、1つまたは2つの新しい一時変数がそのプロセスに忍び込むかもしれませんが、それは便利です。

しかし、パッケージ/モジュールを使用したJSの実装があります

Node.jsでは、そのようなことがもっと理にかなっているところで、モジュールを持っていることに注意してください。JSは、他の言語を悩ますuber-config-hellを回避できると仮定すると、方程式の唯一のものであり、実行される各ファイルは独自の分離スコープです。しかし、Webページでは、jsファイルをリンクすること自体がimportステートメントです。リソースを取得するには、別のページで再び必要になった場合にブラウザにキャッシュされるので、必要に応じてファイルにリンクを追加するよりも多くの労力が必要になるため、その場でより多くのインポートを実行することは時間とリソースの無駄です。そのため、jQueryなどのアダプターオブジェクトファクトリーや、特定のドメイン内のタスクの大部分をカバーし、グローバルで1つのスポットを占有する従来のオブジェクトを作成する以外の方法でグローバルスペースを分割しようとしています。そこ'http://wiki.ecmascript.org/doku.php?id=harmony:modules

そのため、グローバルな名前空間の汚染を回避するために使用される自動呼び出しには、そのようなものを使用する正当な理由がある場合は何も悪いことはありません(そうでない場合が多いです)。そして、オブジェクトに永続的なプライベート同等のプロパティがあります(コンストラクタでvarを定義するだけで、プロパティとして公開しないでください)。

しかし、このようなことができるという事実は素晴らしいです。大量の使用は、JS開発者がまだ成熟していることを示す兆候ですが、ここでは意味をなさないクライアントサイドWebにパラダイムを強制しようとしない人にとって、言語の大きな穴ではありません。


ダウン投票者に、その理由を説明してもらえますか?誰かがそんなに書いているとき、私は彼が説明に値すると思います!
松o

+1の良い答え、なぜ以前は反対票を投じていたのかわかりません。
嘆願

素晴らしい記事と素晴らしい展望。私はまた、「それが単に縄だからといって、それが正しいことを意味するわけではありません。」も好きです。私の問題は、より厳密な言語に慣れていることだと思います(IMO)は、さまざまな方法で開発効率を高めます。JavaScriptは、多くの組み込みのチェックとバランスがなく、本当に希望に満ちたものに見えます。好きなことを実行できます。コーディング構造にアプローチする「正しい」方法を特定するのは困難です。私は、1回限りの迅速な求職者にとって、これは大きな懸念ではないことに同意します。
トム・オージェ

1
IMO、あなた自身を掛ける以外にたくさんのロープでできることはたくさんあり、あなたはより良い習慣を身につけるにつれてあまり頻繁に起こらない時折起こる自己ハングアップから堅牢なコードをより速く書くことを学びますが、私はそれをするつもりはありません全員またはあらゆる仕事の理想的な候補者。私はあなたがそれについてもっと学ぶと思うが、あなたはそれをより忍耐強く見つけるだろう。JSのように柔軟/可変のファーストクラスの関数やオブジェクトのない言語で物事を行おうとすると、頭の半分が欠けているように感じます。
エリックReppen

4

もう1つ欠けているのは、javscriptには後方互換性が必要であることです。パッケージ構文を導入しようとすると、実際にいくつかの奇妙な方法でWebが破壊される可能性があります。それは悪いだろう!ダグ・クロックフォードはさまざまな点でこれについて話し、それを追加する試みが失敗した理由を説明しました。


それは良い点です。それでも、ActionScriptは単に新しいバージョンを公開するだけで管理していました。スクリプトタグを定義するときは、常にJavaScriptバージョンを指定できるため、既存のサイトを「破壊」することは問題ではありません。
トム・オージェ

1
実際には、ネット上のほとんどのスクリプトタグにはバージョン番号がありません。正直なところ、私はこの問題に関するすべての問題を確信しているわけではありませんが、この問題について考えている人々がそれを実行できないと判断したことは知っています。
ザカリーK

1
@Tom:AdobeはFlashプラットフォームを完全に制御しています。すべてのJSプラットフォームを完全に制御できるエンティティはありません。また、ブラウザでJSスクリプトのバージョン番号を追加するだけでは、古いブラウザをサポートしていないか、2つのスクリプトを記述する必要があります。だから、それ問題です。
ジェレミーハイラー

2

はい、それは手品です。

多くの人が「プロトタイプはクラスに劣らない」と言っています。私は同意しませんが、それは好みの問題です。しかし、それはJavaScriptの本当の問題でさえありません-問題は、元々はアニメーションボタンのようなものを作成するための迅速で汚いスクリプト言語として設計されたということです。90年代半ばに戻って、JavaScriptが現在行っているクレイジーなことを行うように求められるとは誰も思いもしませんでした。


6
JavaScriptは、その言語が実際に本当に素晴らしいJavaScriptに同意しません。仕様が不十分で相互に互換性のないDOMと一緒にまとめられたことが、すべての問題の始まりです。
ディーンハーディング

2
これはプロトタイプと何の関係がありますか?
エリックReppen

2

匿名の自己呼び出し関数は、クラスよりもモジュールに似ています。javascriptのデフォルトがグローバルスコープで実行されるのは面倒です。JS.nextに取り組んでいる委員会は、ローカル変数をグローバルスコープにドロップしないように、モジュールの追加を真剣に検討しています。幸いなことに、Javascriptの関数には非常に便利なセマンティクスがあり、匿名関数をプライベートスコープとして比較的簡単に使用できます。

クラスが多くの言語でトップレベルのスコープ構成であるということを除いて、クラスが実際にどのように議論に参加するかはわかりません。より良いモジュール/パッケージ/ please-give-me-a-local-scope-so-i-don't-leave-my-variables-in-the-global-environmentコンストラクトがあればとても便利です。


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.