<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8266213698782674998</id><updated>2011-08-02T04:46:34.891+03:00</updated><category term='js-test-driver'/><category term='jquery'/><category term='inheritance'/><category term='text fall'/><category term='ооп'/><category term='spket'/><category term='select'/><category term='javascript'/><category term='CSS'/><category term='internet explorer'/><category term='iframe-shim'/><category term='z-index issue'/><category term='effect'/><category term='unit testing'/><category term='tabbed browsing'/><category term='IE'/><category term='oop'/><category term='eclipse'/><category term='наследование'/><category term='code completion'/><category term='iframe-substrate'/><category term='ide'/><category term='browsers'/><category term='colorful tabs'/><title type='text'>Web Development [ru]</title><subtitle type='html'>Полезные советы, на основе практического опыта</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8266213698782674998.post-3959155619682894035</id><published>2010-09-06T18:46:00.008+03:00</published><updated>2010-09-14T13:52:39.961+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='text fall'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='effect'/><title type='text'>"Обрушение" текста при помощи jQuery</title><content type='html'>&lt;div id="text"&gt;
    &lt;p id="text1"&gt;
        Решил вот с jQuery побаловаться...
    &lt;/p&gt;
    &lt;p id="text2"&gt;
        Был когда-то такой вирус, под названием "Cascade" (ссылку можно найти внизу страницы). Он вызывал "осыпание" букв, которые были набраны на экране.
        Попробуем создать похожий эффект. Для этого нам пригодятся пару плагинов: doTimeout и Animation Easing (ссылки на них также можно найти внизу страницы).
        Увидеть "разрушительное" действие данного эффекта можно, если нажать на кнопку, расположенную ниже.
    &lt;/p&gt;
&lt;/div&gt;
&lt;input type="button" id="button" disabled="disabled" value="Красная кнопка" /&gt;



&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;

&lt;hr id="ground" /&gt;

Немного о структуре HTML, использованной в эксперименте. Текст состоит из двух абзацев (p#text1 и p#text2) и заключен в контэйнер (div#text).
В качестве отметки для точки "падения" выбрана горизонтальная линия под кнопкой (hr#ground).

&lt;br /&gt;&lt;br /&gt;

Исходный код с комментариями:

&lt;pre class="code"&gt;

  $(document).ready(&lt;code class="reserved"&gt;function&lt;/code&gt;() {
      &lt;code class="comment"&gt;// Считаем максимальное расстояние до "земли"&lt;/code&gt;
      &lt;code class="reserved"&gt;var&lt;/code&gt; offset = $(&lt;code class="string"&gt;'hr#ground'&lt;/code&gt;)[&lt;code class="number"&gt;0&lt;/code&gt;].offsetTop - $(&lt;code class="string"&gt;'#text'&lt;/code&gt;)[&lt;code class="number"&gt;0&lt;/code&gt;].offsetTop - &lt;code class="number"&gt;15&lt;/code&gt;;
      &lt;code class="comment"&gt;// Подготавливаем токены&lt;/code&gt;
      &lt;code class="reserved"&gt;var&lt;/code&gt; re = /&lt;code class="string"&gt;([а-яёa-z_()&amp;lt;&amp;gt;]+|[:,.?!\-/="])&lt;/code&gt;/gi;
      &lt;code class="reserved"&gt;var&lt;/code&gt; str = &lt;code class="string"&gt;'&amp;lt;span style="position: relative"&amp;gt;$1&amp;lt;/span&amp;gt;'&lt;/code&gt;;
      $(&lt;code class="string"&gt;'#text1'&lt;/code&gt;).html($(&lt;code class="string"&gt;'#text1'&lt;/code&gt;).html().replace(re, str));
      $(&lt;code class="string"&gt;'#text2'&lt;/code&gt;).html($(&lt;code class="string"&gt;'#text2'&lt;/code&gt;).html().replace(re, str));
      &lt;code class="comment"&gt;// Настраиваем контэйнер с текстом&lt;/code&gt;
      $(&lt;code class="string"&gt;'#text'&lt;/code&gt;).css(&lt;code class="string"&gt;'position'&lt;/code&gt;, &lt;code class="string"&gt;'relative'&lt;/code&gt;);
      &lt;code class="comment"&gt;// Устанавливаем обработчик "onclick" на кнопку&lt;/code&gt;
      $(&lt;code class="string"&gt;'#button'&lt;/code&gt;).click(
          &lt;code class="reserved"&gt;function&lt;/code&gt;() {
              &lt;code class="comment"&gt;// Для каждого токена&lt;/code&gt;
              $(&lt;code class="string"&gt;'#text span'&lt;/code&gt;).each(
                  &lt;code class="reserved"&gt;function&lt;/code&gt;(i) {
                      &lt;code class="comment"&gt;// Получаем токен&lt;/code&gt;
                      &lt;code class="reserved"&gt;var&lt;/code&gt; token = $(&lt;code class="reserved"&gt;this&lt;/code&gt;);
                      &lt;code class="comment"&gt;// Расчитываем длительности "падения" слов&lt;/code&gt;
                      &lt;code class="reserved"&gt;var&lt;/code&gt; duration = &lt;code class="js-class"&gt;Math&lt;/code&gt;.random() * &lt;code class="number"&gt;2000&lt;/code&gt;;
                      &lt;code class="comment"&gt;// Устанавливаем таймаут (3 сек для знаков препинания и 0-2 сек для слов)&lt;/code&gt;
                      &lt;code class="reserved"&gt;var&lt;/code&gt; timeout = token.text().search(/&lt;code class="string"&gt;[:,.?!\-/="]&lt;/code&gt;/) != &lt;code class="number"&gt;-1&lt;/code&gt; ? &lt;code class="number"&gt;3000&lt;/code&gt; : duration;
                      &lt;code class="comment"&gt;// Ожидаем таймаут&lt;/code&gt;
                      token.doTimeout( timeout, &lt;code class="reserved"&gt;function&lt;/code&gt;(){
                          &lt;code class="comment"&gt;// Запускаем анимацию "падения" токенов&lt;/code&gt;
                          &lt;code class="reserved"&gt;this&lt;/code&gt;.animate( { top: offset - token[&lt;code class="number"&gt;0&lt;/code&gt;].offsetTop + &lt;code class="string"&gt;'px'&lt;/code&gt; }, {
                              queue: &lt;code class="reserved"&gt;false&lt;/code&gt;,
                              duration: &lt;code class="js-class"&gt;Math&lt;/code&gt;.random() * &lt;code class="number"&gt;200&lt;/code&gt; + &lt;code class="number"&gt;800&lt;/code&gt;,
                              easing: &lt;code class="string"&gt;'bounceEaseOut'&lt;/code&gt;
                          });
                      });
                  }
              )
          }
      )
  });

&lt;/pre&gt;

Данный код работает только с чистым текстом. Можно, конечно, доработать его для "обрушения" сложного HTML-кода, но это уже выходит за рамки моего экспенимента.
&lt;br /&gt;&lt;br /&gt;

&lt;hr /&gt;

&lt;span id="links"&gt;Ссылки по теме:&lt;/span&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Cascade_(computer_virus)"&gt;Cascade&lt;/a&gt; - Тот самый вирус на Википедии&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;  (использовалась версия 1.3.2)&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://plugins.jquery.com/project/ba-jquery-dotimeout-plugin"&gt;doTimeout plugin&lt;/a&gt; (использовалась версия 0.4)&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://plugins.jquery.com/project/AnimEasing"&gt;Animation Easing plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;

&lt;script type="text/javascript" src="http://wolodko.narod.ru/blog_materials/jquery-text-fall/jquery-1.3.2.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://wolodko.narod.ru/blog_materials/jquery-text-fall/jquery.animation.easing.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://wolodko.narod.ru/blog_materials/jquery-text-fall/jquery.ba-do-timeout.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
$(document).ready(function() {
    $('#button')[0].disabled = false;
    // Calculate max offset from the "ground"
    var offset = $('hr#ground')[0].offsetTop - $('#text')[0].offsetTop - 15;
    // Prepare tokens
    var re = /([а-яёa-z_()&lt;&gt;]+|[:,.?!\-/="])/gi;
    var str = '&lt;span style="position: relative"&gt;$1&lt;/span&gt;';
    $('#text1').html($('#text1').html().replace(re, str));
    $('#text2').html($('#text2').html().replace(re, str));
    // Set up text container
    $('#text').css('position', 'relative');
    // Set button 'onclick' handler
    $('#button').click(
        function() {
            // For each token
            $('#text span').each(
                function(i) {
                    // Get token element
                    var token = $(this);
                    // Calculate fall duration for words
                    var duration = Math.random() * 2000;
                    // Set timeout (3 seconds for punctuation marks and 0-2 seconds for words)
                    var timeout = token.text().search(/[:,.?!\-/="]/) != -1 ? 3000 : duration;
                    // Wait timeout
                    token.doTimeout( timeout, function(){
                        // Animate tokens fall
                        this.animate( { top: offset - token[0].offsetTop + 'px' }, {
                            queue: false,
                            duration: Math.random() * 200 + 800,
                            easing: 'bounceEaseOut'
                        });
                    });
                }
            )
        }
    )
});
&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8266213698782674998-3959155619682894035?l=web-dev-ru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/3959155619682894035/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://web-dev-ru.blogspot.com/2010/09/jquery.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/3959155619682894035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/3959155619682894035'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/2010/09/jquery.html' title='&quot;Обрушение&quot; текста при помощи jQuery'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8266213698782674998.post-8085275594414874666</id><published>2010-02-19T17:56:00.007+02:00</published><updated>2010-02-19T18:12:43.675+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='browsers'/><category scheme='http://www.blogger.com/atom/ns#' term='tabbed browsing'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='colorful tabs'/><title type='text'>Цветные вкладки в браузере</title><content type='html'>Некоторые браузеры (например, Internet Explorer 8 или Firefox при помощи &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/1368"&gt;плагина&lt;/a&gt;) могут использовать цветовое кодирование вкладок для группировки взаимосвязанных ресурсов.&lt;br /&gt;
И мне, в связи с этим, подумалось... А что если бы веб-дизайнеры могли самостоятельно задавать фон вкладки для своего сайта?
Например, вот так: &lt;code&gt;&amp;nbsp;&lt;code class="css-select"&gt;title&lt;/code&gt; { &lt;code class="css-style"&gt;background&lt;/code&gt;: &lt;code class="css-value"&gt;...&lt;/code&gt; }&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;
По моему, было бы весьма интересно.
&lt;br /&gt;&lt;br /&gt;
&lt;a href="http://1.bp.blogspot.com/_1ammOv3TXXM/S361UCz821I/AAAAAAAAADY/IUwKvcGM_eE/s1600-h/tabs.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 160px;" src="http://1.bp.blogspot.com/_1ammOv3TXXM/S361UCz821I/AAAAAAAAADY/IUwKvcGM_eE/s400/tabs.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5439984755866917714" /&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
Почему только "favicon"?...
&lt;br /&gt;&lt;br /&gt;
&lt;hr /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8266213698782674998-8085275594414874666?l=web-dev-ru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/8085275594414874666/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://web-dev-ru.blogspot.com/2010/02/blog-post.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/8085275594414874666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/8085275594414874666'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/2010/02/blog-post.html' title='Цветные вкладки в браузере'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_1ammOv3TXXM/S361UCz821I/AAAAAAAAADY/IUwKvcGM_eE/s72-c/tabs.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8266213698782674998.post-410235936771842108</id><published>2010-01-01T00:00:00.015+02:00</published><updated>2010-01-01T12:48:05.298+02:00</updated><title type='text'>С Новым кодом!</title><content type='html'>&lt;br /&gt;&lt;span style="font-family:courier new;font-size:70px;font-weight:bold"&gt;&lt;span style="color:#008000"&gt;2&lt;/span&gt;&lt;span style="color:#ee0000"&gt;0&lt;/span&gt;&lt;span style="color:#0000ff"&gt;1&lt;/span&gt;&lt;span style="color:#ffbb00"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8266213698782674998-410235936771842108?l=web-dev-ru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/410235936771842108/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://web-dev-ru.blogspot.com/2010/01/blog-post.html#comment-form' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/410235936771842108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/410235936771842108'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/2010/01/blog-post.html' title='С Новым кодом!'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8266213698782674998.post-7757156098178531770</id><published>2009-11-26T13:29:00.005+02:00</published><updated>2009-11-27T14:24:02.836+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='ide'/><category scheme='http://www.blogger.com/atom/ns#' term='unit testing'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='js-test-driver'/><title type='text'>Модульное тестирование javascript кода при помощи JsTestDriver</title><content type='html'>&lt;h4&gt;Бочка мёда&lt;/h4&gt;

Хочу порекомендовать &lt;a href="http://code.google.com/p/js-test-driver/"&gt;JsTestDriver&lt;/a&gt; - великолепный фрэймворк для модульного тестирования (unit testing) javascript кода от ребят из Google.
Он позволяет в считанные доли секунды протестировать javascript-код &lt;u&gt;одновременно&lt;/u&gt; на &lt;u&gt;любом&lt;/u&gt; (ну, почти любом) количестве &lt;u&gt;любых&lt;/u&gt; браузеров
с &lt;u&gt;любых&lt;/u&gt; компьютеров и платформ. Впечатляет, не правда ли?
&lt;br /&gt;&lt;br /&gt;

Идея JsTestDriver проста, как всё гениальное (картинка взята с оф. сайта):

&lt;br /&gt;&lt;br /&gt;
&lt;img src="http://wolodko.narod.ru/blog_materials/js-test-driver/Overview.png" style="border:0"&gt;
&lt;br /&gt;

Запускается небольшой веб-сервер, причем не обязательно его запускать на локальной машине.
К нему, как и к обычному веб-серверу, используя определённый URL (например, http://localhost:4224/capture), коннектятся необходимые для тестирования браузеры,
которые могут находится на &lt;u&gt;любом&lt;/u&gt; компьютере (и, соответственно, платформе), с которого доступен сервер.
Таким образом, можно будет &lt;u&gt;одновременно&lt;/u&gt; тестировать код на Safari под Mac OS, Internet Explorer под Windows и, например, Firefox под Linux.

&lt;br /&gt;&lt;br /&gt;

Далее происходит основная магия.&lt;br /&gt;
Браузеры (slaves в терминологии JsTestDriver) начинают периодически опрашивать сервер (при помощи AJAX) в ожидании новых задач (тестов).
И, как только задание будет получено, браузеры загрузят необходимые скрипты, выполнят тестовые функции (test cases) и вернут на сервер результаты выполнения.
Управление же сервером происходит при помощи клиентского приложения, которое легко интегрируется как с IDE разработчика, так и с системами автоматической сборки проектов (Ant, Team City, Phing и т.п.).

&lt;br /&gt;&lt;br /&gt;

Однако, разработчику важна не столько вся эта кухня, сколько возможность иметь под рукой удобный инструмент для лёгкого и быстрого запуска модульных тестов и отслеживания результатов.
В этом нам поможет &lt;a href="http://code.google.com/p/js-test-driver/wiki/UsingTheEclipsePlugin"&gt;JsTestDriver плагин для Eclipse&lt;/a&gt; (аналогичный плагин есть так же и для IntelliJ IDEA).

&lt;br /&gt;&lt;br /&gt;
&lt;img src="http://wolodko.narod.ru/blog_materials/js-test-driver/eclipse.png" style="border:0"&gt;
&lt;br /&gt;&lt;br /&gt;

Не вдаваясь в подробности опишу лишь основные фичи этого плагина:
&lt;ul&gt;
    &lt;li&gt;Минимум настроек: только номер порта для сервера и пути к файлам браузеров (Firefox, Chrome, Safari, Internet Explorer и Opera) на локальном компьютере&lt;/li&gt;
    &lt;li&gt;Запуск сервера и браузеров для тестирования прямо из IDE&lt;/li&gt;
    &lt;li&gt;Простейший конфигурационный файл для запуска тестов (прописывается только URL тестового сервера и список необходимых javascript-файлов)&lt;/li&gt;
    &lt;li&gt;Ручной запуск модульных тестов через меню Run&lt;/li&gt;
    &lt;li&gt;Автоматический запуск модульных тестов при каждом изменении javascript-файлов&lt;/li&gt;
    &lt;li&gt;Наглядное отображение результатов тестирования прямо в IDE (на каком браузере под какой платформой в каком тест-кейсе произошла ошибка)&lt;/li&gt;
&lt;/ul&gt;

В общем, установка и настройка JsTestDriver не вызывают никаких особых проблем (всё очень подробно описано на оф. сайте), а уж использование приносит только сплошное удовольствие.
Правда, если быть честным, для этого пришлось немного (совсем чуть-чуть :) "поработать напильником"...

&lt;h4&gt;Капля дёгтя&lt;/h4&gt;

Дело в том, что текущая версия (1.2 для сервера и 1.0.6 для плагина) немного недоработана (уверен, что это не надолго).
В частности, если в каком либо тестируемом js-файле будет синтаксическая ошибка (или иная ошибка, возникающая при исполнении этого файла), то в результатах тестов это никак не отражается.
Кроме того, наблюдается некоторая глючность Opera при исполнении тестов.

&lt;h4&gt;Лекарство&lt;/h4&gt;

Для решения проблемы пришлось переписать один метод по загрузке скриптов и добавить "системный" тест-кейс,
который будет отражать ошибки, произошедшие до начала выполнения пользовательских тест-кейсов (см. &lt;i&gt;runner-fix.js&lt;/i&gt;).
Ну и, в дополнение, мне показалось уместным добавить ещё две вещи:
&lt;ol&gt;
  &lt;li&gt;Обновление тестовой страницы после выполнения тестов, чтобы исключить возможность влияния предыдущего выполнения тестов на последующие&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;assertFail&lt;/b&gt;( [expectedErrorMessage], caseWrapper ) - функция, которая позволяет протестировать случаи, когда должна происходить ошибка.
  Пример использования:
  &lt;pre class="code"&gt;
  &lt;code class="reserved"&gt;function&lt;/code&gt; doSomething() {
      &lt;code class="reserved"&gt;throw&lt;/code&gt; &lt;code class="reserved"&gt;new&lt;/code&gt; &lt;code class="js-class"&gt;Error&lt;/code&gt;( &lt;code class="string"&gt;'Some error'&lt;/code&gt; );
  }
  ...

  &lt;code class="comment"&gt;// Test case&lt;/code&gt;
  &lt;b&gt;assertFail&lt;/b&gt;( &lt;code class="string"&gt;'Some error'&lt;/code&gt;, &lt;code class="reserved"&gt;function&lt;/code&gt;(){ doSomething() } );
  &lt;code class="comment"&gt;// true&lt;/code&gt;
  &lt;/pre&gt;
    &lt;/li&gt;
&lt;/ol&gt;

Чтобы внедрить эти изменения в JsTestDriver нужно выполнить следующие шаги:
&lt;ol&gt;
    &lt;li&gt;Загружаем &lt;a href="http://wolodko.narod.ru/blog_materials/js-test-driver/runner-fix.zip"&gt;архив&lt;/a&gt; (содержит три файла: &lt;i&gt;runner-fix.js&lt;/i&gt;, &lt;i&gt;Runnerquirks.html&lt;/i&gt;, &lt;i&gt;Runnerstrict.html&lt;/i&gt;)&lt;/li&gt;
    &lt;li&gt;Находим &lt;i&gt;JsTestDriver.jar&lt;/i&gt; из которого запускается сервер. Для плагина к Eclipse он находится где-то в папке &lt;i&gt;configuration&lt;/i&gt;.
        В частности у меня, вот тут:&lt;br /&gt;
        &lt;i&gt;c:\Program Files\Eclipse\Galileo\configuration\org.eclipse.osgi\bundles\929\1\.cp\lib\&lt;/i&gt;&lt;/li&gt;
    &lt;li&gt;Открываем &lt;i&gt;JsTestDriver.jar&lt;/i&gt; как обычный zip-архив&lt;/li&gt;
    &lt;li&gt;Заходим в папку &lt;i&gt;JsTestDriver.jar\com\google\jstestdriver\javascript\&lt;/i&gt;&lt;/li&gt;
    &lt;li&gt;Копируем туда файлы из &lt;i&gt;runner-fix.zip&lt;/i&gt;&lt;/li&gt;
    &lt;li&gt;Запускаем JsTestDriver (вручную или через Eclipse плагин) и наслаждаемся :)&lt;/li&gt;
&lt;/ol&gt;

Подробнее о том, как собственно устанавливать, настраивать и использовать сервер или плагин, или писать тест-кейсы, смотрите по ссылкам, приведенным ниже.
Там же можно найти общую информацию о тестировании вообще и о модульном тестировании в частности.

&lt;br /&gt;&lt;br /&gt;

На последок хочется отметить, что разработчики JsTestDriver надеятся, что javascript сообщество объединится
в поддержку этого фрэймворка, как единого движка для запуска тестов (наподобие JUnit в Java).
Что, совместно с использование различных &lt;a href="http://code.google.com/p/js-test-driver/wiki/XUnitCompatibility"&gt;расширений&lt;/a&gt;
(например, для &lt;a href="http://developer.yahoo.com/yui/yuitest/"&gt;YUI Test&lt;/a&gt; или &lt;a href="http://docs.jquery.com/QUnit"&gt;QUnit&lt;/a&gt;),
сделает процесс модульного тестирования javascript максимально продуктивным.

&lt;br /&gt;&lt;br /&gt;

Что ж, кажется &lt;a href="http://code.google.com/p/js-test-driver/"&gt;JsTestDriver&lt;/a&gt; этого вполне достоин.

&lt;br /&gt;&lt;br /&gt;

&lt;hr /&gt;
&lt;span id="links"&gt;Ссылки по теме:&lt;/span&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://code.google.com/p/js-test-driver/"&gt;JsTestDriver&lt;/a&gt; - сайт проекта&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://misko.hevery.com/2009/05/22/yet-another-javascript-testing-framework/"&gt;
        Yet Another JavaScript Testing Framework&lt;/a&gt;
        - статья от авторов JsTestDriver (Mi&amp;#353;ko Hevery &amp;amp; Jeremie Lenfant-engelmann)&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://googletesting.blogspot.com/2009/08/super-fast-js-testing.html"&gt;
            Super Fast JS Testing
        &lt;/a&gt; - статья от автора плагина для Eclipse (Shyam Seshadri)&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://googletesting.blogspot.com/2009/07/software-testing-categorization.html"&gt;Software Testing Categorization&lt;/a&gt;
        (перевод &lt;a href="http://habrahabr.ru/blogs/testing/64874/"&gt;на русский&lt;/a&gt;)&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://misko.hevery.com/2008/11/17/unified-theory-of-bugs/"&gt;My Unified Theory of Bugs&lt;/a&gt;
        (перевод &lt;a href="http://habrahabr.ru/blogs/testing/65062/"&gt;на русский&lt;/a&gt;)&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://misko.hevery.com/2009/05/07/configure-your-ide-to-run-your-tests-automatically/"&gt;Configure your IDE to run your tests automatically&lt;/a&gt;
        (перевод &lt;a href="http://habrahabr.ru/blogs/testing/64737/"&gt;на русский&lt;/a&gt;)&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://testdrivendeveloper.com/2009/08/07/WhenNOTToUseTDD.aspx"&gt;When NOT to use TDD&lt;/a&gt; (Test Driven Development)&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://ru.wikipedia.org/wiki/%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D1%82%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5"&gt;Модульное тестирование&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8266213698782674998-7757156098178531770?l=web-dev-ru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/7757156098178531770/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://web-dev-ru.blogspot.com/2009/11/javascript-jstestdriver.html#comment-form' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/7757156098178531770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/7757156098178531770'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/2009/11/javascript-jstestdriver.html' title='Модульное тестирование javascript кода при помощи JsTestDriver'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8266213698782674998.post-7677931952285806446</id><published>2009-07-31T18:43:00.003+03:00</published><updated>2009-08-01T09:06:31.805+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='ide'/><category scheme='http://www.blogger.com/atom/ns#' term='spket'/><category scheme='http://www.blogger.com/atom/ns#' term='code completion'/><title type='text'>Тюнинг code completion в Spket IDE</title><content type='html'>&lt;a href="http://spket.com/"&gt;Spket IDE&lt;/a&gt; — отличная среда для современной сложной JavaScript-разработки
(подробнее по ссылкам ниже [&lt;a href="#links"&gt;^&lt;/a&gt;]), однако, по непонятным мне причинам,
при работе на кастомном профайле (в настройках Эклипса Spket/JavaScript Profiles)
в code completion отсутствуют некоторые свойства стандартных объектов (например, методы match, replace, search и split для String).
Причем, добавить их через подключение js-файла в кастомный JavaScript-профайл тоже не получается.
&lt;br /&gt;&lt;br /&gt;

Решить проблему можно следующим образом (на примере плагина под Эклипс):
&lt;ol&gt;
    &lt;li&gt;Выходим из Эклипса (если он запущен)&lt;/li&gt;
    &lt;li&gt;Заходим в папку &lt;i&gt;plugins&lt;/i&gt; Эклипса&lt;/li&gt;
    &lt;li&gt;При помощи любого файлового менеджера (FAR, Total Commander) открываем архивный файл &lt;i&gt;com.spket.js_Х.Х.Х.jar&lt;/i&gt; (где X.X.X — ваша версия плагина Spket IDE)&lt;/li&gt;
    &lt;li&gt;Редактируем файл &lt;i&gt;config/core.js&lt;/i&gt;, добавляя недостающие свойства&lt;/li&gt;
&lt;/ol&gt;

Синтаксис там очень простой:
&lt;style&gt;code.comment { color:#666 }&lt;/style&gt;
&lt;pre class="code"&gt;
&lt;code class="comment"&gt;...

class Number {
    static var MAX_VALUE:Number;
    static var MIN_VALUE:Number;
    ...
}

class String {
    var length:Number;

    static function fromCharCode(... chars):String;

    function String(string:String);
    function charAt(index:Number):String;
    ...&lt;/code&gt;

    &lt;code class="reserved"&gt;function&lt;/code&gt; match(searchValue:&lt;code class="js-class"&gt;RegExp&lt;/code&gt;_or_&lt;code class="js-class"&gt;String&lt;/code&gt;):&lt;code class="js-class"&gt;Array&lt;/code&gt;;
    &lt;code class="reserved"&gt;function&lt;/code&gt; replace(searchValue:&lt;code class="js-class"&gt;RegExp&lt;/code&gt;_or_&lt;code class="js-class"&gt;String&lt;/code&gt;, replaceValue:&lt;code class="js-class"&gt;String&lt;/code&gt;_or_&lt;code class="js-class"&gt;Function&lt;/code&gt;):&lt;code class="js-class"&gt;String&lt;/code&gt;;
    &lt;code class="reserved"&gt;function&lt;/code&gt; search(searchValue:&lt;code class="js-class"&gt;RegExp&lt;/code&gt;_or_&lt;code class="js-class"&gt;String&lt;/code&gt;):&lt;code class="js-class"&gt;Number&lt;/code&gt;;
    &lt;code class="reserved"&gt;function&lt;/code&gt; split(separator:&lt;code class="js-class"&gt;String&lt;/code&gt;, limit:&lt;code class="js-class"&gt;Number&lt;/code&gt;):&lt;code class="js-class"&gt;Array&lt;/code&gt;;
&lt;code class="comment"&gt;}

class RegExp {
    function RegExp(pattern:String, flags:String);
    ...
}

...&lt;/code&gt;
&lt;/pre&gt;

так что проблем особых возникнуть не должно. После перезаргузки Эклипса новые свойства (методы) станут доступны для code completion.
&lt;br /&gt;&lt;br /&gt;

&lt;hr /&gt;
&lt;span id="links"&gt;Ссылки по теме:&lt;/span&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://spket.com/javascript-editor.html"&gt;Spket IDE - JavaScript Editor&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.artlebedev.ru/tools/technogrette/soft/eclipse-spket/"&gt;Eclipse: редактирование JavaScript в Spket IDE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8266213698782674998-7677931952285806446?l=web-dev-ru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/7677931952285806446/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://web-dev-ru.blogspot.com/2009/07/code-completion-spket-ide.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/7677931952285806446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/7677931952285806446'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/2009/07/code-completion-spket-ide.html' title='Тюнинг code completion в Spket IDE'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8266213698782674998.post-6830647852583320365</id><published>2009-06-08T19:58:00.004+03:00</published><updated>2009-08-01T09:09:50.841+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='z-index issue'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='iframe-shim'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='iframe-substrate'/><category scheme='http://www.blogger.com/atom/ns#' term='IE'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='select'/><title type='text'>ie-iframe-substrate 1.0.2</title><content type='html'>Новая версия &lt;a href="http://web-dev-ru.blogspot.com/2009/03/css-select-ie.html"&gt;"IFRAME-подложки"&lt;/a&gt; доступна для скачивания:
&lt;strong&gt;&lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/ie-iframe-substrate.1.0.2.css" type="text/css"&gt;ie-iframe-substrate.1.0.2.css&lt;/a&gt;&lt;/strong&gt; (~1.3 KB).
&lt;br /&gt;&lt;br /&gt;
Изменения:
&lt;ol&gt;
    &lt;li&gt;Исправлен баг в IE 5.5&lt;/li&gt;
&lt;/ol&gt;

Исходники: &lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/ie-iframe-substrate.1.0.2.src.ru.css" type="text/css"&gt;ie-iframe-substrate.1.0.2.src.ru.css&lt;/a&gt; (~4.5 KB)
&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;hr /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8266213698782674998-6830647852583320365?l=web-dev-ru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/6830647852583320365/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://web-dev-ru.blogspot.com/2009/06/ie-iframe-substrate-102.html#comment-form' title='Комментарии: 3'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/6830647852583320365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/6830647852583320365'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/2009/06/ie-iframe-substrate-102.html' title='ie-iframe-substrate 1.0.2'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8266213698782674998.post-5346133603548153567</id><published>2009-04-10T19:05:00.003+03:00</published><updated>2009-04-10T19:27:47.168+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='z-index issue'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='iframe-shim'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='iframe-substrate'/><category scheme='http://www.blogger.com/atom/ns#' term='IE'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='select'/><title type='text'>ie-iframe-substrate 1.0.1</title><content type='html'>Новая версия &lt;a href="http://web-dev-ru.blogspot.com/2009/03/css-select-ie.html"&gt;"IFRAME-подложки"&lt;/a&gt; доступна для скачивания:
&lt;strong&gt;&lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/ie-iframe-substrate.1.0.1.css" type="text/css"&gt;ie-iframe-substrate.1.0.1.css&lt;/a&gt;&lt;/strong&gt; (~1.3 KB).
&lt;br /&gt;&lt;br /&gt;
Изменения:
&lt;ol&gt;
    &lt;li&gt;Убран звук "клика" при вставке IFRAME-а&lt;/li&gt;
    &lt;li&gt;Улучшено быстродействие для страниц, на которых нет SELECT-ов&lt;/li&gt;
    &lt;li&gt;Исправлен баг&lt;/li&gt;
&lt;/ol&gt;

Протестировать можно тут: &lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/test1.htm"&gt;тест 1&lt;/a&gt;, &lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/test2.htm"&gt;тест 2&lt;/a&gt;, &lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/test3.htm"&gt;тест 3&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
Исходники: &lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/ie-iframe-substrate.1.0.1.src.ru.css" type="text/css"&gt;ie-iframe-substrate.1.0.1.src.ru.css&lt;/a&gt; (~4.5 KB)
&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;hr /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8266213698782674998-5346133603548153567?l=web-dev-ru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/5346133603548153567/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://web-dev-ru.blogspot.com/2009/04/ie-iframe-substrate-101.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/5346133603548153567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/5346133603548153567'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/2009/04/ie-iframe-substrate-101.html' title='ie-iframe-substrate 1.0.1'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8266213698782674998.post-8337471030208513699</id><published>2009-03-26T19:46:00.033+02:00</published><updated>2009-06-08T20:03:57.870+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='z-index issue'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='iframe-shim'/><category scheme='http://www.blogger.com/atom/ns#' term='internet explorer'/><category scheme='http://www.blogger.com/atom/ns#' term='iframe-substrate'/><category scheme='http://www.blogger.com/atom/ns#' term='IE'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='select'/><title type='text'>Универсальное решение для борьбы с «просвечивающими» SELECT-ами в Internet Explorer</title><content type='html'>&lt;br /&gt;
UPD [08.06.2009] &lt;a href="http://web-dev-ru.blogspot.com/2009/06/ie-iframe-substrate-102.html"&gt;ie-iframe-substrate 1.0.2&lt;/a&gt;&lt;br /&gt;
UPD [10.04.2009] &lt;a href="http://web-dev-ru.blogspot.com/2009/04/ie-iframe-substrate-101.html"&gt;ie-iframe-substrate 1.0.1&lt;/a&gt;

&lt;h4&gt;Введение&lt;/h4&gt;

Как известно, Internet Explorer версий 5.5 и 6.0 содержит ошибку (aka "z-index issue"), которая заключается в том, что элементы SELECT "пробивают" любые другие элементы (например, позиционированные DIV-ы), размещённые над ними.
&lt;br /&gt;&lt;br /&gt;

&lt;a href="http://2.bp.blogspot.com/_1ammOv3TXXM/ScvFSn7K-_I/AAAAAAAAACQ/lAJo0kLxj78/s1600-h/div_over_select_IE6.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 306px; height: 101px;" src="http://2.bp.blogspot.com/_1ammOv3TXXM/ScvFSn7K-_I/AAAAAAAAACQ/lAJo0kLxj78/s400/div_over_select_IE6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5317560708786486258" /&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;

Единственный элемент, с которым этого не происходит &amp;mdash; IFRAME. Именно на использовании его в качестве "прокладки" и основываются все методы устранения описанной выше ошибки IE [&lt;a href="#links"&gt;^&lt;/a&gt;]. Как правило, в них применяется один из двух вариантов. Либо, IFRAME вставляется внутрь (первым потомком) необходимого элемента, делается прозрачным, и стиль &lt;code class="css-style"&gt;z-index&lt;/code&gt; устанавливается в &lt;code class="number"&gt;-1&lt;/code&gt;. Либо, IFRAME добавляется в DOM, позиционируется непосредственно под необходимым элементом и делается равным ему по размеру.
&lt;br /&gt;&lt;br /&gt;
При кажущейся простоте, у первого варианта два серьёзных недостатка. Во-первых, изменяются "внутренности" элемента, что может привести к конфликтам при динамической обработке контента javascript-ом. Во-вторых, "прикрыть", например, элементы с &lt;code&gt;&lt;code class="css-style"&gt;overflow&lt;/code&gt;:&lt;code class="css-value"&gt;auto&lt;/code&gt;&lt;/code&gt; или &lt;code&gt;&lt;code class="css-style"&gt;overflow&lt;/code&gt;:&lt;code class="css-value"&gt;scroll&lt;/code&gt;&lt;/code&gt; весьма проблематично. Второй вариант не имеет данных недостатков, т.к. IFRAME ни коим образом не связан с элементом, который он "прикрывает". Однако, существует проблема изменения позиции или размера элемента, которым IFRAME постоянно должен соответствовать.
&lt;br /&gt;&lt;br /&gt;
В описываемом ниже решении для борьбы с «просвечивающими» SELECT-ами используется второй вариант размещения IFRAME.


&lt;h4&gt;"IFRAME-подложка"&lt;/h4&gt;

Теперь собственно о главном. Предлагаемое решение основано на применении &lt;a href="http://msdn.microsoft.com/en-us/library/ms537634.aspx"&gt;javascript-expressions&lt;/a&gt; в CSS стилях. Используется оно следующим образом:
&lt;ol&gt;
&lt;li&gt;Скачиваем последнюю версию &lt;strong&gt;&lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/ie-iframe-substrate.1.0.1.css" type="text/css"&gt;ie-iframe-substrate.css&lt;/a&gt;&lt;/strong&gt; (~1.3 KB)&lt;/li&gt;
&lt;li&gt;Подключаем его на страницу при помощи тэга LINK или в любой CSS-файл при помощи &lt;code class="css-at"&gt;@import&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Прямо в этом же файле переписываем селекторы для элементов, которым необходима "подложка" (обязательно с &lt;code class="css-select"&gt;* html&lt;/code&gt;).&lt;br /&gt;
    Например: &lt;code&gt;&lt;code class="css-select"&gt;* html div&lt;/code&gt;.&lt;code class="css-class"&gt;some-layer&lt;/code&gt;, &lt;code class="css-select"&gt;* html&lt;/code&gt; #&lt;code class="css-class"&gt;someLayer&lt;/code&gt; {...}&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

Всё.
&lt;br /&gt;&lt;br /&gt;
Протестировать можно вот на этих страницах: &lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/test1.htm"&gt;тест 1&lt;/a&gt;, &lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/test2.htm"&gt;тест 2&lt;/a&gt;, &lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/test3.htm"&gt;тест 3&lt;/a&gt;.&lt;br /&gt;
К сведению: протестированный для сравнения &lt;a href="http://docs.jquery.com/Plugins/bgiframe"&gt;bgIframe&lt;/a&gt; (плагин для jQuery) часть приведённых выше тестов пройти не смог.
&lt;br /&gt;&lt;br /&gt;

Некоторые ограничения и особенности:
&lt;ol&gt;
&lt;li&gt;"Прикрываемый" элемент не должен использовать стиль &lt;code class="css-style"&gt;behavior&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;У каждого "прикрываемого" элемента создаётся и используется свойство "_i" (&lt;code&gt;element._i&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Для "IFRAME-подложки" используется CSS-класс "ie-substrate" (&lt;code class="css-select"&gt;iframe&lt;/code&gt;.&lt;code class="css-class"&gt;ie-substrate&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

Как это работает (в версии 1.0.0):

&lt;pre class="code"&gt;

&lt;code class="js-doc"&gt;/**
 * Селектор слоёв (позиционированных элементов),
 * которым нужно создать "IFRAME-подложку".
 */&lt;/code&gt;
&lt;code class="css-select"&gt;* html div&lt;/code&gt;.&lt;code class="css-class"&gt;layer&lt;/code&gt; { &lt;code class="comment"&gt;/* Скрываем от IE 7+ в "standards-compliant" режиме */&lt;/code&gt;
    &lt;code class="css-style"&gt;behavior&lt;/code&gt;: &lt;code class="css-expr"&gt;expression(&lt;/code&gt;&lt;code class="css-expression"&gt; 
        &lt;code class="comment"&gt;/* Если документ загружен и распаршен */&lt;/code&gt;
        document.readyState==&lt;code class="string"&gt;'complete'&lt;/code&gt; ? (
            &lt;code class="comment"&gt;/* и браузер не IE 7+ (в "quirks" режиме) */&lt;/code&gt;
            parseFloat(navigator.appVersion.split(&lt;code class="string"&gt;'MSIE'&lt;/code&gt;)[&lt;code class="number"&gt;1&lt;/code&gt;])&lt;&lt;code class="number"&gt;7&lt;/code&gt;
            &lt;code class="comment"&gt;/* и "IFRAME-подложка" ещё не создана */&lt;/code&gt;
            &amp;&amp; &lt;code class="reserved"&gt;this&lt;/code&gt;.iframe==&lt;code class="reserved"&gt;null&lt;/code&gt; ? (
                &lt;code class="comment"&gt;/* создаём IFRAME и вставляем его прямо перед данным элементом (слоем) */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.iframe = &lt;code class="reserved"&gt;this&lt;/code&gt;.parentNode.insertBefore(
                    document.createElement(&lt;code class="string"&gt;'iframe'&lt;/code&gt;), &lt;code class="reserved"&gt;this&lt;/code&gt;
                ),
                &lt;code class="comment"&gt;/* устанавливаем свойство "src" (важно для HTTPS соединения) */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.iframe.src = &lt;code class="string"&gt;'javascript:false'&lt;/code&gt;,
                &lt;code class="comment"&gt;/* устанавливаем свойство "id" (для функции обновления) */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.iframe.id = &lt;code class="string"&gt;'_ie_sub'&lt;/code&gt; + &lt;code class="reserved"&gt;new&lt;/code&gt; &lt;code class="js-class"&gt;Date&lt;/code&gt;().valueOf(),
                &lt;code class="comment"&gt;/* устанавливаем свойство "layer" для ссылки на данный слой */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.iframe.layer = &lt;code class="reserved"&gt;this&lt;/code&gt;,
                &lt;code class="comment"&gt;/* создаём функцию обновления (важно для IE 6.0) */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.iframe.func = &lt;code class="reserved"&gt;new&lt;/code&gt; &lt;code class="js-class"&gt;Function&lt;/code&gt;(
                    &lt;code class="string"&gt;"var iframe = document.getElementById('"&lt;/code&gt; + &lt;code class="reserved"&gt;this&lt;/code&gt;.iframe.id +
                    &lt;code class="string"&gt;"'); iframe.allowTransparency=true; iframe.allowTransparency=false;"&lt;/code&gt;
                ),
                &lt;code class="comment"&gt;/* устанавливаем соответствующее имя класса */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.iframe.className = &lt;code class="string"&gt;'ie-substrate'&lt;/code&gt;,
                &lt;code class="comment"&gt;/* сбрасываем ссылку на IFRAME и устанавливаем флажок */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.iframe = &lt;code class="reserved"&gt;true&lt;/code&gt;,
                &lt;code class="comment"&gt;/* отключаем "behavior" для данного элемента */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.style.behavior = &lt;code class="string"&gt;'none'&lt;/code&gt;
            &lt;code class="comment"&gt;/* иначе - отключаем "behavior" для данного элемента */&lt;/code&gt;
            ) : &lt;code class="reserved"&gt;this&lt;/code&gt;.style.behavior = &lt;code class="string"&gt;'none'&lt;/code&gt;
        &lt;code class="comment"&gt;/* иначе - ничего не делаем */&lt;/code&gt;
        ) : &lt;code class="reserved"&gt;null&lt;/code&gt;
    &lt;/code&gt;&lt;code class="css-expr"&gt;)&lt;/code&gt;;
}

&lt;code class="js-doc"&gt;/**
 * Стили для "IFRAME-подложки"
 */&lt;/code&gt;
&lt;code class="css-select"&gt;iframe&lt;/code&gt;.&lt;code class="css-class"&gt;ie-substrate&lt;/code&gt; {
    &lt;code class="css-style"&gt;position&lt;/code&gt;: &lt;code class="css-value"&gt;absolute&lt;/code&gt;;
    &lt;code class="comment"&gt;/* Делаем IFRAME прозрачным */&lt;/code&gt;
    &lt;code class="css-style"&gt;filter&lt;/code&gt;: &lt;code class="css-value"&gt;Mask()&lt;/code&gt;;

    &lt;code class="comment"&gt;/* Отслеживаем позицию и размеры "прикрываемого" слоя */&lt;/code&gt;
    &lt;code class="css-style"&gt;behavior&lt;/code&gt;: &lt;code class="css-expr"&gt;expression(&lt;/code&gt;&lt;code class="css-expression"&gt; 
        &lt;code class="comment"&gt;/* Если IFRAME в DOM-е (т.е. не удален) */&lt;/code&gt;
        &lt;code class="reserved"&gt;this&lt;/code&gt;.parentNode ? (
           &lt;code class="comment"&gt;/* Если "прикрываемый" слой в DOM-е (т.е. не удален) */&lt;/code&gt;
            &lt;code class="reserved"&gt;this&lt;/code&gt;.layer.parentNode ? (
                &lt;code class="comment"&gt;/* и IFRAME вставлен в DOM-е перед "прикрываемым" слоем */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.nextSibling==&lt;code class="reserved"&gt;this&lt;/code&gt;.layer ? (
                    &lt;code class="comment"&gt;/* перехватываем свойства "прикрываемого" слоя */&lt;/code&gt;
                    &lt;code class="reserved"&gt;this&lt;/code&gt;.style.pixelWidth = &lt;code class="reserved"&gt;this&lt;/code&gt;.layer.offsetWidth,
                    &lt;code class="reserved"&gt;this&lt;/code&gt;.style.pixelHeight = &lt;code class="reserved"&gt;this&lt;/code&gt;.layer.offsetHeight,
                    &lt;code class="reserved"&gt;this&lt;/code&gt;.style.pixelLeft = &lt;code class="reserved"&gt;this&lt;/code&gt;.layer.offsetLeft,
                    &lt;code class="reserved"&gt;this&lt;/code&gt;.style.pixelTop = &lt;code class="reserved"&gt;this&lt;/code&gt;.layer.offsetTop,
                    &lt;code class="reserved"&gt;this&lt;/code&gt;.offsetTop&gt;&lt;code class="number"&gt;0&lt;/code&gt; ? ( &lt;code class="comment"&gt;/* только если IFRAME виден */&lt;/code&gt;
                        &lt;code class="reserved"&gt;this&lt;/code&gt;.style.zIndex = &lt;code class="reserved"&gt;this&lt;/code&gt;.layer.currentStyle.zIndex,
                        &lt;code class="reserved"&gt;this&lt;/code&gt;.style.visibility = &lt;code class="reserved"&gt;this&lt;/code&gt;.layer.currentStyle.visibility,
                        &lt;code class="reserved"&gt;this&lt;/code&gt;.style.display = &lt;code class="reserved"&gt;this&lt;/code&gt;.layer.currentStyle.display
                    ) : &lt;code class="reserved"&gt;null&lt;/code&gt;
                &lt;code class="comment"&gt;/* иначе */&lt;/code&gt;
                ) : (
                    &lt;code class="comment"&gt;/* вставляем IFRAME перед "прикрываемым" слоем в DOM-е */&lt;/code&gt;
                    &lt;code class="reserved"&gt;this&lt;/code&gt;.layer.parentNode.insertBefore(&lt;code class="reserved"&gt;this&lt;/code&gt;, &lt;code class="reserved"&gt;this&lt;/code&gt;.layer)
                )
            &lt;code class="comment"&gt;/* иначе */&lt;/code&gt;
            ) : (
                &lt;code class="comment"&gt;/* удаляем IFRAME */&lt;/code&gt;
                &lt;code class="reserved"&gt;this&lt;/code&gt;.removeNode(&lt;code class="reserved"&gt;true&lt;/code&gt;)
            )
        &lt;code class="comment"&gt;/* иначе - ничего не делаем */&lt;/code&gt;
        ) : &lt;code class="reserved"&gt;null&lt;/code&gt;
    &lt;/code&gt;&lt;code class="css-expr"&gt;)&lt;/code&gt;;

    &lt;code class="comment"&gt;/* Обновляем IFRAME-ы периодически, чтобы решить проблему в IE 6.0
     * (SELECT-ы всё ещё могут перекрывать слои после скроллинга). */&lt;/code&gt;
    &lt;code class="css-style"&gt;refresh&lt;/code&gt;: &lt;code class="css-expr"&gt;e\xpression(&lt;/code&gt;&lt;code class="css-expression"&gt; &lt;code class="comment"&gt;/* Скрываем от IE 5.5 */&lt;/code&gt;
        &lt;code class="comment"&gt;/* Если IFRAME виден */&lt;/code&gt;
        &lt;code class="reserved"&gt;this&lt;/code&gt;.offsetTop&gt;&lt;code class="number"&gt;0&lt;/code&gt; ? (
            &lt;code class="comment"&gt;/* включить обновление */&lt;/code&gt;
            &lt;code class="reserved"&gt;this&lt;/code&gt;.timer ? &lt;code class="reserved"&gt;null&lt;/code&gt; : &lt;code class="reserved"&gt;this&lt;/code&gt;.timer = window.setInterval(&lt;code class="reserved"&gt;this&lt;/code&gt;.func, &lt;code class="number"&gt;300&lt;/code&gt;)
        &lt;code class="comment"&gt;/* иначе */&lt;/code&gt;
        ) : (
            &lt;code class="comment"&gt;/* выключить обновление */&lt;/code&gt;
            &lt;code class="reserved"&gt;this&lt;/code&gt;.timer ? &lt;code class="reserved"&gt;this&lt;/code&gt;.timer = window.clearInterval(&lt;code class="reserved"&gt;this&lt;/code&gt;.timer) : &lt;code class="reserved"&gt;null&lt;/code&gt;
        )
    &lt;/code&gt;&lt;code class="css-expr"&gt;)&lt;/code&gt;;
}

&lt;/pre&gt;

[Скачать этот код в виде файла: &lt;a href="http://wolodko.narod.ru/blog_materials/ie-substrate/ie-iframe-substrate.1.0.0.src.ru.css" type="text/css" charset="windows-1251"&gt;ie-iframe-substrate.1.0.0.src.ru.css&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;

Достоинства:
&lt;ol&gt;
&lt;li&gt;Простота и прозрачность в использовании&lt;/li&gt;
&lt;li&gt;Корректно работает с любыми элементами как в "standards-compliant", так и в "quirks" режимах, а также при любых динамических манипуляциях с "прикрытыми" элементами&lt;/li&gt;
&lt;li&gt;Не требует внесения изменений в ваш CSS- или javascript-код&lt;/li&gt;
&lt;li&gt;Небольшой объём библиотечного файла (всего 1 KB без комментариев)&lt;/li&gt;
&lt;li&gt;Нет привязки к каким-либо фрэймворкам&lt;/li&gt;
&lt;li&gt;Не оказывает никакого влияния на другие браузеры (в том числе IE 7+)&lt;/li&gt;
&lt;li&gt;Легко отключается не оставляя следов (например, при отказе от поддержки IE 6 или от использования SELECT-ов)&lt;/li&gt;
&lt;/ol&gt;

Недостатки:
&lt;ol&gt;
&lt;li&gt;Снижение быстродействия при увеличении количества "прикрытых" элементов&lt;/li&gt;
&lt;li&gt;Утечка памяти в IE 5.5 при большом количестве "прикрытых" элементов и при интенсивных манипуляциях с DOM-ом&lt;/li&gt;
&lt;li&gt;Некорректное позиционирование "IFRAME-подложки", если "прикрываемый" элемент имеет относительное позиционирование и расположен внутри элемента TD со значением стиля &lt;code class="css-style"&gt;vertical-align&lt;/code&gt; отличным от &lt;code class="css-value"&gt;top&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

Насколько эти недостатки критичны &amp;mdash; нужно рассматривать для каждого конкретного проекта отдельно.
&lt;br /&gt;&lt;br /&gt;

&lt;hr /&gt;
&lt;span id="links"&gt;Ссылки по теме:&lt;/span&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://docs.jquery.com/Plugins/bgiframe"&gt;http://docs.jquery.com/Plugins/bgiframe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.prototype-ui.com/rc0/Util/IframeShim"&gt;http://docs.prototype-ui.com/rc0/Util/IframeShim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hedgerwow.com/360/bugs/css-select-free.html"&gt;http://www.hedgerwow.com/360/bugs/css-select-free.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://habrahabr.ru/blogs/webdev/21913/"&gt;http://habrahabr.ru/blogs/webdev/21913/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.macridesweb.com/oltest/IframeShim.html"&gt;http://www.macridesweb.com/oltest/IframeShim.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rmcreative.ru/news/id/1185444438/"&gt;http://rmcreative.ru/news/id/1185444438/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8266213698782674998-8337471030208513699?l=web-dev-ru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/8337471030208513699/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://web-dev-ru.blogspot.com/2009/03/css-select-ie.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/8337471030208513699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/8337471030208513699'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/2009/03/css-select-ie.html' title='Универсальное решение для борьбы с «просвечивающими» SELECT-ами в Internet Explorer'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_1ammOv3TXXM/ScvFSn7K-_I/AAAAAAAAACQ/lAJo0kLxj78/s72-c/div_over_select_IE6.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8266213698782674998.post-9018157659874820811</id><published>2009-02-20T17:50:00.060+02:00</published><updated>2009-03-30T20:56:49.041+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='inheritance'/><category scheme='http://www.blogger.com/atom/ns#' term='ооп'/><category scheme='http://www.blogger.com/atom/ns#' term='наследование'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><title type='text'>Классическое наследование в JavaScript</title><content type='html'>Данная статья адресована, в первую очередь, программистам, пишущим на JavaScript и имеющим, как минимум, базовые знания в области объектов и наследования через прототипы. Поэтому, я не буду излагать азы (которые, при желании, можно найти по ссылкам в конце статьи [&lt;a href="#links"&gt;^&lt;/a&gt;]). Хочу просто показать, как можно реализовать классическое (классовое) наследование, используя стандартные возможности языка.&lt;br /&gt;&lt;br /&gt;

Поставим перед собой несколько целей:

&lt;ol&gt;&lt;li&gt;Наследование должно быть полноценным, т.е. конструкция 
&lt;span style="font-family:courier new;font-size:11px;color:#000000;"&gt;object &lt;span style="color:#0000ff;"&gt;instanceof&lt;/span&gt; &lt;span style="color:#008080;"&gt;Class&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;должна работать [&lt;a href="#instOf"&gt;^&lt;/a&gt;]&lt;/li&gt;&lt;li&gt;Реализовать простую возможность вызова конструктора [&lt;a href="#super1"&gt;^&lt;/a&gt;] или любого метода&lt;br /&gt;базового класса [&lt;a href="#super2"&gt;^&lt;/a&gt;]&lt;/li&gt;&lt;li&gt;Простота в использовании, стройность и лёгкость кода [&lt;a href="#result"&gt;^&lt;/a&gt;]&lt;/li&gt;&lt;li&gt;По возможности, облегчить задачу современным IDE (в частности &lt;a href="http://spket.com/"&gt;Spket&lt;/a&gt;) для корректного функционирования code complete по созданным объектам [&lt;a href="#spket"&gt;^&lt;/a&gt;]&lt;/li&gt;&lt;/ol&gt;Итак, создадим базовый класс:&lt;br /&gt;

&lt;pre class="code"&gt;

&lt;span style="color:#c0c0c0;"&gt;// Пишем конструктор базового класса&lt;/span&gt;
&lt;span style="color:#8899aa;"&gt;/**
 * Некий абстрактный человек, имеющий имя и
 * умеющий выполнять некоторые повседневные действия
 * &lt;em&gt;@constructor&lt;/em&gt; Person
 * &lt;em&gt;@param&lt;/em&gt; name {String} Имя человека
 */&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; &lt;span style="color:#008080;"&gt;Person&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; (name) {
    &lt;span style="color:#c0c0c0;"&gt;// Инициализируем public свойство name&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.name = name;
    &lt;span style="color:#c0c0c0;"&gt;// Локальные переменные определённые внутри конструктора
    // можно использовать, при необходимости, как private члены класса
    // но только через специальные public методы (getter и/или setter),
    // определённые здесь же - в конструкторе
    //
    // var somePrivateVariable = {};
    // this._getSomePrivateVariable = function() {
    //     return somePrivateVariable;
    // }&lt;/span&gt;
}
&lt;span style="color:#c0c0c0;"&gt;// Описываем члены базового класса внутри wrapper-функции
// и сохраняем ссылку на неё в public static свойство $class
// для дальнейшего использования
// ПРИМЕЧАНИЕ:
//    Естественно, wrapper-функция может быть и анонимной.
//    В данном примере имя (совпадающее с именем класса) используется
//    только для того, чтобы получить более дружественный code complete в IDE
&lt;/span&gt;
&lt;span style="color:#8899aa;"&gt;/**
 * &lt;em&gt;@class&lt;/em&gt; Person
 */&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Person&lt;/span&gt;.$class = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; &lt;span style="color:#008080;"&gt;Person&lt;/span&gt;() {
    &lt;span style="color:#c0c0c0;"&gt;// Локальные переменные определённые в этой области
    // будут что-то вроде private static членов класса&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; $className = &lt;span style="color:#800000;"&gt;'Person'&lt;/span&gt;;
    &lt;span style="color:#c0c0c0;"&gt;// Описываем public свойства класса&lt;/span&gt;
    &lt;span style="color:#8899aa;"&gt;/**
    * Имя человека
    * &lt;em&gt;@type&lt;/em&gt; {String}
    */&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.name = &lt;span style="color:#800000;"&gt;''&lt;/span&gt;;
    &lt;span style="color:#c0c0c0;"&gt;// Описываем public методы класса&lt;/span&gt;
    &lt;span style="color:#8899aa;"&gt;/**
    * Возвращает список ежедневных действий человека
    * &lt;em&gt;@returns&lt;/em&gt; {String}
    */&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.performEverydayActions = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#800000;"&gt;'- Спит, ест, развлекается [as a '&lt;/span&gt; + $className + &lt;span style="color:#800000;"&gt;']'&lt;/span&gt;;
    }
    &lt;span style="color:#8899aa;"&gt;/**
    * Возвращает имя человека
    * &lt;em&gt;@returns&lt;/em&gt; {String}
    */&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.getName = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span style="color:#0000ff;"&gt;return this&lt;/span&gt;.name;
    }
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.toString = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span style="color:#0000ff;"&gt;return this&lt;/span&gt;.name;
    }
}
&lt;span style="color:#c0c0c0;"&gt;// "Компилируем" базовый класс, создавая прототип из wrapper-функции&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Person&lt;/span&gt;.prototype = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;Person&lt;/span&gt;.$class();&lt;/span&gt;&lt;/span&gt;

&lt;/pre&gt;

Далее, создадим производный класс:

&lt;pre class="code"&gt;

&lt;span style="color:#c0c0c0;"&gt;// Пишем конструктор производного класса&lt;/span&gt;
&lt;span style="color:#8899aa;"&gt;/**
 * Некий абстрактный работник, имеющий имя (как и любой человек) и
 * умеющий выполнять какую-либо работу
 * &lt;em&gt;@constructor&lt;/em&gt; Employee
 * &lt;em&gt;@extends&lt;/em&gt; Person
 * &lt;em&gt;@param&lt;/em&gt; name {String} Имя работника
 * &lt;em&gt;@param&lt;/em&gt; job {String} Функция работника (или работа, которую он умеет выполнять)
 */&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; &lt;span style="color:#008080;"&gt;Employee&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; (name, job) {
    &lt;span id="super1" style="color:#c0c0c0;"&gt;// Вызываем конструктор базового класса Person
    // (через ссылку $super, которую установим ниже),
    // чтобы проинициализировать имя при создании
    // объекта производного класса (Employee)&lt;/span&gt;
    arguments.callee.$super.call(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, name);
    &lt;span style="color:#c0c0c0;"&gt;// Инициализируем public свойство job&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.job = job;
}
&lt;span style="color:#c0c0c0;"&gt;// Сохраняем ссылку на базовый класс для дальнейшего использования&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;.$super = &lt;span style="color:#008080;"&gt;Person&lt;/span&gt;;
&lt;span style="color:#c0c0c0;"&gt;// Описываем члены производного класса внутри wrapper-функции
// и сохраняем ссылку на неё для дальнейшего использования&lt;/span&gt;
&lt;span style="color:#8899aa;"&gt;/**
 * &lt;em&gt;@class&lt;/em&gt; Employee
 * &lt;em&gt;@extends&lt;/em&gt; Person
 * &lt;em&gt;@param&lt;/em&gt; $super {Object} Прототип базового класса
 */&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;.$class = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; &lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;($super) {
    &lt;span style="color:#c0c0c0;"&gt;// Внутрь wrapper-функция производного класса будем передавать
    // в качестве агрумента ссылку на прототип базового класса.
    // Это существенно облегчит обращение к методам базового класса (см. ниже)&lt;/span&gt;

    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; $className = &lt;span style="color:#800000;"&gt;'Employee'&lt;/span&gt;;

    &lt;span style="color:#c0c0c0;"&gt;// Описываем public свойства класса&lt;/span&gt;
    &lt;span style="color:#8899aa;"&gt;/**
     * Функция работника
     * &lt;em&gt;@type&lt;/em&gt; {String}
     */&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.job = &lt;span style="color:#800000;"&gt;''&lt;/span&gt;;
    
    &lt;span style="color:#c0c0c0;"&gt;// Описываем public методы класса&lt;/span&gt;
    &lt;span style="color:#8899aa;"&gt;/**
     * Возвращает функцию работника
     * &lt;em&gt;@returns&lt;/em&gt; {String}
     */&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.getJob = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span style="color:#0000ff;"&gt;return this&lt;/span&gt;.job;
    }
    &lt;span style="color:#c0c0c0;"&gt;// Переопределяем метод базового класса&lt;/span&gt;
    &lt;span style="color:#8899aa;"&gt;/**
     * Возвращает список ежедневных действий человека, включая его рабочие функции
     * &lt;em&gt;@returns&lt;/em&gt; {String}
     */&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.performEverydayActions = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span id="super2" style="color:#c0c0c0;"&gt;// Вызываем метод базового класса&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; $super.performEverydayActions.call(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;) +
                &lt;span style="color:#800000;"&gt;'\n- '&lt;/span&gt; + &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.job + &lt;span style="color:#800000;"&gt;' [as an '&lt;/span&gt; + $className + &lt;span style="color:#800000;"&gt;']'&lt;/span&gt;;
    }
}
&lt;span style="color:#c0c0c0;"&gt;// Устанавливаем наследование производного класса
// от базового класса через прототипы&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;.$class.prototype = &lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;.$super.prototype;
&lt;span style="color:#c0c0c0;"&gt;// "Компилируем" класс, создавая прототип из wrapper-функции
// и передавая в качестве аргумента прототип базового класса&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;.prototype = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;.$class(&lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;.$super.prototype);

&lt;/pre&gt;

Теперь, создадим класс производный от производного (именно на этом шаге многие попытки реализовать классовое наследование терпели неудачу):

&lt;pre class="code"&gt;

&lt;span style="color:#c0c0c0;"&gt;// Пишем конструктор ещё одного производного класса&lt;/span&gt;
&lt;span style="color:#8899aa;"&gt;/**
 * Программист, который может писать код
 * &lt;em&gt;@constructor&lt;/em&gt; Developer
 * &lt;em&gt;@extends&lt;/em&gt; Employee
 * &lt;em&gt;@param&lt;/em&gt; {String} name Имя
 */&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; (name) {
    &lt;span style="color:#c0c0c0;"&gt;// Вызываем конструктор базового класса (Employee)&lt;/span&gt;
    arguments.callee.$super.call(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, name, &lt;span style="color:#800000;"&gt;'Пишет код'&lt;/span&gt;);
}

&lt;span style="color:#c0c0c0;"&gt;// Т.к. класс Developer не имеет собственных членов, то wrapper - пустая функция&lt;/span&gt; 
&lt;span style="color:#8899aa;"&gt;/**
 * &lt;em&gt;@class&lt;/em&gt; Developer
 * &lt;em&gt;@extends&lt;/em&gt; Employee
 */&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;.$class = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {};
&lt;span style="color:#c0c0c0;"&gt;// Сохраняем ссылку на базовый класс&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;.$super = &lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;;
&lt;span style="color:#c0c0c0;"&gt;// Устанавливаем наследование&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;.$class.prototype = &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;.$super.prototype;
&lt;span style="color:#c0c0c0;"&gt;// "Компилируем" класс&lt;/span&gt;
&lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;.prototype = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;.$class(&lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;.$super.prototype);

&lt;/pre&gt;

Ещё немного усложним - создадим третий производный класс:

&lt;pre class="code"&gt;

&lt;span style="color:#c0c0c0;"&gt;// Пишем конструктор последнего производного класса&lt;/span&gt;
&lt;span style="color:#8899aa;"&gt;/**
 * Ведущий инженер-программист, который ещё и командой разработчиков управляет
 * &lt;em&gt;@constructor&lt;/em&gt; LeadDeveloper
 * &lt;em&gt;@extends&lt;/em&gt; Developer
 * &lt;em&gt;@param&lt;/em&gt; {String} name Имя
 * &lt;em&gt;@param&lt;/em&gt; {Developer[]} team Команда программистов
 */&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; &lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(name, team) {
    &lt;span style="color:#c0c0c0;"&gt;// Вызываем конструктор базового класса (Developer)&lt;/span&gt;
    arguments.callee.$super.call(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, name);
    &lt;span style="color:#c0c0c0;"&gt;// Инициализируем public свойство team&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.team = team;
}
&lt;span style="color:#c0c0c0;"&gt;// Сохраняем ссылку на базовый класс&lt;/span&gt;
&lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;.$super = &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;;
&lt;span style="color:#c0c0c0;"&gt;// Описываем члены класса&lt;/span&gt;
&lt;span style="color:#8899aa;"&gt;/**
 * &lt;em&gt;@class&lt;/em&gt; LeadDeveloper
 * &lt;em&gt;@extends&lt;/em&gt; Developer
 * &lt;em&gt;@param&lt;/em&gt; $super {Object} Прототип базового класса
 */&lt;/span&gt;
&lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;.$class = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; &lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;($super) {

    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; $className = &lt;span style="color:#800000;"&gt;'LeadDeveloper'&lt;/span&gt;;

    &lt;span style="color:#c0c0c0;"&gt;// Описываем public свойства класса&lt;/span&gt;
    &lt;span style="color:#8899aa;"&gt;/**
     * Команда программистов, которой руководит данный Lead
     * &lt;em&gt;@type&lt;/em&gt; {Developer[]}
     */&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.team = [];
    
    &lt;span style="color:#c0c0c0;"&gt;// Описываем public методы класса&lt;/span&gt;
    &lt;span style="color:#8899aa;"&gt;/**
     * Возвращает подчиненных данного Lead-а
     * &lt;em&gt;@returns&lt;/em&gt; {Developer[]}
     */&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.getTeam = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span style="color:#0000ff;"&gt;return this&lt;/span&gt;.team;
    }
    &lt;span style="color:#c0c0c0;"&gt;// Переопределяем метод базового класса&lt;/span&gt;
    &lt;span style="color:#8899aa;"&gt;/**
     * Возвращает список ежедневных действий человека, включая его рабочие функции
     * &lt;em&gt;@returns&lt;/em&gt; {String}
     */&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.performEverydayActions = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span style="color:#c0c0c0;"&gt;// Вызываем метод базового класса&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; $super.performEverydayActions.call(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;) +
                &lt;span style="color:#800000;"&gt;'\n- Управляет командой: [as a '&lt;/span&gt; +
                $className + &lt;span style="color:#800000;"&gt;']\n    '&lt;/span&gt; + &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.team.join(&lt;span style="color:#800000;"&gt;'\n    '&lt;/span&gt;);
    }
}
&lt;span style="color:#c0c0c0;"&gt;// Устанавливаем наследование&lt;/span&gt;
&lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;.$class.prototype = &lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;.$super.prototype;
&lt;span style="color:#c0c0c0;"&gt;// "Компилируем" класс&lt;/span&gt;
&lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;.prototype = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;.$class(&lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;.$super.prototype);

&lt;/pre&gt;


Теперь проверим, что получилось:

&lt;pre class="code"&gt;

&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; ivanov = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;Person&lt;/span&gt;(&lt;span style="color:#800000;"&gt;'Иванов Василий'&lt;/span&gt;);
alert(ivanov.getName() + &lt;span style="color:#800000;"&gt;':\n'&lt;/span&gt; + ivanov.performEverydayActions());
&lt;span style="color:#c0c0c0;"&gt;// Иванов Василий:
// - Спит, ест, развлекается [as a Person]&lt;/span&gt;

&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; petrova = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;(&lt;span style="color:#800000;"&gt;'Петрова Мария'&lt;/span&gt;,&lt;span style="color:#800000;"&gt;'Доит коров'&lt;/span&gt;);
alert(petrova.getName() + &lt;span style="color:#800000;"&gt;':\n'&lt;/span&gt; + petrova.performEverydayActions());
&lt;span style="color:#c0c0c0;"&gt;// Петрова Мария:
// - Спит, ест, развлекается [as a Person]
// - Доит коров [as an Employee]&lt;/span&gt;

&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; sidorov = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;(&lt;span style="color:#800000;"&gt;'Сидоров Алексей'&lt;/span&gt;);
&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; pupkin = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;(&lt;span style="color:#800000;"&gt;'Пупкин Иван'&lt;/span&gt;);
&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; shishkin = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;(&lt;span style="color:#800000;"&gt;'Шишкин Пётр'&lt;/span&gt;);
alert(sidorov.getName() + &lt;span style="color:#800000;"&gt;':\n'&lt;/span&gt; + sidorov.performEverydayActions());
&lt;span style="color:#c0c0c0;"&gt;// Сидоров Алексей:
// - Спит, ест, развлекается [as a Person]
// - Пишет код [as an Employee]&lt;/span&gt;

&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; myshkin = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;(&lt;span style="color:#800000;"&gt;'Мышкин Фёдор'&lt;/span&gt;, [sidorov, pupkin, shishkin]);
alert(myshkin.getName() + &lt;span style="color:#800000;"&gt;':\n'&lt;/span&gt; + myshkin.performEverydayActions());
&lt;span style="color:#c0c0c0;"&gt;// Мышкин Фёдор:
// - Спит, ест, развлекается [as a Person]
// - Пишет код [as an Employee]
// - Управляет командой: [as a LeadDeveloper]
//     Сидоров Алексей
//     Пупкин Иван
//     Шишкин Пётр &lt;/span&gt;

&lt;span id="instOf"&gt;alert(myshkin &lt;span style="color:#0000ff;"&gt;instanceof&lt;/span&gt; &lt;span style="color:#008080;"&gt;Person&lt;/span&gt;);&lt;/span&gt;
&lt;span style="color:#c0c0c0;"&gt;// true &lt;/span&gt;
alert(myshkin &lt;span style="color:#0000ff;"&gt;instanceof&lt;/span&gt; &lt;span style="color:#008080;"&gt;Employee&lt;/span&gt;);
&lt;span style="color:#c0c0c0;"&gt;// true &lt;/span&gt;
alert(myshkin &lt;span style="color:#0000ff;"&gt;instanceof&lt;/span&gt; &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt;);
&lt;span style="color:#c0c0c0;"&gt;// true &lt;/span&gt;
alert(myshkin &lt;span style="color:#0000ff;"&gt;instanceof&lt;/span&gt; &lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt;);
&lt;span style="color:#c0c0c0;"&gt;// true &lt;/span&gt;

&lt;/pre&gt;


[Весь предыдущий код одним файлом: &lt;a href="http://wolodko.narod.ru/blog_materials/classes-start.js" type="application/javascript" charset="windows-1251"&gt;classes-start.js&lt;/a&gt;]
&lt;script src="http://wolodko.narod.ru/blog_materials/classes-start.js" charset="windows-1251"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;
&lt;input type="button" onclick="testClasses();" value="Протестировать" /&gt;&lt;br /&gt;&lt;br /&gt;

&lt;span id="spket"&gt;Всё отлично работает. Code complete в Spket без проблем выдаёт список свойств и методов объекта &lt;em&gt;myshkin&lt;/em&gt;, причем по каждому из них указан класс, который их содержит:&lt;/span&gt;
&lt;br /&gt;
&lt;a href="http://2.bp.blogspot.com/_1ammOv3TXXM/SZ77eLstdYI/AAAAAAAAAAU/u359eGj48Jk/s1600-h/spket.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 222px;" src="http://2.bp.blogspot.com/_1ammOv3TXXM/SZ77eLstdYI/AAAAAAAAAAU/u359eGj48Jk/s400/spket.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5304953907043988866" /&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;span id="result"&gt;Осталось сделать красивую "обёртку":&lt;/span&gt;

&lt;pre class="code"&gt;

&lt;span style="color:#008080;"&gt;Function&lt;/span&gt;.prototype.$extends = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; ($super) { 
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.$super = $super;
    &lt;span style="color:#0000ff;"&gt;return this&lt;/span&gt;;
}
&lt;span style="color:#008080;"&gt;Function&lt;/span&gt;.prototype.$class = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; ($class) {
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; ($class == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;) {
        $class = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {};
    }
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.$class = $class;
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.$super != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.$class.prototype = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.$super.prototype;
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.prototype = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; $class(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.$super!=&lt;span style="color:#0000ff;"&gt;null&lt;/span&gt; ? &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.$super.prototype : &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);
    &lt;span style="color:#0000ff;"&gt;return this&lt;/span&gt;;
}

&lt;/pre&gt;


И "упаковать" (для примера, только два последних класса, чтобы не повторять опять гору кода):

&lt;pre class="code"&gt;

&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; (name) {

    arguments.callee.$super.call(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, name, &lt;span style="color:#800000;"&gt;'Пишет код'&lt;/span&gt;);

}.$extends( &lt;span style="color:#008080;"&gt;Employee&lt;/span&gt; ).$class();


&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; &lt;span style="color:#008080;"&gt;LeadDeveloper&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(name, team) {

    arguments.callee.$super.call(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, name);
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.team = team;

}.$extends( &lt;span style="color:#008080;"&gt;Developer&lt;/span&gt; ).$class( &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; ($super) {

    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; $className = &lt;span style="color:#800000;"&gt;'LeadDeveloper'&lt;/span&gt;;

    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.team = [];
    
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.getTeam = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span style="color:#0000ff;"&gt;return this&lt;/span&gt;.team;
    }
    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.performEverydayActions = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; $super.performEverydayActions.call(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;) +
                &lt;span style="color:#800000;"&gt;'\n- Управляет командой: [as a '&lt;/span&gt; +
                $className + &lt;span style="color:#800000;"&gt;']\n    '&lt;/span&gt; + &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.team.join(&lt;span style="color:#800000;"&gt;'\n    '&lt;/span&gt;);
    }

});

&lt;/pre&gt;

[Финальная реализация одним файлом: &lt;a href="http://wolodko.narod.ru/blog_materials/classes-final.js" type="application/javascript" charset="windows-1251"&gt;classes-final.js&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;

К сожалению, данная конструкция уже не по зубам IDE и code complete в финальной варианте всё-таки работать не будет. Однако, есть некоторые хитрости, которые позволят извлечь максимум пользы из всего вышеизложенного на различных фазах девелопмента.
&lt;br /&gt;&lt;br /&gt;
Но об этом как-нибудь в другой раз...
&lt;br /&gt;&lt;br /&gt;

&lt;hr /&gt;
&lt;span id="links"&gt;Ссылки по теме:&lt;/span&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Details_of_the_Object_Model"&gt;Details of the Object Model&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Inheritance"&gt;Inheritance&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://javascript.crockford.com/inheritance.html"&gt;Classical Inheritance in JavaScript&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://javascript.crockford.com/prototypal.html"&gt;Prototypal Inheritance in JavaScript&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://karaboz.ru/2007/10/06/oop-v-java-script-4-nasledovanie-klassov/"&gt;ООП в Java Script: Наследование классов&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8266213698782674998-9018157659874820811?l=web-dev-ru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://web-dev-ru.blogspot.com/feeds/9018157659874820811/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://web-dev-ru.blogspot.com/2009/02/javascript.html#comment-form' title='Комментарии: 3'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/9018157659874820811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8266213698782674998/posts/default/9018157659874820811'/><link rel='alternate' type='text/html' href='http://web-dev-ru.blogspot.com/2009/02/javascript.html' title='Классическое наследование в JavaScript'/><author><name>Pavel Volodko</name><uri>http://www.blogger.com/profile/07899805499420778345</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://3.bp.blogspot.com/_1ammOv3TXXM/SaWMte2maNI/AAAAAAAAAAw/_1OEUV7C7HU/S220/DSC06190.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_1ammOv3TXXM/SZ77eLstdYI/AAAAAAAAAAU/u359eGj48Jk/s72-c/spket.png' height='72' width='72'/><thr:total>3</thr:total></entry></feed>
