1. JavaScript / Говнокод #26691

    +2

    1. 1
    2. 2
    3. 3
    function isNative (Ctor){
      return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
    }

    https://habr.com/ru/company/ruvds/blog/503634/
    >>> 5 интересных JavaScript-находок, сделанных в исходном коде Vue

    Запостил: gost, 26 Мая 2020

    Комментарии (46) RSS

    • Остальные четыре «интересные находки» — не меньший пиздец. Чего стоит функция определение «точного типа любого объекта»:
      function toRawType (value) {
          const _toString = Object.prototype.toString
          return _toString.call(value).slice(8, -1)
      }
      toRawType(null) // "Null"
      toRawType(/sdfsd/) //"RegExp"

      Пиздец, блядь.
      Ответить
      • Или вот, охуительная функция для мемоизации:
        function cached(fn){
          // Создаём объект для хранения результатов, возвращаемых целевой функцией после её выполнения
          const cache = Object.create(null);
        
          // Возвращаем целевую функцию в соответствующей обёртке
          return function cachedFn (str) {
        
            // Если в кеше нет подходящих результатов - функция будет выполнена
            if ( !cache[str] ) {
                let result = fn(str);
        
                // Сохраняем результат выполнения функции в кеше
                cache[str] = result;
            }
        
            return cache[str]
          }
        }

        Действительно, нахуя нам кэшировать 0, null, undefined, false, '' и NaN?
        Ответить
        • А для чего эта питушня используется? Может, в документации прописали, что там ровно один аргумент arg с условием typeof arg == 'string'.

          Ведь если придираться, то тут второй и далее аргументы не учитываются.
          Ну и с функциями как аргументами и прочей плохо сериализуемой питушнёй была бы питушня.
          Ответить
          • > typeof arg == 'string'

            И arg != '' ещё.
            Ответить
            • А зачем такое ограничение? Если ключ находится в пределах string, пустую строку нельзя будет ни с чем перепутать.
              Для пустой строки, так же как и для других не-идентификаторов сложновато будет получить значение через оператор "точка", но это и не нужно.
              Ответить
              • А тьфу, там не на ключ это ограничение, а на результат функции. Если результат пустой, то он не закешится.
                Ответить
        • удивительно, что при всем многообразии способов проверить наличие значения в кеше выбран самый мудацкий
          Ответить
          • > самый

            Ну всё-таки не линейным обходом кеша проверяют, и на том счастье.
            Ответить
            • сразу вспомнился кусок кода который мне однажды попал на ревью
              if(Object.keys(cache).includes(str)){/*...*/}
              Ответить
      • Там [object null] что ли получается после тустринга?
        Ответить
        • «[object tag]», где tag — одно из [Undefined, Null, Array, String, Arguments, Function, Error, Boolean, Number, Date, RegExp, Object]. Да, это по Стандарту.
          Ответить
          • Ну так эта питушня работает же, пока ССЗБ не попердолили Object.prototype.
            Считаю, что нормальный код. Хотя с бы матчил /^\[object (.*?\]$/ для надёжности.

            А вот с /native code/ - жопа, да. Там необходимо матчить более строго, иначе нормальные функции могут случайно задетектиться.
            Ответить
            • Но ведь это неинтуитивное говно, завязанное на мелкие внутренние детали реализации языка. Такая хуйня в других языках считается дурным тоном.

              > Там необходимо матчить более строго, иначе нормальные функции могут случайно задетектиться.
              А как матчить более строго, если «userFunction.bind(hui).toString()» выдаёт «native code»?
              Ответить
              • Неинтуитивное говно спрятано в документированную функцию.

                Про выхлоп bind писал ниже: формально он выдаёт нативный код. Функциушня рождает много философских вопросов и проблем с сериализацией.
                Ответить
                • Но оно лежит и воняет. Это классический «JavaScript-way»: сначала макаки привязываются к идиотскому поведению (toString() => '[object Object]'), а потом стандартизаторы вместо того, чтобы сделать нормальный API вроде «Object.prototype.getRawType()», поддерживают тупых макак, добавляя ещё больше тупой неочевидной хуйни.
                  Ответить
                  • Не, ну добавить Object.prototype.getRawType ничего не мешает, это же ортогональная питушня. Некоторые макаки, которые читают toString, после этого пересядут на getRawType.

                    А помните arguments.callee/caller? Их же вроде выпилили ради оптимизации хвостовой питушни.
                    Ответить
                    • > Не, ну добавить Object.prototype.getRawType ничего не мешает, это же ортогональная питушня.
                      Ну вот, а оно отсутствует. В результате нормальных, немакаковых способов получить этот самый raw type просто нет (или я о нём не знаю?).

                      Где-то мельком читал, что callee/caller удолили ради какой-то там безопасности, хотя верится с трудом. Хвостовая рекурсня выглядит правдоподобнее.
                      Ответить
              • А зачем вообще отличать native от не native? Функция и функция.
                Ответить
                • https://github.com/vuejs/vue/issues/11400
                  I checked all current usages of the isNative function in Vue and none of them
                  should cause any problems IMO. It's used to check whether the environment
                  has any Promise/Set/Proxy implementation and will only be bypassed if user
                  provide some environment with custom Promise/Set/Proxy implementation
                  with any native code string in their function bodies. If there is any, that should
                  be probably polyfills checking native support (imagine we may also have a native
                  code check inside a Promise polyfill). Though technically by only checking the
                  appearance of native code is not 100% correct, I don't think it make much sense
                  to change it because there's little actual benefits but the proposed change is much
                  harder to maintain.
                  Ответить
                  • Т.е. они перед обезьяньим патчингом проверяют, не запатчила ли эти функции другая обезьяна?

                    Какая архитектура )))
                    Ответить
                    • показать все, что скрытоvanished
                      Ответить
                      • Причём сраный leftpad вынесли в либу. А полифиллы, которые реально всем нужны, почему-то вкорячивают руками, проверяя не вкорячил ли их кто-то ещё. А потом поди ещё ловят баги из-за того, что какие-то тонкости реализации отличаются.
                        Ответить
        • И, кстати:
          > Object.prototype.toString.call([1, 2, 3]);
          < "[object Array]"
          > typeof [1, 2, 3]
          < "object"

          Какой прекрасный, консистентный язык!

          Кстати, вопрос к знатокам прекрасного языка: можно без таких уёбищных хаков определить, что объект является, например, RegExp'ом?
          Ответить
          • Можно x.constructor == RegExp. Однако, был какой-то подвох или под node, или ещё где-то из-за того, что могут быть разные инстансы конструктора в разных модулях.

            P.S. А для массива - Array.isArray.
            Ответить
            • Именно поэтому я за чёткие, единообразные решения единообразных задач, а не «в огороде constructor == RegExp, а в Киеве Array.isArray»:
              >>> type([1, 2, 3]) == list
              True
              >>> type({1, 2, 3}) == set
              True
              >>> type((1, 2, 3)) == tuple
              True

              Впрочем, справедливости ради, «Python» тоже посасывает: проверка на функцию там делается через «callable(obj)».
              Ответить
              • А что с callable(obj) не так? Если крякает как функция, значит функция.
                Ответить
                • Единообразность страдает. Надо чтоб гомоиконы всё было единообразно:
                  isinstance(obj, list)
                  isinstance(obj, tuple)
                  isinstance(obj, callable)  # no
                  Ответить
              • А, да, instanceof же. Хотя, это вроде про него говорили, что классы могут быть разными.

                Хотя, вообще всё это - рефлектушня со всеми вытекающими. Отдельный вопрос нужно задать программисту - что в его программе делают питушни, типы которых он не знает.
                Ответить
            • Эррей из эррей, на-на, на-на-на...
              Ответить
    • function isNative (Ctor){
            return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
      }
           
      function pituh(){
              print('native code');
      }
           
      print(isNative(pituh));


      https://ideone.com/7DvWYl
      Ответить
      • Какой натив )))
        Ответить
      • Там в комментариях подсказывают, что даже жёсткий тест на «function %name% { [native code] }» не поможет из-за
        (() => console.log('naive code')).bind(this).toString();
        "function () { [native code] }"
        .
        Ответить
        • пристрелили бы уже этот JS чтоб не мучался
          Ответить
          • Не хватает мозгов осилить Javascript - не лезь
            Ответить
            • у тебя просто хватило мозгов только на джаваскрипт, признай
              Ответить
        • Не, ну там же возвращается нативная питушня, у которой в замыкании наша функция. Формально это нативная питушня, а что ей передали в качестве аргументов и замыкания - мелочи.
          Ответить
        • Какой багор )))
          Ответить
      • print(isNative(isNative)); // true
        Ответить
        • Скоро смысл слова "нативе" будет означать другое, подобно указателю "Выход", указывающему на бетонную стену.
          Ответить
      • Какой багор )))
        Ответить

    Добавить комментарий