Самоаналіз анонімних закриттів: чи незавершений JavaScript?


18

Чи свідчить той факт, що закриття функції анонімного самопосилання настільки перевалять у JavaScript, що JavaScript є неповною специфікацією? Ми бачимо стільки цього:

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

і я гадаю, що все - справа смаку, але чи це не схоже на хитрощі, коли все, що вам потрібно, - це приватний простір імен? Не вдалося JavaScript реалізувати пакети та належні класи?

Порівняйте з ActionScript 3, також заснованим на ECMAScript, де ви отримуєте

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 це впорався ...
Мейсон Уілер

8
@Тому немає "вбудованих класів". Не існує такого поняття, як клас на прототипній мові . Ви продовжуєте плутати дві парадигми.
Рейн Генріхс

1
Я особисто вважаю, що функція мови анонімних функцій є більш гнучкою, ніж класи. Однак мені подобається функціональне програмування, в якому ця ідіома є загальною.
дієтабудди

1
Для інших тут: brianodell.net/?page_id=516 - приголомшливий праймер на JavaScript як мова прототипу.
Том Ожер

Відповіді:


9

Я припускаю, що все є справою смаку, але чи це не схоже на хитрощі, коли все, що вам потрібно, - це приватний простір імен? Не вдалося JavaScript реалізувати пакети та належні класи?

Більшість коментарів заперечують міф про те, що "прототипи - це класи бідних людей", тому я просто повторю, що ОО, засноване на прототипі, нічим не поступається ОО на базі класу.

Інший пункт "хитрості, коли все, що ви хочете, це приватний простір імен". Ви можете бути здивовані, дізнавшись, що схема використовує саме той самий вираз для визначення обсягів. Це не перешкоджало стати архетипним прикладом добре зробленого лексичного обстеження.

Звичайно, у Схемі "хитрість" прихована за макросами ....


1
Ви не представляєте жодних доказів, що підтверджують ваше твердження про те, що схема є основним прикладом добре зробленого лексичного обстеження або що це має щось спільне з тим, як схема використовувала функції для визначення обсягів.
DeadMG

Не можу говорити Схема бути зразком , але один приклад JS співтворець Брендан Ейч обговорює схему грає роль в дизайні JS тут: readwrite.com/2011/07/22/javascript-was-no-accident
Ерік Reppen

7

По-перше, кілька речей:

  1. Ще один спосіб перегляду JavaScript - це 1 мільйон і 1 речі, які ви можете виконати з функцією як конструкція. Це все є, якщо шукати. Це просто ніколи не далеко від функції.

  2. Ця річ із створенням плагінів jQuery жахлива. Я поняття не маю, чому вони виступають за це. $ розширення повинні бути загальноприйнятими матеріалами, у яких $ вже є досить добре охопленими методами не build-me-a-complete-widget Це інструмент нормалізації DOM-API. Це використання найкраще закопувати всередині власних об'єктів. Я не бачу заклику використовувати його як повне сховище бібліотеки інтерфейсу користувача.

Пакети на стороні клієнта безглузді

Що мені особисто не подобається у пакунках у мережі клієнтів, це те, що ми в основному робимо вигляд, що робимо щось, що насправді не є. У дописі .NET веб-форм і збитків жахливих речей, які ніколи не переганяються з нашого Java-друзів у світі, я вважаю за краще використовувати HTML з пов'язаними ресурсами як те, що це насправді? і не намагайтеся втішати розробників додатків для ОС, що навчаються, нові речі, роблячи вигляд, що це щось інше. У JS в Інтернеті на базі клієнта нічого не стає "імпортним" забороною, що робить щось жахливе з Ajax, який працює в незнанні кешування браузера, що так, багато хто намагався зробити. Важливе значення для браузера полягає в тому, що він або завантажений і інтерпретований, або не був. У нас немає більше коду, прихованого у клієнта, десь він доступний для використання "про всяк випадок" з поважних причин. # 1, оскільки я щойно описав залежність плагінів і плагінів для веб-додатків як явище, як правило, не надто добре. Зараз ми хочемо Інтернет. Не після того, як Adobe або Sun буде проведено оновлення втретє цього тижня.

Мова має те, що їй потрібно для структури

Об'єкти JS дуже мінливі. Ми можемо мати гілки дерев просторів імен будь-якої міри, що нам здається корисним це робити, і це дуже легко зробити. Але так, для будь-якого повторного використання ви повинні приклеїти корінь будь-якої бібліотеки в глобальному просторі. Всі залежності так чи інакше пов'язані та завантажені одночасно, тож який сенс робити щось інше? Сенс уникнення глобального простору імен полягає не в тому, що там все є погано. Це занадто багато матеріалів, це погано, оскільки ви ризикуєте зіткнутися з простором імен або випадково перезаписати функції основної мови.

Просто тому, що це популярно, не означає, що ми робимо це правильно

Тепер, коли ви бачите це в усьому веб-додатку на стороні клієнта:

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

Проблема полягає не в тому, що нам не вистачає інструментів для структуризації програми навколо, проблема полягає в тому, що люди не оцінюють структуру. Для одноразових тимчасових сайтів, що викидаються на 2-3 сторінки, у дизайнерське агентство, у мене насправді немає проблем з цим. Там, де стає некрасиво, це коли ви повинні побудувати щось доцільне, розбірливе і легко змінити.

Але коли ви дістанетесь до того місця, де настав час просто впровадити всі повторно використовувані об'єкти та фабрики, і, можливо, одна чи дві нові тимчасові вагони можуть залізти в цей процес, це зручність.

Але є реалізація СВ з пакетами / модулями

Майте на увазі, що в Node.js, де такі речі мають набагато більше сенсу, у них є модулі. JS, якщо припустити, що ми можемо уникнути uber-config-hell, що набридає іншими мовами, - це єдине в рівнянні, і кожен виконаний файл має свою окрему область. Але на веб-сторінці посилання js-файлу є самою заявою про імпорт. Робити більше імпорту на ходу - це лише марна трата часу та ресурсів, оскільки отримання ресурсів вимагає набагато більше зусиль, ніж просто додавання посилань на файли, оскільки вони вам потрібні, знаючи, що вони будуть кешовані у веб-переглядачі, якщо знову потрібна інша сторінка. Тому намагається розділити глобальний простір, роблячи що-небудь, крім створення заводських об'єктних заводів, таких як jQuery або більш традиційних об'єктів, які охоплюють велику множину завдань у даному домені, займаючи одно місце в глобальному масштабі. Там 'http://wiki.ecmascript.org/doku.php?id=harmony:modules

Тож ні, немає нічого поганого в автоматичних викликах, які використовуються для уникнення забруднення глобального простору імен, коли є вагомі причини використовувати такі речі (частіше за все, немає). І у нас є постійні властивості, еквівалентні приватному, у наших об'єктах (просто визначте var у конструкторі та не виставляйте його як властивість).

Однак той факт, що ми можемо робити такі речі, є приголомшливим. Сильне використання - це ознака того, що розробники JS все ще дозрівають, але це не є проміжною дірою в мові для тих, хто не намагається примусити парадигму до клієнтської павутини, яка тут просто не має сенсу.


Чи не могли б ви пояснити, чому виборцеві вниз? Коли хтось так багато пише, я думаю, що він заслуговує на пояснення!
Сонго

+1 хороша відповідь, не впевнений, чому до цього голосували проти.
pllee

Дивовижна репутація та велика перспектива. Мені також подобається "тільки тому, що це тропа, не означає, що це правильно". Я думаю, що моє питання полягає в тому, що мені зручніше суворіші мови, які (ІМО) різними способами допомагають розвивати ефективність. JavaScript здається дійсно бажанням з не дуже багато вбудованих стримувань і противаг: ви можете робити все, що завгодно, отже, пейзаж там безлад ідіомів та практик. Важко прибити «правильний» спосіб підійти до вашої структури кодування. Хоча я згоден, що для швидких одноразових робочих місць це не викликає особливих проблем.
Том Ожер

1
ІМО, є багато речей, які можна зробити за допомогою великої кількості мотузки, окрім як повісити себе, і ви навчитесь писати надійний код швидше з випадкових самовивісів, які трапляються рідше, коли ви розвиваєте кращі звички, але я не буду робити вигляд, що це для всі або ідеальний кандидат на кожну роботу. Я підозрюю, що чим більше ви дізнаєтесь про це, однак, тим толерантніше ви знайдете його. Я відчуваю, що мені не вистачає половини мозку, коли я намагаюся робити речі мовами без першокласних функцій або предметів, таких гнучких / змінних, як у JS.
Ерік Реппен

4

Інше, що вам не вистачає, це те, що javscript повинен бути сумісним назад. Якщо ви спробуєте ввести синтаксис пакунків, він справді може зламати Інтернет деякими шаленими способами. Це було б погано! Дуг Крокфорд говорив про це в різні моменти, і чому спроби додати його не вдалися.


Це хороший момент. І все ж ActionScript впорався з цим, просто вивівши нову версію. Визначаючи тег скрипту, ви завжди могли вказувати версію JavaScript, тому "зламати" існуючі сайти не слід.
Том Оже

1
На практиці більшість тегів сценаріїв в мережі не мають номера версії. Якщо чесно, я не впевнений у всіх питаннях цього, але я знаю, що люди, які думають над цим матеріалом, вирішили, що це неможливо.
Захарій К

1
@Tom: Adobe також має повний контроль над платформою Flash. Жодна організація не має повного контролю над усіма платформами JS там. Крім того, просто встановити номер версії для сценарію JS у браузері означає, що ви або не підтримуєте старіші браузери, або вам доведеться написати два сценарії. Таким чином, це є проблемою.
Джеремі Хайлер

2

Так, це хитрощі.

Дуже багато людей кажуть, що «прототипи не поступаються класам». Я не згоден, але це питання переваги. Але це навіть не справжня проблема з JavaScript - проблема полягає в тому, що він спочатку був розроблений як швидка та брудна мова сценаріїв для створення таких речей, як анімовані кнопки. Ще в середині 90-х ніхто ніколи не думав, що JavaScript попросять зробити деякі шалені речі, які він робить зараз.


6
Я не погоджуюся, мова JavaScript насправді приголомшлива. Всі проблеми розпочалися разом із визначеним і не сумісним DOM.
Дін Гардінг

2
Що це стосується прототипів?
Ерік Реппен

2

Функції анонімного самовикликання більше схожі на модулі, ніж на класи. Прикро, що за замовчуванням javascript - це запускатись у глобальному масштабі. Комітет, що працює над 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 = {
   //...
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.