Пользователь
0,0
рейтинг
25 июля 2014 в 11:38

Разработка → Собеседование на должность JavaScript разработчика



Недавно прочитал неплохой пост на тему поиска работы QA и подумал, что похожий пост был бы полезен для JavaScript разработчиков. В конечном счёте, веб движется вперед семимильными шагами, и соискателей на позицию JavaScript программиста хоть отбавляй (разумеется, хороших всегда меньше).

Я очень хочу уйти от бессмысленной демагогии на тему «это обязательно знать, а это нет», поэтому свою статью я построю вокруг самых популярных вопросов-ответов (по опыту собственных собеседований, и собеседований, в которых я выступал собеседующей стороной), который случались за время моей профессиональной практики.

Вопросы, относящиеся к общим знаниям в области JavaScript


ООП в JavaScript. Один из самых популярных вопросов, на мой взгляд. Время от времени можно услышать вариации а-ля «Что такое прототипное наследование», «Инкапсуляция в JavaScript». Информацию можно найти тут или тут.

Утечки памяти в JS. Огромная тема, можно минут 10 рассказывать, мне кажется. Самым лаконичным примером я считаю var a = {}; a.a = a;. Такой код создаст утечку в IE <= 7 версии, т.к. осёл до 8 версии не умеет чистить циклические зависимости. Должно хватить для простой демонстрации понимания механизма работы с утечками. Далее будут вопросы а-ля «Как создать утечку, используя фреймворк N». В деталях можно прочитать тут.

Замыкания в JS. Нет, ну правда, какое собеседование без вопроса о замыканиях? Вопрос отчасти относится к предыдущему («Инкапсуляция в JavaScript»), но чаще всего рассматривается отдельно.

Самовызывающиеся функции. Тоже весьма частый вопрос на собеседованиях. Ещё иногда подходят к этому со стороны jQuery: «Почему все плагины обособлены в конструкцию (function() {})();?».

Область видимости переменных. Ключевое слово «this». Да и, честно говоря, всё, что связано с баблингом переменных и функций. Мол, чем отличается запись var a = function() {}; от записи function a() {};. Рассказать про this.

Как поменять контекст функции. Частичное применение функции. Ну, тут можно оставить без комментариев, всё упирается в знание разницы между .call, .apply и .bind и некоторых стандартных решений на уровне языка. Обо всём этом можно прочитать в одной замечательной статье.

Разница между операторами == и ===. За ответом сюда

Напишите регулярное выражение для проверки строк соответствующих формату даты dd.mm.yyyy. Ну, тут и без комментариев всё понятно.

Каков будет результат выполнения следующего кода:
for (var i = 0; i < 10; i++) { 
  setTimeout(function () { 
    console.log(i); 
  }, 0); 
}

В дополнение к вопросу хочу сказать, что обычно вторым вопросом идет «Как сделать так, чтобы выводило цифры по порядку?»

Что вернет выражение +new Date()? Чем отличается от Date.now(). Отличный вопрос. Ответ в том, что +new Date(); создаст экземпляр объекта Date и благодаря + переведет его в числовой формат. Во втором случае вызовется статический метод конструктора, который является более приоритетным, т.к. во-первых он не требует создания экземпляра, а во-вторых является более понятным.

Напишите функцию принимающую строку с именем файла и возвращающую расширение (фрагмент после последней точки). Я просто оставлю ссылку на ответ.

Производительность циклов. Иногда (но далеко не всегда) такой вопрос имеет место. Лично мне он нравится. По крайней мере, человек должен знать, почему for быстрее, чем Array.prototype.forEach. Но желательно ознакомиться с информацией из этой статьи.

На этом, как правило, стандартные вопросы заканчиваются. Дальше идут вопросы, касательно специфики вакансии. Я имею ввиду, более «профильные» для компании. Например, если требуется JS разработчик со знанием Backbone/Marionette(Chaplin), то следующий блок вопросов будет про jQuery, underscore/lodash и прочие связанные технологии, как бы очевидно это не звучало. Вопросов по данным тематикам море, но парочку любимых я всё-таки приведу:

Вопросы, относящиеся к jQuery


Почему перед исходным кодом jQuery стоит восклицательный знак?

Расскажите про $.Deferred. Могу посоветовать одно: кроме знания $.Deferred, было бы неплохо упомянуть о нативных Promise'ах

Как создать утечку памяти с помощью jQuery.
Я люблю простые примеры, поэтому обычно привожу следующее:

var jqSelector = $("#selector"),
    nativeSelector = document.getElementById("selector");

// Удаляем элемент "нативным" способом
nativeSelector.parentNode.removeChild(nativeSelector);

// Выводим закешированное значение селектора jQuery
console.log(jqSelector); // Привет, jQuery.cache!

А вообще, в части вопросов о нативном JS уже было похожее, и там же приведена ссылка на примеры с использованием jQuery.

jQuery.extend. Рассказать всё про функцию, возможно попросят написать аналог. Кстати, возможно будет полезно прочитать статью про примеси в JS.

Составьте AJAX-запрос на сервер, используя jQuery. Не особо популярный вопрос, но если спрашивать нечего, спросят что-то вроде него. Разумеется, вы должны знать, как использовать функции $.ajax, $.get, $.post и устанавливать настройки в $.ajaxSettings. Всё это уже давно есть на хабре.

Остальные вопросы скорее «для массовки», я считаю, что о jQuery больше нечего спрашивать. Конечно, будут ещё вопросы типа «Как добавить класс к объекту, используя jQuery», но я думаю, это не будет неожиданностью и не вызовет проблем.

Вопросы, относящиеся к Underscore/Lodash


Такие встречаются, честно говоря, очень редко. Но всё же, приведу краткий список того, что я могу вспомнить:

Чем _.throttle отличается от _.debounce. Опять же, ответ есть на хабре.

Как работает функция _.extend. Аналог вопроса про jQuery.extend, ссылка на доку выше.

Расскажите о шаблонизаторе Underscore. Кстати, не исключено, что это только начало, и вас будут спрашивать про шаблонизатор jQuery и все остальные. Я бы советовал хоть одним глазом прочитать эту статью.

Lodash vs Underscore. Вопрос для разведения холивара на собеседованиях

Что дальше?


А дальше специальные вопросы, касательно фреймворков и библиотек, которые использует компания в своих проектах. Обычно, больше всего ценятся ответы на вопросы из категории «нативного» JS, да ведь оно и не мудрено: технологии появляются и исчезают, и совсем не удивительно, если программист о чём-то не слышал, но ответы на эту категорию вопросов показывают, как быстро человек может изучить и понять, как работает та или иная библиотека/фреймворк.

Разумеется, если вам есть, что добавить к этой статье — пишите в лс, я обязательно дополню её вашей информацией.

Спасибо f0rk за интересные вопросы.
Алексей Куреев @xamd
карма
48,7
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (313)

  • 0
    спасибо, очень лаконично и со смыслом
  • +1
    Скопирую сюда некоторые вопросы, которые задаю на собеседовании

    1. Напишите функцию inArray проверяющую вхождение элемента в массив и возвращающую значение типа Boolean.
    2. Что вернет выражение +new Date()? Чем отличается от Date.now()?
    3. Напишите функцию принимающую строку с именем файла и возвращающую расширение (фрагмент после последней точки).
    4. Каков будет результат выполнения следующего кода:
    for (var i = 0; i < 10; i++) { 
      setTimeout(function () { 
        console.log(i); 
      }, 0); 
    }
    

    5. Напишите регулярное выражение для проверки строк соответствующих формату даты dd.mm.yyyy.
    6. Опишите разницу между операторами == и ===. Когда имеет смысл использовать каждый из вариантов?

    Иногда прошу реализовать bind или new ручками. Но если честно, люди, которых имеет смысл об этом просить встречаются не часто, к сожалению…
    • +2
      3 вопрос заинтриговал :)
      function getExt(filename){
       return filename.indexOf('.')!=-1?('.' + filename.split('.').pop()):'';
      }
      
      • –14
        так короче:
        return filename.split(".")[1];
        
        • +6
          Упс..image
          • 0
            Проще тогда так:

            var a = filename.split(".");
            return a[a.length-1];
            • 0
              Одной строкой:
              return text.match(/\.([a-zA-Z0-9]+)$/)[1];
              • 0
                P.S. сорри, уже заметил похожий вариант ниже. И _ забыл ).
        • 0
          ну, как минимум файлы бывают без расширений, да и никто не запрещает использовать точки в названиях :)

          например, в стандартном проекте есть файл:
          jquery.validate.unobtrusive.min.js

          ну и в windows, есть файлик «hosts», совсем без расширения.

          так что такой код — не круто :)
          • 0
            а еще есть .tar.gz
            • 0
              это несколько расширений.
        • 0
          del
        • 0
          del
        • +1
          Так не сработает, если имя файла будет содержать несколько точек. Можно так:

          function getExtension(filename) {
              var fragments = filename.split(".");
              return fragments[fragments.length - 1];
          }
          
          • 0
            Забыли проверку на наличие точек
          • +4
            'sdaasddasasdasd.asdasdasdasd.sadasdsdasda.das'.split('.').pop();
            'sdaasdsad'.split('.').pop()
            ''.split('.').pop()
            
        • +1
          ок, проспал… летс гоу эгейн:
          (function(a){ return a[a.length-1]; })(filename.split("."))
          
          • 0
            ".htaccess"
            
            "some.dir/else.dir/file-name-without-extension"
            
      • +6
        'some.class.js'.substring('some.class.js'.lastIndexOf('.') + 1)
        • 0
          не знаю, почему-то жутко не люблю операция с позициями в строках, их надо всегда жутко внимательно проверять, появляются всякие +1, знаки больше/меньше и т. п.
          • 0
            Приведите пример. Я не докапываюсь, просто мне правда интересно, так как я возможно опрометчиво не боюсь подобных операций.
            • +2
              Вы не поверите, полазил по своему коду, не встретил ни одного вызова substring (больше 20 000 строк, последний проект), видимо страх где-то глубоко :)

              А суть простая, например, взглянув на мой код, сразу понятно, с точкой я возвращаю или без. А вот смотря на
              substring('some.class.js'.lastIndexOf('.') + 1)
              

              Надо напрягать мозги: вспоминать, что возвращает функция; рассчитывать количество символов; да и просто напрягаться, а почему + 1, а не просто вызов.

              Хотя, если Вы каждый день пишите парсеры и т. п. То полагаю у Вас этот код не вызовет трудностей.
              • –4
                Я думаю, что если у вас есть страх по поводу операций с позициями в строках, то у вас точно есть PHP-прошлое.
                А что касательно кода вашего и того, что выше — то я бы для себя может сделал как у вас, а на собеседовании бы докопались до того, что создается ненужный массив и всякое такое. Хотя вот недавно меня попросили что-то подобное решать двумя разными способами.
                • 0
                  :) не, бог избавил от php, хотя пару страниц может и написал на нём.

                  да, докопаться можно до чего угодно, хотя javascript, это не C++ и не Assembler, поэтому не вижу смысла оптимизировать такие простые функции, до того момента, пока профайлер не покажет на них. :)
                • 0
                  Меня в Рамблер не взяли с такой формулировкой:
                  В Вашем решении на Asp.net слишком мало Asp.net!


                  Хотя я читал в вакансии, что знание xslt приветствуется, поэтому и «выпендрился» решив задание при помощи xml->xslt. :)
          • 0
            Все от задачи, имхо. Если речь идет о получении расширения файла, то чего тут бояться.
        • 0
          Решил так же, но сам к себе придрался, из-за lastIndexOf
          • +6
            Кстати, если сплясать от варианта devian (которого слишком уж, имхо, заминусовали), и поперчить его вариантом DenisNikolayev:

            'some.class.js'.split(".").pop();
            
            • +1
              Выдаст неверный ответ, если в имени файла вообще нет точки.
            • 0
              .join('')
      • +2
        Я однажды встречал где-то вот такой интересный способ.
        function getExt(filename)
        {
           return filename.substr((~-filename.lastIndexOf(".") >>> 0) + 2);
        }
        

        Работает почти корректно. Работает даже когда нету точек, или их больше одной. Не работает, если пустое имя файла (.htaccess) :-)
        • +1
          Не почти, а корректно. У .htaccess не пустое имя файла, это скрытый файл без расширения.
          • 0
            Это смотря с какой ОС посмотреть)
            • +1
              С точки зрения Win, это и вовсе некорректное имя файла. Во всяком случае создать такой файл с ходу она не позволяла. Про версию ОС, к сожалению, не уточню. Спасало либо наличие уже существующего файла с таким именем, либо командная строка. Поэтому давайте смотреть на задачи только с тех ОС, которые для них приспособлены? (=
              • +1
                Вы хотите сказать «с точки зрения приложения Explorer (проводник)», потому как например из командной строки или в FAR'е можно создавать такие файлы без проблем.
                • 0
                  Да-да, именно об этом я и говорил.
          • –1
            Корректно или нет, зависит от задачи — например, нужно разрешить загрузку файлов только с определенными расширениями, в т.ч. и .htaccess, тогда нужно чтобы эта функция возвращала «htaccess».
            • +1
              Но обсуждаемая функция пропустит и somefile.htaccess. А если вам нужно загружать файл .htaccess, то вам, скорее всего, нужен исключительно .htaccess, и никаких somefile.htaccess. Это совсем другая задача, и проверять здесь нужно имя целиком.
              • +1
                Ну да, согласен.
          • 0
            Не совсем точно говорить, что это скрытый файл, в unix-архитектуре такого понятия нет. Зато есть ленивый программист, посадивший баг, последствиями которого мы пользуемся до сих пор: habrahabr.ru/post/221105/
            • 0
              Да, эта история мне известна. Но важно не то, как зародилось явление, а чем оно является на данный момент.
      • 0
        А мне нравятся regexp'ы. Вот это должно работать, вроде:
        function getExt(file_path) {
            return (/\.([^./]*$)/.exec(file_path) || [,null])[1];
        }


        Хотя, мне кажется, что оно будет возвращать undefined вместо null в старых IE (там, кажись, при несовпадении пустой массив возвращался, а не null, если мне не изменяет память). Железнобетонно можно так:
        Скрытый текст
        function getExt(file_path) {
            var ext = (/\.([^./]*$)/.exec(file_path) || [])[1];
            // ext может быть undefined или пустой строкой. Следующая строка это разруливает:
            // пустая строка (для file_path == 'empty ext.') сохраняется, а undefined (для file_path == 'without ext'), заменяется на более логичный null.
            return ext == null ? null : ext;
        }
        
        • 0
          Ну если любите регулярки, то у нас вот такое используется:
          ( /(?:\.)([^.]+$)/.exec('jquery.validate.unobtrusive.min.js') || [] )[1]
          • 0
            ( /(?:\.)([^.]+$)/.exec('justfile') || [] )[1]
            вернёт undefined. Имхо, функция должна возвращать null в таком случае. А ещё, если расширение — пустая строка (имя заканчивается точкой), то что возвращать? Понятно, что это крайние и бредовые случаи, но всё же…
            • 0
              Ну, мне кажется об этом думать необязательно. Это же собеседование, в конце концов, а не production-решения :)
      • 0
        Эээх, люблю я чейнинг. Код сделан с учетом всех замечаний про .htaccess и так далее.

        return filename
          .replace(/^\./, '')
          .split('.')
          .slice(-2)
          [1] || ''
        

      • 0
        Все чуть проще вроде как. Поправьте меня, пожалуйста
        function ext(filename){
          return filename.split(".").pop();
        }
        ext('js.ert.txt.gz') //"gz"
        
        • 0
          Извиняюсь, не обновлял комментарии 2 часа… Увидел уже такой вариант.
      • 0
        'some.class.js'.replace(/.*\./, '');
        
      • 0
        Может я чего не понял, но почему нельзя сделать так:
        'filename.min.js'.match(/[^.]+$/)
        • 0
          Вернёт имя файла на имени без точки.
          • –1
            EZ :)

            ('filename.min.js'.match(/[^.\s]\.([^.]+)$/)||[])[1] === «js»

            ('.htaccess'.match(/[^.\s]\.([^.]+)$/)||[])[1] === undefined

            ('.hidden.ext'.match(/[^.\s]\.([^.]+)$/)||[])[1] === «ext»

            PS: не смотря на то то регулярные выражения не самая быстрая вещь на свете — они идеально подходят для решения данной задачи… ибо нам нужно найти… «регулярное выражение» :D
          • 0
            эмм, но согласитесь, что в условии четко написано «написать ф-ию, в которую передается имя файла». Если делать в каждом месте проверки на криворукость использующих функционал, то я даже не знаю… т.е. если ты в ф-ию передаешь 'filename', хотя в описании прописано что ф-ия делает, то ты кривой)))
            • 0
              эмм… а где у вас была функция? я лишь дополнил ваш RegExp. Вот вам функция.

              function getExt(fn) { return (fn.match(/[^.\s]\.([^.]+)$/)||[])[1] }

              Работает правильней любых других примеров и занимает меньше символом. Учитесь.
              • 0
                Подкол про наличие ф-ии засчитан :) Ф-ию писать не было нужны, т.к. основная часть заключается в регулярке…
                регулярку можно тогда и покороче написать:

                (fn.match(/[^.\s]\.([^.]+)$/)||[])[1]
                (fn.match(/\.([^.]+)$/)||[])[1]
                

                ЗЫ а вот про «учитесь» это вы не по адресу =)
              • 0
                У вас там регулярка при каждом вызове создаётся.
                • 0
                  На самом деле браузер кеширует такие регулярки и по факту они создаются только один раз.
                  • 0
                    Тоже верно. Ну тогда остаётся лишь заменить str.match(rgx) на rgx.exec(str) — одной буквой меньше :)
          • 0
            ЗЫ тем более, что из match совпадение мы получаем 2 элементом массива, в случае передачи названия без точки, мы получим undefined, так что все ок. Не знаю зачем такие длиные решения тут пишут =/
      • –2
        (function(name){return name.substr((name.lastIndexOf(".")+1)||name.length, name.length);})("txt.tar.gz");
        

        «txt.tar.gz» -> «gz»
        «hosts» -> ""
        • 0
          что ж вы не обосновали ваш минус?
      • –1
        Возможно, оптимальнее было бы так, поскольку файлы чаще имеют расширения, чем нет…

        function getExt(filename){
         var parts = filename.split('.');
         return (filename.length>1)?('.' + filename.pop()):'';
        }
    • –2
      Добавил все, кроме 1. Слишком уж очевидно. Или я ошибаюсь?

      function inArray(arr, item) {
          return !!~arr.indexOf(item);
      }
      
      • +7
        Аж мурашки побежали от "!!~". Ну, почему бы просто не написать != -1?
        Ну и плюс, полагаю, нужна поддержка большинства «любимых» браузеров семейства ie :)
        • 0
          Ну, все пишут, как им привычнее. В конечном счёте, это не production-код, а простое собеседование. Можно и != -1, конечно.
          Вы мне только скажите, при чём тут IE?!!! — двойное логическое отрицание, а ~ — побитовое отрицание, почему они не должны работать в IE?
          • 0
            Не, я про indexOf у Array, он в старых IE не поддерживается.
            • 0
              Так-то даже Яндекс уже поддерживает ИЕ лишь с 8-й версии и пилит полифиллы.
              Так что кажется такие пометки о неподдерживаемости стоит уже пропускать.
    • 0
      Каков будет результат выполнения следующего кода:
      for (var i = 0; i < 10; i++) { 
        setTimeout(function () { 
          console.log(i); 
        }, 0); 
      }
      


      В дополнение к вопросу хочу сказать, что обычно вторым вопросом идет «Как сделать так, чтобы выводило цифры по порядку?»


      Я ещё предлагаю написать 5 разных способов сделать чтобы цифры выводило по порядку. Совсем как бонус, показывает на сколько человек заинтересован темой и отличная ступенька для дальнейшего обсуждения на собеседовании.
      • 0
        А не поделитесь всеми пятью? Можно без кода, на словах. Интересно, насколько они разными будут и насколько отходить от исходного.
        • +1
          Способы довольно разные. Очень разные конструкции языка. С дом-элементами есть ещё шестой способ) Подсказки дам, давайте предположения в комментах в спойлерах:
          Скрытый текст
          1. Стандартный способ
          2. Deprecated-способ
          3. Deprecated-нуб-способ
          4. Ecma5
          5. Ecma6


          Самые интересные, на моё мнение, второй и четвёртый.
          • +2
            В принципе моего мышления есть одна проблема — неумение решать задачи типа «Сделайте n способами». Если нашелся один способ, который устраивает и подходит, разум отказывается даже думать в других направлениях. Другое дело, если найденный способ имеет недостатки. Там уже можно рассматривать поиск нового решения, отвечающего требованиям.

            Поэтому сходу могу предложить лишь один способ, и он, полагаю, как раз идет первым пунктом в вашем списке.
          • +5
            Ох уж этот TheShock. Придумал только 3.

            Скрытый текст
            for (var i = 0; i < 10; i++) { 
              (function (i) {
                setTimeout(function () {
                  console.log(i);
                }, 0);
              })(i)
            }
            
            for (var i = 0; i < 10; i++) { 
              setTimeout(function (i) {
                console.log(i)
              }.bind(undefined, i), 0)
            }
            
            for (var i = 0; i < 10; i++) { 
              setTimeout(function (i) {
                console.log(i)
              }, 0, i)
            }
            

            • +8
              Ой, я и забыл про то, что аргументы можно в setTimeout передать. Даже проверил на всякий случай. Так что это шестой способ.

              Вот ответы:

              Скрытый текст
              1. Стандартный способ — IIEF
              for (var i = 0; i < 10; i++) { 
                (function (i) {
                  setTimeout(function () {
                    console.log(i);
                  }, 0);
                })(i)
              }
              


              2. Deprecated-способ. Довольно интересный, как на меня. Про него практически никто не знает, хотя это тот же let из Ecma6 который работает везде

              for (var i = 0; i < 10; i++) with({ i: i }) {
                setTimeout(function () {
                  console.log(i);
                }, 0);
              }
              


              3. Deprecated-нуб-способ. Главное — не блевануть.
              for (var i = 0; i < 10; i++) { 
                setTimeout('console.log('+i+')', 0);
              }
              


              4. Ecma5 — способ, который я предпочитаю на практике. Для более сложного случая подойдёт тот вариант с bind, что написали вы)
              for (var i = 0; i < 10; i++) { 
                setTimeout(console.log.bind(console, i), 0);
              }
              


              5. Ecma6
              for (var i = 0; i < 10; i++) {
                let k = i;
                setTimeout(function () {
                  console.log(k);
                }, 0);
              }
              


              6. Параметры
              for (var i = 0; i < 10; i++) { 
                setTimeout(function (i) {
                  console.log(i)
                }, 0, i)
              }
              


              Ещё есть способы в случае с примером с dom-элементом и click (использовать data и event.target).

              7. Вот ещё способ додумал. Не очень интересный:
              var k = 0;
              for (var i = 0; i < 10; i++) {
                setTimeout(function () {
                  console.log(k++);
                }, 0);
              }
              


              • +3
                Остается только повторить самого себя, ох уж этот TheShock.
                • 0
                  Ну вы тоже молодец. Все три способа годны)
                  Как мои способы? Разнообразны?
                  • 0
                    Еще как. Про with и eval я уже просто забыл, да и что там говорить, когда я пришел в js-тусовку так делать уже давно было порицаемо, так что просто ни разу не использовал.
                • +1
                  7. Ну и чисто посмеяться добавочка:
                  Скрытый текст
                  new Array(10).join().split(',').forEach(function (item, index) {
                    console.log(index)
                  });
                  

                  • 0
                    8. Еще

                    Скрытый текст
                    Добавляем перед for
                    setTimeout = function(f){f()};
                  • 0
                    Ещё вариант, без join & split:

                    Скрытый текст
                    Array.apply(null, Array(10)).forEach(function (_, i) { console.log(i); });
                    
              • 0
                Let достаточно умный:

                5. Ecma6
                for (let i = 0; i < 10; i++) {
                  setTimeout(function () {
                    console.log(k);
                  }, 0);
                }
                
                • +1
                  Я в консоли Фокса проверил — недостаточно умный(
                  • 0
                    К сожалению это Фокс недостаточно умный, как впрочем и node: оба пока не поддерживают let на 100% (https://developer.mozilla.org/en-
                    US/docs/Web/JavaScript/ECMAScript_6_support_in_Mozilla)

                    В спеке прописано поведение описанное выше, когда let создает замыкание для каждой итерации цикла.

                    Правильное поведение выдает, например traceur (хоть и по-уродски)

                    • 0
                      Правильное поведение выдает, например traceur (хоть и по-уродски)

                      А онлайн не генерит((
                      • 0
                        Вот тут открыть Options, поставить флаг experimental.

                        Результат смотреть в консоли браузера
              • 0
                Наконец-то я узнал, зачем вообще кто-то использует setTimeout со строковым параметром…

                Я думал, что передать функцию всегда проще, чем строку, а значит, строку передают только незнающие о том, как передать функцию. Оказывается, дело в незнании замыканий…
    • +1
      Тут вам уже поотвечали, но самого простого варианта для третьего задания пока ещё нет:
      function (s) {
          return s.replace(/.*\./, '')
      }
      
      Подразумевается, то параметр всегда строка и расширение у файла есть.
      • 0
        Oй, не обратил внимание, что вы уже это написали.
    • 0
      Капитанское решение:

      function getExt(filename){
        var res = false;
        if (filename) {
          var arr = filename.split('.');
          res = arr.length > 1 ? arr[arr.length - 1] : false;
        } 
        return res;
      }
      

      • 0
        Во-первых не нужна проверка if (filename) — вызывая функцию вы уже гарантируете, что передают имя файла,
        во-вторых если в имени файла нет расширения, то вы имеете все шансы вернуть почти полный путь к файлу (например файл /mydir/dir.2/home/myfile),
        в-третьих в случае отсутствия результата семантичнее возвращать null, а не false, который сигнализирует о пустом результате, а не отрицательном,
        в-четвертых для выражений с единой структурой по ряду причин лучше использовать регулярные выражения, а не split (например расширение не может содержать символ "/").
        Ну и если уж до конца идти, то проверка на существование значения лучше выглядит так: if (filename != null), ввиду отсутствия привидения типов.
        А объявления переменных, например arr лучше выносить вверх скоупа.
        Я бы немного поругался на такой код. :)
        • 0
          А объявления переменных, например arr лучше выносить вверх скоупа.


          Вот этого я не понимаю. Зачем? Как будто вернулся в школьные времена, к родному Паскалю. Да, есть variable hoisting, но это проблема только в очень больших функциях с кучей мелких переменных.
        • 0
          1) Составитель задания это не гарантирует. Скорее всего будут случаи, когда аргумент функции не определен или содержит null
          2) В задании есть фраза «фрагмент после последней точки», не вижу противоречий, про отделение имени файла от остальной части пути нас не просили.
          3) как бы да, но в таком случае есть опасность, что напишут нечто вроде
          if (getExt(fn) == null) {
          
          а это приведет к плачевным результатам
          4) Для такой пустяковой задачи рациональнее использовать сплит
          идти до конца нет смысла, но проверку на существование аргумента можно улучшить написав так
          if (filename + "") {
          

          С объявление переменных в начале скоупа соглашусь.
          С удовольствием взглянул бы на ваш вариант этой функции.
          • 0
            Обязательно напишу, но чуть позже — время уже позднее. Еще один кейс, который неожиданно вспомнился мне это скрытые файлы в unix системах. Например имя файла ".htaccess" не имеет расширения.
            Строго говоря по заданию «фрагмент после последней точки» у вас всё здорово и ни в коем случае на собеседовании не предъявил подобных претензий.
            В маленький локальный проект такой код можно поместить, но не в библиотеку.
            P.S.: Скорее всего даже не смогу с первого раза правильно написать регулярку, т.к. не помню ограничений различных файловых систем по наименованию. В *nix системах вроде только "/" нельзя использовать в названии файла, но могу ошибаться. :)
            P.P.S.: В целом на большинстве кейсов у вас хороший код, но реально в программировании всякое бывает, вспомнить только статью Заблуждения программистов относительно времени чего стоит.
  • +20
    Спасибо, сбегал, устроился.
  • –1
  • +6
    Я тут собеседовался в одну топовую российскую контору, и мне всего-то навсего задали вопросы про замыканий, this, контекст и еще мелочи, в общем обычные вопросы, со слегка хитроумными формулировками(чтобы понять на сколько я хорошо понимаю синтаксис и особенности).

    Так что работодателям я бы посоветовал не переусердствовать с вопросами, а соискателям посоветовал бы приложить к резюме какой-нибудь рабочий код прямо в архиве и с демонстрацией, ну или профиль на гитхабе, если есть что показать.
  • +2
    Про архитектуру нужны вопросы, про модульность, про паттерны, а то многие конструкции писать научились, а воедино это свести не могут. Пишут вермишель, превышают все сроки и не знают, что можно по-другому.
  • НЛО прилетело и опубликовало эту надпись здесь
    • +6
      Я тоже разорился.
      • 0
        Сильно извиняюсь, не обратил внимания. Пережал, теперь 140Кб
  • 0
    после отпуска пригодится )
  • +14
    Никогда не понимал, почему спрашивают всякую фигню, которую то и знать не обязательно для успешного программирования… людям надо давать задания решить ту или иную задачу, и не спрашивать всякий бред
    • +1
      Это будет выглядеть как обезьяна с гранатой. Необходимость теоретических знаний обусловлена тем, что код надо не только «писать в ящик», но и поддерживать. Если человек не знает языка, то велика вероятность большого количества костылей, которые придется переписывать, чтобы на код можно было смотреть без слёз. Это не говоря уже об оптимизации узких мест и т.п.
      • +2
        Вот и посмотрите на код, который на следующий день напишет вам притендующий на должность… а приличные фирмы еще и обучают сотрудников, показывая почему такой то вариант не годится.
        • 0
          К сожалению, у меня был опыт работы с одним таким человеком, и он ещё раз подтверждает мои слова.
          А по поводу фирм — вы правы, если мы рассуждаем о больших компаниях, то обучение персонала является важной составляющей. Однако, если мы говорим о каком-нибудь стартапе или небольшой компании, это становится непозволительной роскошью.
          • –2
            «если мы говорим о каком-нибудь стартапе или небольшой компании, это становится непозволительной роскошью»

            Мотайте на ус господа программисты — там где вас мучают ничего не значащими тестами — это фирмы однодневки, в которых вас хотя просто «подоить» :)
  • –10
    А про ООП в JavaScript — надо отвечать — нет ООП в JavaScript. А потом уточнять недореализация. Если вопрошающий не соглашается — вставать и уходить — с такими людьми не сработаетесь.
    • +3
      По этому вопросу можно столько жарких споров учинить.

      Например, Никлаус Вирт, категорически против того, чтобы выделять ОПП, как парадигму. Типа, взяли record, добавили сахарку с вызовом функций func(obj) на obj.func() и «внезапно», это стало новой крутой парадигмой :) У него в языке Оберон, например, так и использует обычные записи с сахаром в вызове методов. Плюс первая реализация ООП, была совсем иной, да и есть куча разношерстных реализаций (с посылкой сообщений, с множественным наследованием, интерфейсами с реализацией, с прототипированием и т. п.)

      Так что, если не хотите на эту работу, можно спросить: «А что Вы понимаете под аббревиатурой ООП?» :)
      • –8
        Если есть желание, можем поговорить, но думаю вначале стоит прочитать

        Существуют только структурная и объектная парадигмы программирования.
      • –5
        «добавили сахарку с вызовом функций func(obj) на obj.func()»

        Это тоже важно, так как показывает, что мы вызываем функцию конкретного объекта, а не передаем не понятно чьей функции (т.е. функции в глобальной куче) объект, а в случае с JS это и вовсе не объект а массив.
        • +2
          а в случае с JS это и вовсе не объект а массив.

          Э-э, што?
          в случае
          var obj = Class();

          в obj будет объект, а не массив, более того, массив в JS — это тоже объект:
          var a = [];
          toString.apply(a);
          

          выведет:
          [object Array]

          Это тоже важно, так как показывает, что мы вызываем функцию конкретного объекта, а не передаем не понятно чьей функции (т.е. функции в глобальной куче)
          да, не передаём, но это синтаксис. Функции как бы всё равно с каким this она работает.
          ведь при наследовании она работает с не объектом класса, где она была определена, а с объектом дочернего класса.

          В C#, например, можно делать функции, которые будут добавляться как методы во встроенные классы, String, например.
          В Перле тоже можно сделать внешнюю функцию, которую с помощью специальной команды bless можно прицепить к какому-нибудь классу (хотя в Перле пакеты, а не классы, но для простоты назовём класс).
          • +1
            var obj = Class();
            

            ---->
            var obj = new Class();
            

            • 0
              Ого, привет с кадабры.
              В последнее время стало модным пихать во все конструкторы проверку this instanceof Class, толпы JS-ников привыкли и напрочь забыли оператор new. Так что и такая запись сгодится для понимания =)
      • 0
        Конечно же обычно вызов метода реализуется как функция с нулевым аргументом-this, но всё же func(obj) != obj.func(), так как существуют виртуальные функции, полиморфизм. Я категорически против того, чтобы выделять Никлауса Вирта в отдельную парадигму.
        • 0
          Есть структурный полиморфизм (утиная типизация)! :)

          Да, с виртуальными функция сложнее, но сейчас многие рекомендуют не создавать больших иерархий объектов, не больше двух уровней (интерфейс и реализация). А вместо наследования реализовывать ассоциацию. Причем достаточно много классов в C# помечены атрибутом sealed, запрещающим наследование.

          Читал множество критики наследования, всяких уток от птиц и т. п. Так что похоже можно жить без него :)

        • 0
          Полиморфизм можно реализовать не только через виртуальные методы на обьектах. Есть же мультиметоды, протоколи (clojure).
    • +8
      ммм, не хочу вас расстраивать, но JS соответствует парадигме ООП
      • –21
        Нет.
        • +7
          Могу я услышать ваши аргументы на этот счёт?
          • –16
            Я бы хотел услышать как в JS описать класс :)
            • +7
              Вместо класса — объект-прототип. Если интересно, можете прочитать про прототипное программирование, которое входит в понятие ООП.
              • –16
                Давайте не кидаться ссылками. Мне не надо про это читать. А вот утверждения вида " прототипное программирование, которое входит в понятие ООП" нужно обосновывать. Я утверждение надуманное, ничего там и близкого нет с ООП.
                • +3
                  Давайте не кидаться ссылками, но вы не верите мне на слово, я и подкрепляю свои слова достоверными источниками. Есть вполне себе ясная трактовка парадигмы ООП и её составляющих.

                  А вот утверждения вида " прототипное программирование, которое входит в понятие ООП" нужно обосновывать

                  Оно обосновано ссылкой, которую я привел выше.

                  Я утверждение надуманное, ничего там и близкого нет с ООП.

                  А вот это было бы неплохо обосновать.
                  • –14
                    Ссылка на Википедию :)
                    • +3
                      Если вы считаете википедию сомнительным источником, вы можете привести свой, более надёжный и достоверный источник. Однако, я до сих пор не увидел ни одного подтверждения вашей позиции. Было бы здорово, если бы вы начали свой ответ с этого.
                  • –6
                    Но я вам дам определение Г. Буча — думаю сомнений в его компетенции не возникает?

                    1. ООП использует в качестве базовых элементов объекты, а не алгоритмы
                    2. Каждый объект является экземпляром какого-либо определенного класса
                    3. Классы организованны иерархически

                    Программа будет объектно-ориентированной только при соблюдении всех трех указанных требований


                    Поэтому мы можем порассуждать, что такое и насколько хорошо прототипное программирование, только связи с ООП тут нуль целых.
                    • –5
                      И в частности Буч продолжает:

                      В частности, программирование, не основанное на иерархических отношениях, не относится к ООП, а называется программированием на основе абстрактных типов данных.


                      Продолжая же его мысль, можно сказать что программирование без классов, т.е. без абстрактных типов данных — тем более не является ООП, и может называться прототипным программированием. Хотя концепция этого программирования достаточно смешна по сравнению с ООП — и это можно обсудить детальнее если будет интерес. Но вначале совершенно не провомочно делать вид, что прототипное программирование как то относится к ООП.
                      • +5
                        Объект-прототип является таким же абстрактным типом данных, что и класс, поэтому никакой ошибки здесь нет. С помощью прототипного наследования можно реализовать иерархические отношения между объектами.
                        • 0
                          Ниже пример и вопрос: как мне узнать что объект принадлежит типу ClassExample?
                          • +9
                            obj instanceof ClassExample
                            


                            if (obj instanceof ClassExample) {
                                  ...
                            }
                            
                    • 0
                      Вы знаете, что ссылаетесь на книгу «Object Oriented Analysis and Design» 91/94 года выпуска?
                      Я ни капельки не сомневаюсь, что в те года это было абсолютно правильно. Но разумеется, многое изменилось за 20 лет, и парадигма ООП существенно расширилась за это время.
                      • 0
                        :) парадигмы не меняются… возникают новые, а то что некоторые хотят к ней примазаться — это скорее плохо, т.к. дискридитируют саму парадигму. ООП — это не все что можно придумать :)

                        Да и потом Вы пока не сослались не на что
                        • +1
                          Ну, я бы не называл всемирную интернет-энциклопедию «ничем». По моему скромному мнению, на данный момент это самый полный и достоверный источник знаний.

                          Если они не меняются, то должна быть отправная точка — своеобразная спецификация, формулировка, которая является «единственно правильной». Вы можете её привести? Можете считать это доказательством от обратного. Найдете — ваша правда, не найдете — моя. И пожалуйста, пусть это будет формулировка из этого тысячелетия.
                          • –9
                            Уж поверьте мне — я прекрасно знаю как пишется этот «достоверный источник». Все зависит от автора. Ну и потом Википедия сама говорит, что он не является достоверным источником :)

                            И вот такие люди принимают собеседование :) — остаюсь при своем мнении — вставать и уходить, не вам оценивать знания других :)
                            • +9
                              Ну, в свою очередь, могу сказать, что рад, что не работаю с такими людьми.
                              • 0
                                Он же сразу и честно написал: «Не сработаемся» (:
                                Встал и ушёл — и хорошо, пусть к вам придёт другой человек, а он придёт к другим людям.
                              • 0
                                Весной собеседовал одного кандидата с аналогичной позицией. Жаль это было по скайпу…
                            • 0
                              del
                      • +6
                        Прототипное программирование является более «объектным», чем классовое, так как в языках с иерархией классов существуют объекты нескольких типов — объекты классы и объекты экземпляры, и смысл их разный, а в прототипном все объекты унифицированы. И всё это изменилось не с 1994, а было известно и проверено ещё в 70-e во времена возникновения Smalltalk и Self. Не нужно полагать, что история началась с C++ ;-)
                    • +2
                      1. ООП использует в качестве базовых элементов объекты, а не алгоритмы
                      2. Каждый объект является экземпляром какого-либо определенного класса
                      3. Классы организованны иерархически

                      Программа будет объектно-ориентированной только при соблюдении вех трех указанных требований

                      1. создавай объект в JS, и будут тебе объект
                      2. невероятно, но это так! даже пустой литеральный объект — это экземпляр класса Object (правда в JS класс — это тоже объект)
                      3. невероятно, но по цепочке прототипов в JS есть иерархия до верхнего класса Object

                      • 0
                        Ну вы же сами понимаете, что инстанс Object в JS это не объект в понимании классического ООП. Это ближе к Hash в руби или Map какой-нибудь там в джаве. Просто назвали так.

                        Да и не все в жс объекты. 4 instanceof Object === false. Да даже 4 instanceof Number === false.

                        Давайте я скажу вам факт, после которого ООПсрач можно закрыть будет? Если нет желания срача ради срача.
                        ООП в жс есть. Но оно канонично использовалось для механизмов работы DOM, глубоко интегрированных в реализации языка, сам подход в ЖС всегда был преимущественно функциональным, то, что создаются методы — это необходимый сахар из-за невозможности делать оверлоад функций.
                        Без ООП пришлось бы для каждого типа ноды назначать свои методы, потому что не было бы цепочки HTMLAudioElement -> HTMLMediaElement -> HTMLElement -> Node -> EventEmitter -> Object (могу путать точный порядок).
                        • 0
                          Ну вы же сами понимаете, что инстанс Object в JS это не объект в понимании классического ООП

                          Чем он отличается, и что в вашем понимании «классическое ООП»

                          Да и не все в жс объекты. 4 instanceof Object === false. Да даже 4 instanceof Number === false.

                          Разумеется. Ещё есть примитивы, которые не являются объектами, но это никак не противоречит парадигме ООП.

                          ООП в жс есть

                          Есть. И оно подходит без всяких «натяжек» под каноны ООП. С историей становления JS вы абсолютно правы, но перед ним и не стояло тех задач, которые стоят сейчас. Разумеется, язык развивается вместе с требованиями к нему.

                          Я поддерживаю идею не разводить срач.
                          • –5
                            > И оно подходит без всяких «натяжек» под каноны ООП.

                            Просто фиерическое утверждение :)

                            Помимо уже обсужденных натяжек… опишите мне как переопределить функцию в классе наследнике?
                            • –2
                              т.е. аналог

                              	public class A
                              	{
                              		public virtual void M1()
                              		{ }
                              	}
                              
                              	public class B : A
                              	{
                              		public override void M1()
                              		{
                              			base.M1();
                              			...
                              		}
                              	}
                              
                              

                              • 0
                                del
                                • 0
                                  см. комментарий ниже — вы реализовали нечто другое :) и назвали не правильно :)

                                  А если вдруг озоботитесь ответом на вопрос чем наследование отличается от агрегирования, может на шаг вперед продвинетесь в изучении ООП.
                                  • 0
                                    Ну, вы несколько путаете: использование/переопределение методов родительского класса и использование их в перегружаемом методе — разные вещи. При чём последнее никак не описывается в требованиях к языку, соответствующему парадигме ООП.

                                    А то, что вы хотите подменить понятия, не характеризует вас как хорошего собеседника.
                                    • 0
                                      Что-то я не понял, это какие такие я понятия подменяю? Хороший собеседник с вас получился бы если бы вы признали, что в JS не реализованно наследование, о чем я вам убедительно продемонстрировал. Если же вы этого не признаете — это вы подменяете понятия — наследование для вас тоже самое, что агрегация… ну что же — жаль…
                              • –1
                                function A() {
                                  this.M1 = function() {
                                    console.log("m1 from A");
                                  }
                                }
                                
                                var instanceA = new A();
                                
                                function B() {
                                  this.M1 = function() {
                                    instanceA.M1();
                                    console.log("m1 from B");
                                  }
                                }
                                
                                B.prototype = instanceA;
                                
                                var instanceB = new B();
                                instanceB.M1();
                                


                                Если я вас правильно понял.
                            • 0
                              something.prototype.someFunction = function(a1, a2, a3)
                              {
                              somethingVeryParent.prototype.someFunction.call(this, a1, a2, a3);
                              }
                              
                              

                              если мне не изменяет память.
                              • 0
                                А вот у меня устойчивое впечатление, что на JS (хоть вы и не показали весь код) Вы реализовали совсем другую концепцию, а не переопределение функции в наследнике. По сути JS подменяет это решением вида:

                                	public class O
                                	{
                                		public object prototype;
                                	}
                                
                                	public class A : O
                                	{
                                		public void M1()
                                		{ }
                                	}
                                
                                	public class B : O
                                	{
                                		public void M1()
                                		{
                                			A a = prototype as A;
                                			if (a != null)
                                			{
                                				a.M1();
                                			}
                                		}
                                	}
                                
                                


                                Причем присвоение прототипа мне почему то надо делать за рамками класса. (в коде это не показано)

                                А я хочу, чтобы я мог создать конструкцию именно наследования и переопределения.
                        • 0
                          4..valueOf(); // 4
                          

                          Даже у примитивов есть свойства

                          • НЛО прилетело и опубликовало эту надпись здесь
                    • –1
                      Буч идет лесом. Для ООП важно понятие интерфейса (или контракта), понятие класса нафиг не нужно.
              • –1
                Теперь про класс. Как по вашему для чего в языках ООП присутствует класс и его эксземпляры объекты?
                • 0
                  Вас интересует исключительно моё мнение, или академическая информация? Я могу предоставить и то и другое, просто не понимаю, вокруг чего спор? Мы говорим о принадлежности конкретного языка к конкретной парадигме. В JS нет классов (кстати, в спецификации ECMAScript 6 есть классы), вместо этого в JS есть прототипы, благодаря которым JS реализует один из стилей ООП, который называется «Прототипное программирование».
                  • 0
                    Меня интересует в частности ваше мнение. Что касается академических мнений они мне известны и вызывают неприятие :) Поэтому меня интересует то, почему люди ведутся на такие академические мнения.
                  • 0
                    Нет, нету. Это на самом деле просто сахар, реально на класс это не похоже:
                    -нельзя создать методы или свойства класса (ну, статические)
                    -нельзя переназначить только геттер или сеттер метода (нужно повторно назначать оба)
                    и так далее
                    • 0
                      -нельзя создать методы или свойства класса (ну, статические)

                      Вы ошибаетесь, любая функция в JS является объектом, поэтому любой класс сможет иметь статические методы или свойства.

                      -нельзя переназначить только геттер или сеттер метода (нужно повторно назначать оба)

                      Можно.

                      class Apple {
                          get color: function() { ... }
                      }
                      
                      • +1
                        Еще раз, внимательно.
                        Это будет свойство, не более. Метод класса не будет далее наследоваться, то есть

                        class Fruit {}
                        Fruit.add = function(){}
                        class Apple extends Fruit {}
                        Apple.add //=> undefined
                        


                        И внимательно перечитайте, что я написал. Переназначить, не просто назначить. Приведу пример, который у меня был. Решил через событийную модель.

                        class Player {
                            ...
                           get volume(){return this._volume}
                           set volume(val){...}
                           ...
                        }
                        class MetaPlayer extends Player {
                           set volume(val){
                               return; //нужно было заблокировать функционал
                           }
                        }
                        
                        var p = new Player;
                        p.volume; // => 100
                        
                        var p = new MetaPlayer;
                        p.volume; //=> undefined. Геттер для метода отнаследованного класса "потерялся".
                        


                        Вы, видимо, не работали либо с ООП, либо с классами в es6, раз так радостно это утверждаете.
                        • 0
                          Да, методы класса не наследуются, согласен.

                          Геттер не потерялся, просто, по всей видимости, геттер для класса ищет только в экземпляре класса, без «заглядывания» в прототип. Я не уверен, это просто мои соображения на этот счёт.

                          P.S. Да, ES6 на практике не применял, вы правы. Только читал спецификацию.
                          • +1
                            Вот. А в реальности этот весь class — это просто сахар поверх Object.create.
              • –2
                > Вместо класса — объект-прототип

                Каким образом мне в JS объявить некий тип или если он уже объявлен в программе узнать к какому типу он относится?
            • +1
              Я бы хотел услышать как в JS описать класс :)


              function ClassExample() {
                    this.a = 1;
                    this.method = function () {
                            return this.a;
                    }
              }
              


              применять:
              var obj = new ClassExample();
              obj.method();
              
              • 0
                Я вижу, что вы описали функцию с двумя переменными :) и вызвали метод, находящийся по ссылке в одной из переменных

                Это такой интуитивно понятный сахарок для программистов :) — нет это как минимум криворукое название концепций
                • +3
                  я не виноват, что в JS класс описывается, также как и функция. Это особенности синтаксиса.
                  Также как я не виноват, что в объектном Паскале класс описывается словом object, а не class.

                  Я получил объект, если я сделаю вызов с new ещё раз, то получу другой объект.

                  Это особенности синтаксиса
                  • –3
                    Понятно. И вас я не виню. Я хорошо знаю особенности это синтаксиса. Я лишь обращаю внимание на неестественность. Это мелочи. Скоро пойдем дальше в развенчании мифа о том, что в Js есть ООП
                    • 0
                      Для начала давайте определимся, что есть ООП
                      • 0
                        Выше я привел мнение классика Буча. Я с ним полностью согласен.
                        • 0
                          выше я ответил. Я если чо, не особо в востороге от JS, но надо признать все 3 пункта там выполняются.
                        • 0
                          Программирование — не художественная литература. Многое меняется. Если ЯП расширяется новой функциональностью, это ведь не означает, что это другой ЯП. Так же и со всем остальным, включая парадигмы.
                          • –3
                            Программирование — я склонен считать наукой. А в науке принято не использовать термины, которые имеют определенное значение в случаях, когда это значение меняется. Принято в таких случаях вводить новый термин и если нужно показывать похожесть или различия. В данном случае различий существенно больше. Смешивать это все в одно не правильно.
                        • +2
                          Наиболее обобщенное понятие ООП самым лаконичным образом выражается в эрланге. Нужны лишь три условия наличия объекта:

                          1) Объект держит внутри себя состояние
                          2) Существует ссылка на объект и можно её передавать
                          3) Можно передавать сообщения объекту (вызывать методы)

                          Эти условия покрывают все языки и виртуальные машины, где можно писать код в стиле ООП.

                          Классы не имеют прямого отношения к основной концепции ООП, но часто вводятся для формализации сущностей.
                          • 0
                            Все пункты кроме 3 (хотя то же можно), присутствуют в языке Си, хотя его никто не считает ООП языком.
                            Это очень странно…
                            Всё же где то тут есть путаница, Объектно Ориентированное Программирование и язык где есть объекты видимо разные вещи. Все фичи ООП можно реализовать и в Си только вот выглядеть это будет не очень… и к слову станут прослеживаться параллели с JS.

                            В JS работа с объектами мне не нравится, она постоянно вызывает боль, куча способов выстрелить в ногу и постоянный оверхед. Главная проблема JS в том, что в нём до сих пор все ООП фичи как бы с боку прикручены и с большим количеством эффектов.
                    • +7
                      Я лишь обращаю внимание на неестественность

                      То, что вы привыкли к другому синтаксису — совершенно не означает, что этот синтаксис неправильный.
                      • –10
                        Любой человек привык к такому синтаксису, где понятия языка определяются соответствующим синтаксисом, а не когда думаем класс, а пишем функция.
                        • +3
                          Болтология какая то :)
              • 0
                Давайте посмотрим на немного измененный код:

                function ClassExample() {
                      var a = 1;
                      this.method = function () {
                              return a;
                      }
                }
                
                

                Что такое в этом случае a?

                • +1
                  private переменная
                  • 0
                    Давайте усложним пример

                    function ClassExample() 
                    {
                           var a = 1;
                     
                          this.SetUTC = function SetUTC(argUTC)
                          {
                             var rd = new RequestData()
                             rd.OnJSONProcessing = function (argJSON)
                             {
                                a = argJSON;
                             }
                         }
                    }
                    


                    Попробуйте угадать в какой переменной какого «класса» будет значение argJSON?

                    • +1
                      Здесь ровно одна private переменная `a` и она будет в том же инстансе ClassExample. Лямда-функция OnJSONProcessing хоть и создаётся каждый раз заново, вовсе не создаёт новую переменную `a`. Ровно то же самое, но чуть по другому, можно было бы на C++ написать:

                      class Example {
                        int a;
                      public:
                        void SetUTC(utc) {
                          new RequestData().OnJsonProcessing = [this](json){
                            this.a = json;
                          };
                        }
                      };
                      
                      • –4
                        О как замечательно мы нарушили private область видимости — фиерично :) и язык к этому не имеет отношение — лямды всякие как раз и нарушают ООП.
                        • 0
                          нарушили private область видимости


                          Разжуйте мне недалёкому где я ошибся: в примере на C++ или может я не смог понять как работает ваш пример на JS?

                          Лямбда это тот же самый функтор записанный более удобным способом. Функторы ведь ООП не нарушают? Я бы мог сделать отдельный объект класса ProcessingResultCallback, передать ему в конструктор указатель на this.a и он бы сделал *a = json. Или указатели тоже нарушают ООП?
                          • –2
                            Вот если бы Вы сделали так — то проблем не было бы. А так есть. Вдруг откуда не возьмись… лан, меня заминусовали — ухожу я от вас, до свидос, Не жалею, не зову, не плачу,
                            Всё пройдёт, как с белых яблонь дым.
                            Увяданья золотом охваченный,
                            Я не буду больше молодым.
                            • +1
                              Какие ещё яблони? Мы лямбды в ООП обсуждали.
                              • –4
                                это ругательство — забудьте — лямбы их в ООП нет. Это страшное нашествие киборгов функционального программирвоания
                              • –3
                                речь о том, что я вам скоро не смогу отвечать :) из-за демократии большинства ушлепков, которые не понимают за что минусуют.
                          • –6
                            > Лямбда это тот же самый функтор записанный более удобным способом.

                            ужас, если это более удобный способ — то пипец — плаколо мое образование… это новомодный бред, не имеющий ничего общего не с удобностью, не с понятийностью, ни с чем… это возврат к ассемблеру, только под определенным соусом.
                          • –1
                            И еще не путайте — вы не смогли бы сделать так в «private область видимости»… опять вы господа попутали все понятия :) Попробуйте в калбеке функции присвоить в привайт свойство объекта… вы о чем вообще?
                            • 0
                              Вы лучше с примерами кода — а то так непонятно. Например «в калбеке функции присвоить в привайт свойство объекта» — что это значит? У функции есть колбек? И что там за объект такой — тот который функтор или что то другое?
                              • 0
                                Вот давайте вы напишите сами вначале свой пример кода — а я уже потом объясню почему он не компилируется. Я же оталкивался от ваших слов «и он бы сделал *a = json» — если a private — вы получили бы ошибку компиляции.
                                • 0
                                  Возьмём уже написанный пример на C++ где «class Example» — что в нём не так?
                                  • 0
                                    Нет тут примера С++, я писал примеры на C#… а о чем Вы я вообще не понимаю, какой class Example?
                                    • 0
                                      Я об этом примере:

                                      class Example {
                                        int a;
                                      public:
                                        void SetUTC(utc) {
                                          new RequestData().OnJsonProcessing = [this](json){
                                            this.a = json;
                                          };
                                        }
                                      };
                                      
                                    • –3
                                      а понял, вы все про лямды — успокойтесь — они нарушают ООП. Вы фразами дальше говорили не о лямдах, перепишите тогда свой пример без лямд.
                                      • 0
                                        > Я бы мог сделать отдельный объект класса ProcessingResultCallback>

                                        Вот этот пример я обсуждал, напишите его полностью тогда уж
                                        • 0
                                          Как то так:

                                          class MyCallback: public IntCallback {
                                            int* target;
                                          public:
                                            MyCallback(int* ptr) {
                                              target = ptr;
                                            },
                                            override void Invoke(int data) {
                                              *target = data;
                                            }
                                          };
                                          
                                          class Example {
                                            int a;
                                          public:
                                            void SetUTC(utc) {
                                              new RequestData().OnJsonProcessing = new MyCallback(&a);
                                            }
                                          };
                                          
                                          • 0
                                            Ну и вы не видите разницы? Теперь объекты имеют дело только со своими свойствами, а не с чужими. (и это не то, что вы вначале заявили)
                                            • 0
                                              Неа, не вижу. Честно :) Я вижу здесь тот же самый анонимный колбек (closure, как это часто говорят в JS) который превратился в громоздкую конструкцию MyCallback (кстати, этот класс можно было бы объявить внутри метода SetUTC — С++ позволяет это). Кажется в Java было нечто похожее: чтобы подписаться на какое то событие (event) или указать колбек в асинхронном вызове надо было городить кучу фабрик функторов. Как только ввели лямбды — стало возможным обходиться без этого леса фабрик.

                                              Кстати, что насчёт модного нынче способа написания асинхронного кода при помощи т.н. промисов Они были давным давно в JS (потому как там всё для этого есть) и станут частью стандарта JS в ES6; они стали частью C# в виде Task и стали частью C++ в виде std::promise. Эти промисы превращают нечитабельный асинхронный код разбросанный по колбекам-методам класса написанными по всему огромному cpp файлу в читабельную последовательность:

                                              doStuff1().then([](result1){
                                                return doStuff2(result1, 123);
                                              }).then([](result2){
                                                return doStuff3(result2, 456);
                                              });
                                              


                                              Это C++ с т.н. полиморфными лямбдами которые станут частью стандарта. Как по мне, так упаковка асинхронного таска в виде отдельного объекта «промис» — прекрасный пример ООП. Без лямбд с всеми их фичами (доступ к членам класса, к локальным переменным метода и к её параметрам) — написать этот код невозможно.

                                              Кстати, этот код на C++ фактически ничем не отличается от такого же кода на JS.
                                              • –3
                                                Ну, что я могу поделать, не видите, значит надо учится
                                                • +1
                                                  Учиться надо вам.
                                          • 0
                                            Ну, и в C# аннонимные методы предоставляют доступ к свойствам текущего класса (как в данном примере), но зато там есть хотя бы ограничение — аннонимные методы не имеют доступа к параметрам ret, out — т.е. тем которые были переданны по ссылке.

                                            Иначе, позволительно изменить любую переменную в любом классе. Так вот аннонимные методы, особенно в вариации JS, в которой нет ограничений как в C# — стимулирует разработчика писать гавно — код, без объектной декомпозии. Уже становится не важно, какому классу принадлежит переменная — мы можем работать с ними как с глобальными переменными, а именно это вытравливали в C# из-за нарушения объектности и «мрака» работы с ссылками.
                                            • 0
                                              изменить любую переменную в любом классе + из любого места.
                                      • +1
                                        По вашей логике, четко прослеживающейся на протяжении всего треда: лямбды нарушают ООП, значит в языке с лямбдами ООП нет. И как с этим жить?
                                        • –1
                                          Не так, лямды — это как в С++ есть смешение объектного подхода со структурным в силу историчности. C# долго «отмывали» от структурного подхода, но теперь загадили лямдами. Поэтому если человек использует лямбы в C# — значит он отказался от ООП. Но может и не отказываться, просто убрав бред using System.Linq
                                          • –1
                                            а в JS увы, только и есть лямды если хотите, но ООП там и не пахнет.
                                            • 0
                                              вразумительных ответов на мою аргументацию до сих пор нет, есть 15 минусов кармы — так это неучи, они даже тут пару фраз связать не могут, чтобы мне что-то возразить :) Все пока я спать — пишите в личку.
                                          • 0
                                            Но это лишь парадигма, подразумевающая манипуляцию объектами. Ее можно придерживаться, а можно отказаться. И решение об используемом подходе принимает разработчик, вне зависимости от того, JS это или C#. Просто один язык оказывается более строгим, другой — нет. К тому же сравнивать JS с C* и на основе этого говорить о наличии или отсутствии ООП не совсем корректно: это слишком разные языки.
                                          • +2
                                            Расскажите про «отмывание» и откуда в C# появился этот страшный-ужасный «структурный подход» если учесть, что первые версии C# были как две капли воды похожи на всю из себя объектно-ориентированную Java.
                                            Поэтому если человек использует лямбы в C# — значит он отказался от ООП.
                                            «Он предал веру! Сжечь еретика!»
                                            Вам бы во времена святой инквизиции родиться :)
                        • +1
                          лямды всякие как раз и нарушают ООП.

                          Докажите это утверждение. Начните с определения того, что такое «лямбда».
                    • 0
                      Ну и еще, если мы изменим пример так

                      function ClassExample()
                      {
                      this.a = 1;

                      this.SetUTC = function SetUTC(argUTC)
                      {
                      var rd = new RequestData()
                      rd.OnJSONProcessing = function (argJSON)
                      {
                      this.a = argJSON;
                      }
                      }
                      }

                      Объясните почему это не будет работать? Почему с якобы с private переменными работает, а с public нет?
                      • 0
                        Зачем вы пишете ерунду, а потом спрашиваете почему ерунда странно работает?

                        Есть вполне общепринятые соглашения для написания кода и аннотации с поддержкой в IDE. Если вам нужно писать код, то никто не мешает это делать, если троллить на тему того, что на JS при желании можно писать говно, то тут уже другой вопрос…

                        Вот скрин на тему того как работать с private, protected, public полями в JS. Никаких проблем, варнинги, автокомплит и подсказки по типам, все на месте.

                        Скрин с ворнингом:


                        Скрин с пофикшеным кодом:
                      • 0
                        Это будет работать если написать как надо:

                        function ClassExample()  {
                          this.a = 1;
                        
                          this.SetUTC = function SetUTC(argUTC) {
                            var rd = new RequestData()
                            rd.OnJSONProcessing = function (argJSON) {
                              this.a = argJSON;
                            }.bind(this);
                          }
                        }
                        


                        Эта проблема широко известна как lexical scoping и чтобы её решить более удобным способом (без явного bind) в ES6 вводят arrow functions у которых this привязан к this того места откуда их вызвали:

                        function ClassExample()  {
                          this.a = 1;
                        
                          this.SetUTC = function SetUTC(argUTC) {
                            var rd = new RequestData()
                            rd.OnJSONProcessing = (argJSON) => {
                              this.a = argJSON;
                            };
                          }
                        }
                        


                        Кстати, в вашем примере this.a перестало быть приватным членом класса. Однако и эта проблема широко известна и может быть решена при помощи использования вместо «a» какого нибудь неугадываемого случайного числа или более изящно при помощи Symbol добавленного в ES6:

                        var a = new Symbol('a"); // visible only to ClassExample
                        
                        function ClassExample()  {
                          this[a] = 1;
                        }
                        
                        ClassExample.prototype.SetUTC = function SetUTC(argUTC) {
                          var rd = new RequestData()
                          rd.OnJSONProcessing = (argJSON) => {
                            this[a] = argJSON;
                          };
                        };
                        


                        Даже колбек OnJSONProcessing я бы мог вынести в прототип и сделать его private при помощи Symbol, но не хочу, потому что код станет запутаннее (фактически будет это выглядеть так как это было бы написано в старом C++ — на каждый колбек отдельный метод).
                        • –2
                          вы сами то хоть поняли, что вы отчаено ищите костыли при криворуком языке? лан хабратушканчики отхабрили — мне сложно комментировать — ушел, сугубо поняв что вас — горбатых токо могила исправит
                          • 0
                            Я вам даже плюс поставил, чтоб комменты писать могли, так что придержите свои эмоции. А костыли это городить отдельный класс функтора на каждый колбек.
                            • 0
                              Ну хорошо. Вы понимаете, что в ООП каждый класс имеет свою область ответственности? На выском уровне это означает, что один объект не может прямо менять поведение другого объекта. На низком это указывает о непересечении областей видимости — отсутствие работы с данными в глобальной куче.

                              В примере на JS эта область ответственности нарушена — «чужой» метод непосредственно меняет состояние объекта. В вашем примере на C++ нет — вы сами передали переменную, в которую попросили записать результирующие значение.
                              • 0
                                Это не чужой метод, а метод созданный в том же классе для изменения переменной того же инстанса. Колбек не может менять состояние чужого класса. Вот например два класса:

                                class A {
                                  B b;
                                public:
                                  void DoStuff() {
                                    Http.Send("GET", "/a/b/c").then([](rsp){
                                      b.SetData(rsp);
                                    });
                                  }
                                }
                                
                                class B  {
                                  Data data;
                                public:
                                  void SetData(Data) {
                                    ...
                                  }
                                }
                                


                                Колбек в A имеет доступ к состоянию A, но не к состоянию B. Он может менять состояние A потому что написан внутри A. Точно также любой метод в A может менять состояние A. В этом смысле я не вижу разницы между колбеком и методом. Я бы мог сделать старым способом — унаследовать A от некоего IHttpResponseHandler и передать указатель на A вместо колбека — но колбек выглядит чище.

                                Вот если бы колбек внутри A мог менять состояние B напрямую, то это было бы нарушением области видимости. Однако было бы это нарушением принципов ООП я бы ещё поспорил. Всё таки разделение на public/private — всего лишь синтаксический сахар, а не само ООП.
            • +2
              Я бы хотел услышать как в JS описать класс :)

              В ES5 никак. И это не мешает JS быть ООП языком. С чего вы взяли, что наличие классов — обязательное требование для ООП языка?
              • +4
                Не кормите троля.
    • +11
      А про ООП в JavaScript — надо отвечать — нет ООП в JavaScript. А потом уточнять недореализация. Если вопрошающий не соглашается — вставать и уходить — с такими людьми не сработаетесь.

      Какое знатное невежество.
      • +6
        Что-то мне подсказывает, что на собеседовании, где сложность вопросов идет по нарастающей, автор коммента вряд ли добрался бы до вопросов по ООП.
  • +5
    Почему перед исходным кодом jQuery стоит восклицательный знак?

    интересно было бы прочитать ответ на этот вопрос. сам не нашел.
    • +5
      выражение function () {} синтаксический анализатор не поймет, так как думает, что это объявление функции хотя мы имели в виду создание выражения возвращающего функцию.
      ! — «унарное не» предполагает, что после него идет выражение, так что все становится хорошо и синтаксической ошибки не происходит :)

      можно еще
      (function () {})()
      или
      (function () {}())
      написать, результат тот же.
      • 0
        а мне вот

        void function(){
        }()
        


        как-то по душе еще
        • 0
          Я тоже всегда использую этот способ, правда у него есть два фатальных недостатка:

          1. Такой код плохо оптимизируется компилятором (к сожалению не могу вспомнить где лежит ссылка на более детальное объяснение)

          2. Goggle Closure Compiler очень не любит это способ.
      • 0
        ! почему-то во многих гайдлайнах стал иметь признак модуля.
      • 0
        Спасибо за ответ. Когда искал — эти примеры видел. Но я подумал, что речь идет о другом восклицательном знаке:
        /*!
        * jQuery JavaScript Library v2.1.1
        * jquery.com/
        *…
        */

        Так как того, что указан в вашем ответе, в исходниках я не нашел.
    • +2
      !function() { console.log(«работает»); } () === (function() { console.log(«работает»); })();

      function() { console.log(«не работает»); } ()
  • 0
    про CORS, кстати, очень часто вопросы задают. Рекомендую всем поизучать новую спецификацию XHR, заголовки для CORS, узнать, что был такой XDR, и какие есть способы кроссдоменных запросов

  • +2
    Еще вспомнил пример, который хорош для скайп собеседований.

    Объясните работу этого кода:
    (function () {}).call({})
    


    Если человек не понимает что это, и пытается тупо выполнить код в консоли, ему это ни капельки не поможет :)
    • +3
      Не совсем понял, что тут необходимо объяснить?
      Что мы создаём функцию и вызываем на пустом объекте?
      • +1
        Есть у меня товарищ который любит называть это анонимным методом анонимного объекта :)
        Ну а так, да. Такой ответ говорит о том, что с человеком есть о чем говорить.
    • 0
      Объясните работу этого кода:
      (function () {}).call({})
      


      Довольно близко к
      new function () {}
      

    • 0
      Вот теперь, после вашего комментария, он вобьет эту строчку в гуглояндекс (во время скайп собеседования) и выдаст чужой ответ за свой
      Можно начинать придумывать новый пример :)
  • –4
    Итак, оставшиеся без ответа комментарий 1 и комментарий 2 показывают, что «ООП» JS по сути нарушает все мыслимые правила реального ООП — как то нарушение областей видимости, так и подмену наследования агрегированием. На этом откланиваюсь, не понимающие могут долго минусовать, а умеющие думать — могут задуматься, что не всюду где на заборе написано дрова, они там есть.

    И о том пройду ли я собеседование по вот таким формальным правилам, где нужно, чтобы у человека не было собственного экспертного мнения, и где собеседования проводят молодчики еле написавшие пару программ, но позволяющие себе оценивать знания других людей.
    • +8
      А Вы знаете, что можно программировать используя принципы ООП совершенно без поддержки со стороны языка! Например, на Assembler'е или в Pascal используя ручную эмуляцию виртуальных функций (так же храним ссылки на методы).

      Как мне кажется под ООП подразумевают изменение мыслей в сторону объектов. Если раньше мы размышляли алгоритмами, данными, то теперь стараемся думать объектами. Вот, например, какой-то манеджер, вот словарь, вот интерфейс, вот описание нашего объекта. Полагаю именно это видение позволило думать иначе, строить менее связанные системы, разруливать обязанности и т. п. Хотя так же встречается мнение, что это хорошо проданное под соусом обычное структурное программирование (хотя какая нам разница, главное помогает решать часть проблем).
      • –8
        К сожалению, без поддержки языка думать объектами не получается, точнее думать можно, но на код это не повлияет, если нет соответствующей поддержки.

        Но этим комментарием наконец-то было признано, что JS не имеет как минимум полноценной поддержки ООП. О чем я и сказал в самом начале. А так поддержка которая есть скорее ведет к несуразностям, можно конечно за не имением лучшего, как то к этому приспособится — но и всего лишь.
        • +1
          Так и вижу картину…

          Внезапно в голову закралась мысль, а вдруг, вот эти данные и эти функции, это нечто большее, чем алгоритмы, и решают они какую-то определённую задачу! А может это объект и их можно объединить!? Тут сзади удар чем то тяжелым! И злобное хихиканье javascript'а:" я не позволю тебе думать объектами!".

          :)
          • –1
            к сожалению, именно так и есть — ни какого юмора :)
          • –2
            у меня реальная ломка, когда сажусь за JS после C# :)
            • 0
              Вы просто думайте о том, что это языки для разных целей.

              Я, как-то пробовал использовать C# для скриптования простых задач (для сборки проектов), так жутко… Столько лишних действий, по сравнению с msbuild, хотя там используется синтаксис xml!

              Так же и использования C# для простых действий: добавить-удалить узел, обработать событие и т. п. — слишком сложно. Но если Вы делаете громадное приложение в браузере, то использовать javascript очень сложно. Поэтому используют разные конвертеры из языков с типизацией и т. п.
              • 0
                > Поэтому используют разные конвертеры из языков с типизацией

                Можно подробнее, может ссылку какую то? интересно посмотреть как это делают…
                • 0
                  scriptsharp.com/

                  ну или typescript!
                  • 0
                    Ну и пробовали пользоваться? Я так понимаю переводит C# на JS? На сколько серьезный код может перевести?

                    Возможно это и выход, мне то до лампочки — пусть там JS гавно код генерирует с объектного C#, по сути действительно JS может притендовать на уровень машиного языка, а не на высокоуровневый язык.

                    Я заодно пропадут вакансии с бредо собеседованиями на программирование на JS :)

                    P.S. Кстати вот вам и критерий — пусть попробуют обратный конвертер написать с JS на C# — поржем :)
                    • 0
                      Это невозможно из за того, что некоторые конструкции невыразимы в C#. Верно и обратное — не всё из C# можно выразить на JS.
                    • 0
                      Тулза которая переводит C# на JS есть и она позволяет писать очень сложные проекты (например Office 365). Однако с TS она ничего общего не имеет.
                  • 0
                    пишет ошибку prntscr.com/46ia58, чтобы это значило?
                  • 0
                    TypeScript видимо посерьзнее будет. Тем кто любит Википедию как достоверный источник :)

                    TypeScript отличается от JavaScript возможностью явного определения типов (статическая типизация), поддержкой использования полноценных классов

                    … т.е. общепризнано, что JS не поддерживает ООП, и вот попытались сделать надстройку над языком — поюзаем… звучит неплохо.
                    • 0
                      Не надо путать статическую типизацию (которая в TS динамическая) и ООП. Идея TS было в том, что он будет выглядеть как следующая версия JS (ES6) и за счёт кодогенерации будет позволять использовать конструкции из ES6. Однако комитет ES6 немного изменил направление и теперь у TS фактически свой синтаксис, несовместимый с ES6.
                    • 0
                      Вы похоже не понимаете разницу между языком программирования и его синтаксисом, раз говорите, что JS не поддерживает ООП, а TypeScript, по сути являющийся синтаксическим сахором для JS, поддерживает. В языках программирования в основном важна семантика, то есть значение той или иной конструкции языка, а не способ ее записи.

                      Код на TypeScript:
                      class Person {
                          name: string;
                          constructor(name: string) {
                              this.name = name;
                          }
                          getName() {
                              return this.name;
                          }
                      }
                      


                      И на JS:
                      function Person(name) {
                        this.name = name;
                      }
                      Person.prototype.getName = function () {
                        return this.name;
                      };
                      


                      Означает одно и то же на 100%. Просто пишется по-разному. Глупо говорить, что одно ООП, а другое нет.
                      • –2
                        Ну тут не удержусь и еще на последок скажу.

                        А что такое язык по вашему? Язык это и есть синтаксис, и то какие конструкции этот синтаксис позволяет описать и делает ли это удобно. Без этого идите программировать на ассемблере и фиерично высокоуровневые языки называйте синтаксическим сахором — ведь он вам не нужен.

                        К сожалению, практика показывает что как пишешь на языке так и думаешь. Я же не хочу отвлекаться на низкоуровневые забабоны недореализованного языка.

                        Если даже в MS пришли к выводу, что нужна обертка к недоязыку, ок — с этой оберткой еще терпимо можно программировать, и то потому что альтернативы нет.
                        • +2
                          Язык это и есть синтаксис

                          Вот я и говорю, не понимаете разницы. А между тем, это серьезное заблуждение. Свойства и возможности языка определяются абстракциями и семантикой конструкций, которые он предоставляет. Когда я пишу код, я думаю не о ключевых словах и операторах, скорее о формальных математический сущностях, которые я описываю, о том что значит мой код. Семантически, JS гораздо ближе к Lisp-подобным языкам (в которых, к слову, синтаксис вообще практически отсутствует и ограничен правилами расстановки скобок, а так же несколькими особыми формами) и думать на нем лучше в функциональной манере, но из-за его внешней си-подобности, JS часто неправильно воспринимается программистами. И остается абсолютно непонятым недопрограммистами, которые думают, что ООП — это наличие слова class в языке.

                          с этой оберткой еще терпимо можно программировать, и то потому что альтернативы нет

                          Есть аннотации, которые решают проблему удобства написания кода в IDE. Но вам нужно не эту проблему решать, у вас сложности с фундаментальным представлением о том, что такое программирование.
                          • –1
                            Ну, разницы не понимаете Вы. Я же не говорил, что язык только синтаксис, я говорил, что синтаксис определяет высокоуровневость языка как парадигмы. А противном случае все можно было бы написать в синтаксисе ассемблера. Я давал ссылку на статью, где среди прочего есть слова Флойда (тот который ввел в обиход термин парадигма программирования):

                            «Парадигма более высокого уровня абстракции — это конструирование иерархии языков, где программы на языке самого высокого уровня воздействует с абстрактными объектами, и переводят их на программы языка следующего более низкого уровня.»

                            Вот и он о том же гворит. JS по сути является языком низкого уровня, по сравнению с TS. Отличие в них такое, что TS вводит дополнительные понятия ООП, которые нет в языке низкого уровня, а потом компилирует/генерирует в язык машиного уровня. Да JS возможно хорош как машиный скриптовый язык, но это никак не отменяет того, что в нем нет ООП. Аналогично и С# и VB компилируется в CIL. А вы пытаетесь доказать, что можно сразу в CIL писать в ООП — нет это не так, вы заблуждаетесь.
                            • +1
                              Спорить с вами бесполезно, т.к. вы явно не понимаете о чем говорите.

                              Дам просто хороший совет, поизучайте другие ЯП кроме си-подобных. Советую Smalltalk и Lisp. И книжки по computer science почитайте, например SICP. Конечно если вам интересна тема языков программирования.
                              • –3
                                Дорогой Вы мой книжек и опыта у меня по сравнению с вами лет на 10 больше, поэтому оставьте свои советы при себе, да и языков я достаточно знаю :) А умершие языки учите сами если они вам нравятся: )
                                • +2
                                  Странно, опыта и знаний много, а глупости пишете.
                                  • –3
                                    Ну, это ваше исклюзивное мнение… сейчас для вас это глупости, может позже поймете, что это не так… видимо надо написать пару серьезных проектов, чтобы начать ценить ООП, и понимать каким языком его невозможно обеспечить.
                                    • 0
                                      Извините — но вы сильно напоминаете очередного «диванного» эксперта который «не работал — но осуждаю». Почитайте историю Smalltalk и Self. «Прототипное программирование» изначально создавалось на базе одного из классических представителей ООП — Smalltalk. В нем не может «не быть ООП» — он на нем основан! Серьезно — просто почитайте историю.
                                      • –2
                                        > В нем не может «не быть ООП» — он на нем основан

                                        Значит плохо основан :) То, что хотели видимо сделать, и то что получилось — разные вещи, хотя думаю вы заблуждаетесь, я конечно почитаю историю, но думаю для JS — ООП никогда не было первичным, поэтому и получилось то, что получилось.
                  • –1
                    Спасибо. Все перехожу на typescript, жаль что синтаксис не C#, но это мелочи — главное есть поддержка ООП.

                    Кстати, многое сказано в этой статье habrahabr.ru/post/173813/ Почему вам стоит использовать TypeScript

                    Основные недостатки JavaScript:

                    Динамическая типизация, которая вызывает множество регрессионных ошибок.
                    Отсутствие модульности. Нет ни модулей, ни классов, прототипное ООП рвет мозг тем, кто пишет на C++\Java\C#.
                    Неочевидное поведение во многих местах.
                    • –1
                      И кстати, забавно, что сразу после такого решения — все эти глуппые вопросы на собеседовании идут лесом… вот и покурите, какие действительно вопросы имеют смысл :)
                    • +2
                      Основные недостатки JavaScript


                      Ковыряю JS уже лет 10 и эти «недостатки» меня только смешат. Это не недостатки языка, а недостатки кодеров плотно подсевших на слово «class».
        • 0
          Вы знатный тролль :) Я не знаю, кому вы это доказали, но спорить с вами весьма забавно. Именно то, что так необходимо вечером пятницы :)
          • –3
            :) пусть так, только этот тролль многое сделал, чего многим и не снилось :)
            • +1
              Так я и не принижаю ни ваши статьи, ни ваши скиллы в программировании. А уж тем более не буду спорить, что в области биоинформатики и алгоритмов, вы, скорее всего, надерете мне зад, но это никак не относится к теме обсуждения. Если хотите похвастаться своими достижениями, я буду рад прочитать о них в хабе «Я пиарюсь».
              • 0
                Я не об этом :) Вечер пятницы проходил толскливо, я за пивом… а потом продолжим :)

                Но у Вас есть шанс подумать, что если язык для выражения концепции наследования и агрегации предоставляет одинаковые синтаксические конструкции — то с каким успехом он позволяет построить объектную модель?
  • 0
    Мне нравятся задание на рефакторинг. Даешь кусок кода, где часть нужно исправить, и часть оптимизировать.
    • 0
      А можно пример? Я добавлю в статью. Или, что еще лучше, несколько
      • 0
        А есть ли смысл сюда писать примеры? Пост популярный, наверняка после 300-400 комментариев попадет на страницы Гугла и Яндекса. А значит, большинство кандидатов на запрос в поисковике будут сюда попадать, вопросы и ответы читать. Соответственно, вопросы перестанут быть актуальными.

        В мире Java лет 10 назад было модно спрашивать, чем ArrayList отличается от LinkedList или чем абстрактный класс отличается от интерфейса. Ценность[1] ответа на оба вопроса была минимальной уже тогда, а сегодня тем более.

        С этими вопросами на JavaScript-интервью произойдет то же самое. Вопрос про new Date() вообще ничего не показывает. Гораздо интереснее спросить про время высокого разрешения, потому что если человек знает про window.performance.now(), то может и про другие аспекты Performance API ему что-то известно.

        [1] Для меня цель интервью — понять, насколько эффективным будет тот или иной инженер в работе, насколько успешно он будет решать задачи и насколько медленно при этом будет расти технический долг на проекте. Как оказалось, корреляция между тем, отвечает ли человек на такие вопросы, и его эффективностью практически не прослеживается.
        • 0
          В мире Java лет 10 назад было модно спрашивать, чем ArrayList отличается от LinkedList или чем абстрактный класс отличается от интерфейса.
          За 10 лет мало что изменилось.
          Может и не модно уже, а по-прежнему спрашивают.
  • 0
    Было бы круто, если бы кто-то написал что-то подобное про python, например.
  • –1
    Для ankh1989 (на комментарий habrahabr.ru/post/231071/#comment_7814413) и f0rk (на комментарий habrahabr.ru/post/231071/#comment_7814447):

    Для обсуждаемого примера ankh1989 вы показали костыль JS с использованием .bind(this) (что надо заметить, почему то фиерично спрашивают как о значимом понятии JS на собеседования как отдельную тему :) — хотя на самом деле это просто попытка исправить плохую реализацию языка, но не об этом).

    А Вы f0rk показали сравнение TS с JS, где почти не заметно отличие, и фиерично заметили, что раз так то ООП поддерживается в JS.

    Вот вам другой более ценный пример (не уверен, что сразу оцените, но покурив подумаете хотя бы):

    На TS

    GetData(argPageName:string)
    {
    this.CreateXMLHttpRequest();
    xmlhttp.open('GET', argPageName, true);
    xmlhttp.onreadystatechange = () =>
    {
    if (xmlhttp.readyState == 4)
    {
    if (xmlhttp.status == 200)
    {
    var serverResponse = JSON.parse(xmlhttp.responseText);
    this.OnJSONProcessing(serverResponse);
    }
    }
    }
    xmlhttp.send(null);
    }

    Компилятор перевел на JS как:

    RequestData.prototype.GetData = function (argPageName)
    {
    var _this = this;
    this.CreateXMLHttpRequest();
    xmlhttp.open('GET', argPageName, true);

    xmlhttp.onreadystatechange = function ()
    {
    if (xmlhttp.readyState == 4)
    {
    if (xmlhttp.status == 200)
    {
    var serverResponse = JSON.parse(xmlhttp.responseText);
    _this.OnJSONProcessing(serverResponse);
    }
    }
    };
    xmlhttp.send(null);
    };

    Тут два важных момента, которые превратили код в объектный.
    1. Метод GetData он привязал сразу к классу RequestData.prototype.GetData (почему это важно см. ниже)
    2. В TS стало возможно естественным образом в аннонимных методах обращаться к this — см. строку в примере this.OnJSONProcessing(serverResponse);
    и перевел он это используя другой костыль

    var _this = this;

    _this.OnJSONProcessing(serverResponse); (собственно, как и было в моем изначальном примере, и на что я ругался)

    Правда я в своем коде вначале не использвоал аннонимный метод, но TS заставил, т.к.

    кусок

    if (xmlhttp.readyState == 4)
    {
    if (xmlhttp.status == 200)
    {
    var serverResponse = JSON.parse(xmlhttp.responseText);
    instance.OnJSONProcessing(serverResponse);
    }
    }

    у меня был выделен в отдельный метод A

    и запись в TS xmlhttp.onreadystatechange = this.A не работала. Почему?

    Да потому, что компилятор в этом случае не использует костыль описанный выше, и тем самым появляется различие где на самом деле метод класса, а где по сути подпись на событие, через аннонимный метод.

    Вот такого рода разведения понятий в разные углы и строгое использование синтаксиса (+без костылей) для этого позволяет писать не гавно код, а код соответствующий ООП, причем не напрягаясь на знание внутримашинных костылей JS.
    • +3
      Хватит смешить людей, просто признайте, что вы не знаете JS и не умеете на нем программировать. Чисто формально, метод «класса» в JS — это функция лежащая в прототипе конструктора.

      Запись:
      obj.handler = function () {}.bind(this)
      

      это просто создание функции выполняющейся в контексте текущего объекта.

      Оба примера кода значат одно и то же. То что вы говорите, можно сравнить с утверждением, что англичане не могут понимать, что такое стол, только потому, что называют его «table» а не «стол».

      Завязывайте уже с этой бессмыслицей и погуглите, что такое денотационная семантика, например. Возможно вы станете проще относиться к синтаксису языков и глубже понимать их возможности.
      • –6
        Ладно, пошли уже слюни, когда поймете о чем вам говорят — продолжим, пока полностью мимо и ощущение, что даже не попытались понять о чем речь.
        • +4
          Да что же тут понимать то :) Вы утверждаете, что стрелочка — это ООП, а «bind(this)» — не ООП, class — ООП, а prototype — не ООП и так далее в том же духе. Серьезно, я не понимаю, зачем вы с таким упорством выставляете себя болваном?
          • –3
            Это у вас такой уровень понимания, я же говорил о другом.
          • 0
            Пардон, что лезу в ваш холивар.
            Поддержу — классовое или прототипное, оно всё равно — ООП.
            Но вот эта вся историческая мутагория в JS с контекстом и костылями типа bind — это вообще не про то. К чему это упоминать?

    • 0
      GetData(argPageName:string)
      {
      this.CreateXMLHttpRequest();
      xmlhttp.open('GET', argPageName, true);
      xmlhttp.onreadystatechange = () =>
      {
      if (xmlhttp.readyState == 4)
      {
      if (xmlhttp.status == 200)
      {
      var serverResponse = JSON.parse(xmlhttp.responseText);
      this.OnJSONProcessing(serverResponse);
      }
      }
      }
      xmlhttp.send(null);
      }
      


      Это код на JS версии ES6 и вы его вроде называете правильным объектным кодом?
      • 0
        Она уже вышла?
        • 0
          Частично. Скажем arrow functions (те которые с => и с правильным this) уже есть в firefox (spidermonkey) и заканчивают делать в chrome (v8). А никакие другие фичи вы не используете в этом примере.

          т.е. спецификация уже есть и дело лишь за кодописателями браузеров.
          • –2
            Ну может они и прейдут к поддержке ООП. Я же никогда не говорил, что ООП или есть или его нет. Вот в версии Си — ООП тоже не было, в С++ была, но смешенна с структурной парадигмой, и только наконец в С# полноценная поддержка. Хорошо, если JS тоже движется в этом направлении, но на данный момент реализация ООП очень скромная (это если выразится политкорректно, я собственно с этого и начал не столь политкорректно — недореализация). Поживем посмотрим, но TS меня пока больше устраивает, они опередили столь необходимую полноценную поддержку ООП. Конечно, TS тоже не идеален по сравнению с С#, но много лучше JS, и эта не идеальность кроется в том, что ни раз они сами пишут в документации:

            «В данный момент замыкания являются единственным доступным в JavaScript способом реализовать инкапсуляцию данных — сохраняя и используя окружающие переменные, замыкания способны помнить информацию, недоступную вне замыкания. Это часто используется при указании обработчиков событий и других асинхронных обратных вызовов»

            «Классы и интерфейсы помогают при создании больших приложений на JavaScript, предоставляя механизм для определения того, как должен использоваться отдельный компонент приложения, если реализация этого компонента неизвестна. TypeScript производит сокрытие (инкапсуляцию) реализации класса на стадии написания кода, но у него нет возможности распространить это на исполнение программы, поскольку во время исполнения JavaScript все свойства объектов доступны, хотя будущие версии JavaScript, возможно, будут иметь ключевое слово private. При текущем же состоянии JavaScript единственный способ организовать инкапсуляцию — это использование модулей, когда сокрытие собственных переменных модуля производится с помощью замыкания.»
            • 0
              Значит ли это, что на ассемблере нельзя писать в стиле ООП потому что там нету слова «class»? Также я не вижу никаких проблем писать в стиле ООП на C. Другое дело, что на C# или Java писать в стиле ООП буквально заставляет сам язык, а JS не мешает, но и не заставляет писать в стиле ООП.
              • 0
                Да, ООП язык должен именно, что ЗАСТАВЛЯТЬ. Иначе это не ООП язык, а лишь имеет в той или иной степени поддеркжу ООП, JS в малой степени, ассемблер и С ни в какой, С++ ну или скажем FoxPro в достаточной, но не идеально и т.д.

                Да я видел извращения на Си, где с помощью ссылок пытались показать как выглядят ООП конструкции — но это игры для ума, а не промышленное программирование. Я уже в том возрасте, когда мне надо знать, что молодой программист не напишет гавно-код, и что ему хоть в какой то мере помешает язык с ООП, и такой язык который его именно ЗАСТАВИТ. А так же наличие в языке таких конструкций, в которых я реализуя ядро системы именно, что заставлю разработчиков писать код с лучшим качеством.
                • +2
                  ООП язык должен именно, что ЗАСТАВЛЯТЬ


                  Если бы вы с этого начали, никто бы даже не вздумал спорить, потому как вряд ли хоть один адепт JS рискнёт сказать, что JS заставляет писать в стиле ООП. JS скорее склоняет начинающих кодеров писать особо изощрённый говнокод :)

                  А так же наличие в языке таких конструкций, в которых я реализуя ядро системы именно, что заставлю разработчиков писать код с лучшим качеством.


                  Это кстати очень интересная тема. На Хабре как то рассказывали о проекте с кучей индусов (которые нафигачат такой говнокод даже на Java, что там сам автор Java ничего не поймёт) которых за счёт хитрой архитектуры проекта (какой то там большой конечный автомат) заставили написать работающий большой проект (что то в области VoIP 4G).
                  • –3
                    Ну, ок, я же не могу знать где возникнет синхронизация в мозгах… для меня это было естественно и не отделимо одно от другого, вот теперь выявили неявную аксиому, которая мной подразумевалась.

                    P.S.

                    мы нашли кое в чем консенсус :), хабратушканчики — те кто минусовал, но не слова не написал со мной в диалоге — возвращайте карму — мне статьи еще надо будет написать :)
                  • –2
                    Да, интересный пример, не читал… собственно, только в таких случаях и возникает понятие об архитектуре, иначе можно писать как угодно хорошо, а на завтра придется «шибко умный» и не оставит камня на камне от твоей архитектуры.
      • 0
        и по мне так лямды вида () => надо заменить на приятный синтаксис аннонимных методов C# — но вот это уже действительно придирка по синтаксису, поэтому можно потерпеть.
        • 0
          Вы про этот синтаксис?

          delegate() { System.Console.WriteLine("Copy #:{0}", ++n); }
          


          Это синтаксис JS с точностью до ключевого слова delegate/function. Позже в C# добавили стрелочные функции вида a => b или () => {… }. Собственно из C# эти стрелочные функции и пришли в JS.
          • –1
            Про этот, там еще += перед

            abc.SomeEvent += delegate() { System.Console.WriteLine(«Copy #:{0}», ++n); }

            и да, я же и говорил, что плохо вообще, что лямды изобрели — я бы их родил обратно :) А то, что в JS — там именно что другое — я уже выше объяснял (с неправильным this), и пусть вас не путает близкий синтаксис.

            • 0
              Омг, не позорьтесь, += — это синтаксический оператор для событий и MulticastDelegate, он вообще никакого отношения к анонимным методам отношения не имеет.
  • +1
    Вот кстати неплохая подборка вопросов вообще по фронтенду (включая js):
    github.com/shikolay/Front-end-Developer-Interview-Answers
  • –4
    Господа, я потестировал TypeScript — идея конечно хорошая, но оно мне так посадило браузерную игрушку, что Safari вообще отрубился и неотбражает графику canvas, а IE пытается, но оооочень медленно. Видимо не судьба мне веб в ООП кодировать — пока и скрости малые и интерпретаторы для этого не приспособлены.
    • +3
      Каким образом связаны TypeScript, ООП и производительность?
      • +1
        Да никаким, конечно. Просто не кормите тролля.
      • –5
        Естественно связаны :) TypeScript обеспечивает ООП JS, но к сожалению, Js скрипт исправит только могила, поэтому те накрутки генератора TS, которые делаются ради обеспечения ООП снижают существенно производительность.
        • 0
          Я даже соглашусь поиграть в эту специальную олимпиаду и спрошу далее: какие именно куски кода, полученного с помощью TS, замедляют производительность?
          • +2
            Мне кажется, что те, на которых регистрация в cyberrise.eu написана. Попытался зарегистрироваться и сайт лег.
            • +2
              Да.. Явно какие-то проблемы с производительностью


              Я правильно понимаю, что это один из примеров масштабных и сложных проектов, в которых мне бы стоило поучаствовать, чтоб опыта поднабраться?
            • +2
              Прочитал js код сайта

              • 0
                Охтыж ежык!!! Я тоже почитал, примеры, которые этот гуру ООП сюда кидал — это не примеры говнодизайна созданные специально для троллинга, это реальный код из его игрушки!

                cyberrise.eu/Game/js/AgentStateG.js
          • 0
            Оказывается, дело не в производительности. Подозрение на производительность получилось из-за того, что у меня видимо часто обновляются состояния разных объектов. А проблема именно в том, что я то расчитывал, что TS обеспечит мне нормальный ООП, но он не обеспечил. Кривые руки тех кто создавал JS не дали прямым рукам, которые сделали TS — гарантировать ООП.

            Напишу возможно статью на сей счет.
  • 0
    «какие именно куски кода, полученного с помощью TS» Детально я уже поленился смотреть, там думаю в комплексе — но факт один, как только возращаю реализацию на JS все работает, на TS просто глючит… там всего лишь несколько классов с наследованием.

    Регистрация написана на ASP и в ней проблем нет. Есть проблемы с MySQL — именно эта фигня тормозит, и отказывает по таймауту переодически, а так бы было все хорошо. Скорее всего надо переходить на MS SQL Server… хотя я бы послушал, как поднастроить MySQL — может кто и даст дельные советы — в личку желательно, сейчас там то что по умолчанию.

    • 0
      Т.е. вы даже не изучили в каких местах у вас организовались проблемы с производительностью? Чудес же не бывает — у всего есть причина.
    • +1
      MySQL тормозит? Что там за нагрузка такая?? У нас 2.5к запросов в секунду и не тормозит… (там правда кеш еще перед ним в виде монго и варниша, но это мелочи :))
      • +3
        MySQL тормозит, JS тормозит, явно проблемы в технологиях, а не в том, что у кого-то руки из жопы.
        • –1
          Тормозит не JS, а код сгенерированный с TS на JS. Можно конечно трахат… и дальше с такими технологиями, думая что что-то не так с руками, только вот в других технологиях почему то таких проблем нет.
      • –1
        Так может надо сравнить сравниваемые вещи? Что у Вас без кэша и прочего, на голой нулевой установке MySQL с настройками по умолчанию?
  • 0
    В дополнение к вопросу хочу сказать, что обычно вторым вопросом идет «Как сделать так, чтобы выводило цифры по порядку?»

    Здесь более уместен вопрос «Как сделать так, чтобы выводило разные цифры?».
    Поясню своё мнение — когда впервые увидел код, был абсолютно уверен что порядок вызова отложенных функций будет правильным и как следствие выведуться цифры по порядку(почему-то забыл об это извечной проблеме js c обращением внутри функии к переменной, которая была изменена). Даже после вашего дополнительного вопроса — не сразу понял о чём речь — пока не выполнил код. Иными словами — порядок вызова функций будет правильным(и как следствие порядок вывода), а вот значение я увсех будут разные — как следствие вопрос про разные цифры более точен и более понятен.
  • –2
    Меня пугает вот что: когда я искал работу и проходил собеседования, я мог ответить наверное на 80-90% этих вопросов, а теперь работая в компании 2 года и программируя на JS почти каждый день помню только процентов 20-30%.
    Опять закон Парето? Только 20% особенностей и возможностей языка нужно что бы писать на нём… странно это. На python получается помнить 60-70% от стандартного набора для собеседования.
    Вот то ли у меня с памятью плохо, то ли JS не самый лучший язык…

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.