Что такое JS нативный (JavaScript)
Чем отличается JS нативный от обычного JavaScript, я не понимаю значения JS нативный, что это такое?
Дополнен 4 года назад
Лучший ответ
Наверное не нативный, а ванильный JavaScript? Без использования сторонних библиотек, то есть.
«Нативный» больше подходит для компилируемого кода, а JS все-таки интерпретируемый (не считая JIT V8).
Остальные ответы
Без библиотек.
Javascript без всякой мути типа jQuery
native в переводе с английского означает «родной»
Native JS? то это библиотека кроссплатформенная на основе js. а чистый js, это vanilla js.
Похожие вопросы
Ваш браузер устарел
Мы постоянно добавляем новый функционал в основной интерфейс проекта. К сожалению, старые браузеры не в состоянии качественно работать с современными программными продуктами. Для корректной работы используйте последние версии браузеров Chrome, Mozilla Firefox, Opera, Microsoft Edge или установите браузер Atom.
Как в JavaScript определить, является ли функция нативной
Время от времени мне приходится проверять, является ли та или иная функция нативной — это важная часть проверки, была ли функция предоставлена браузером или это порождение постороннего шима, замаскированное под встроенный компонент. Лучший способ выполнения такой проверки — это, конечно же, оценка значения toString , возвращённого функцией.
JavaScript
Код, требуемый для этого, довольно прост:
function isNative(fn) < return (/\/).test('' + fn); >
Вся суть состоит в том, чтобы конвертировать функцию в строчное представление и выполнить сопоставление строки с регулярными выражениями. Лучшего способа подтвердить, что это нативная функция, не существует!
Обновление!
Создатель библиотеки lodash, Джон-Дэвид Далтон (John-David Dalton), предложил лучшее решение:
;(function( ) < // Используется для разложения на составляющие внутреннего `[[Class]]` значений var toString = Object.prototype.toString; // Используется для разложения на составляющие декомпилированного // исходного кода функции var fnToString = Function.prototype.toString; // Используется для определения конструкторов среды (Safari > 4; // по сути, предназначено специально для типизированных массивов) var reHostCtor = /^\[object .+?Constructor\]$/; // Составление регулярного выражения на основе часто употребляемого // нативного метода в качестве шаблона. // Выбираем `Object#toString`, так как вполне вероятно, что он ещё не задействован. var reNative = RegExp('^' + // Применяем `Object#toString` к строке String(toString) // Избавляемся от любых специальных символов регулярных выражений .replace(/[.*+?^$<>()|[\]\/\\]/g, '\\$&') // Заменяем упоминания `toString` на `.*?`, чтобы сохранить обобщённый вид шаблона. // Заменяем `for . ` и тому подобное для поддержки окружений вроде Rhino, // которые добавляют дополнительную информацию, такую как арность метода. .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); function isNative(value) < var type = typeof value; return type == 'function' // Используем `Function#toString`, чтобы обойти собственный метод // `toString` самого значения и избежать ложного результата. ? reNative.test(fnToString.call(value)) // На всякий случай выполняем проверку на наличие объектов среды, так // как некоторые окружения могут представлять компоненты вроде // типизированных массивов как методы DOM, что может не соответствовать // нормальному нативному паттерну. : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false; > // экспортируем в удобном для вас виде module.exports = isNative; >());
И вот теперь у нас точно есть лучший подход для определения, является ли метод нативным. Естественно, не стоит использовать его для обеспечения безопасности — это лишь признак того, что функция нативна.
Проверяем, есть ли у нативной JavaScript‑функции манкипатч
Кратко: как можно понять, была ли переопределена нативная JavaScript‑функция? Никак — или не совсем надежно. Способы есть, но полностью доверять им нельзя.
Нативные функции в JavaScript
В JavaScript «нативная функция» — это функция, исходный код которой был скомпилирован в машинный код. Нативные функции можно найти в стандартных встроенных объектах JavaScript (таких, как eval() , parseInt() и т. д.) и веб-API браузеров (таких, как fetch() , localStorage.getItem() и т. д.).
Из-за динамической природы JavaScript разработчики могут переопределять нативные функции, предоставляемые браузером. Этот метод известен как манкипатчинг.
Манкипатчинг
Манкипатчинг, в основном, используется для изменения поведения встроенных API и нативных функций браузера. Часто, это единственный способ добавить специфичную функциональность, полифиллы или «зацепиться» за API, который иначе изменить невозможно.
Например, инструменты мониторинга, такие как Bugsnag, переопределяют интерфейсы Fetch и XMLHttpRequest, чтобы получить представление о сетевых подключениях, запускаемых кодом JavaScript.
Манкипатчинг — это мощный, но опасный метод, потому что код, который вы переопределяете, не находится под вашим контролем: будущие обновления движка JavaScript могут нарушить предположения, сделанные в вашем патче, и вызвать серьезные ошибки.
Кроме того, делая манкипатчинг кода, которым не владеете, вы можете переопределить код, уже содержащий манкипатч другого разработчика, что приведет к потенциальному конфликту.
По этим (и многим другим) причинам может понадобиться проверить, является ли данная функция нативной или она имеет манкипатч… Но получится ли?
Использование toString() для проверки того, что у функции есть манкипатч
Самый распространенный способ проверить, является ли функция «чистой» (то есть, без манкипатча) — это проверить вывод ее toString() .
По умолчанию, нативная функция toString() возвращает что-то вроде строки «function fetch() < [native code] >» :

Эта строка может немного отличаться в зависимости от того, какой движок JavaScript используется. Тем не менее в большинстве браузеров вы можете с уверенностью предположить, что эта строка будет включать подстроку «[native code]» .
Если нативная функция будет иметь манкипатч, ее toString() перестанет возвращать строку «[native code]» в пользу возврата тела функции в виде строки.
Таким образом, простой способ проверить, является ли функция по-прежнему нативной — это проверить, содержит ли ее вывод toString() строку «[native code]» .
Элементарная проверка может выглядеть так:
function isNativeFunction(f) < return f.toString().includes("[native code]"); >isNativeFunction(window.fetch); // → true // Манкипатч fetch API (function () < const < fetch: originalFetch >= window; window.fetch = function fetch(. args) < console.log("Вызов fetch перехвачен:", . args); return originalFetch(. args); >; >)(); window.fetch.toString(); // → "function fetch(. args)
Этот подход отлично работает в большинстве случаев. Однако, его легко обойти, заставив считать, что функция по-прежнему нативна, когда это не так. Будь то злой умысел (например, вредоносное изменение кода) или потому, что кто-то хочет скрыть факт переопределения. Есть несколько способов, которыми вы можете сделать функцию «нативной».
Например, вы можете добавить код (или даже комментарий!) в тело функции, содержащий строку "[native code]" :
(function () < const < fetch: originalFetch >= window; window.fetch = function fetch(. args) < // function fetch() < [native code] >console.log("Вызов fetch перехвачен:", . args); return originalFetch(. args); >; >)(); window.fetch.toString(); // → "function fetch(. args)
…Или вы можете переопределить метод toString() , чтобы он возвращал строку, содержащую "[native code]" :
(function () < const < fetch: originalFetch >= window; window.fetch = function fetch(. args) < console.log("Вызов fetch перехвачен:", . args); return originalFetch(. args); >; >)(); window.fetch.toString = function toString() < return `function fetch() < [native code] >`; >; window.fetch.toString(); // → "function fetch() < [native code] >" isNativeFunction(window.fetch); // → true
…Или вы можете создать функцию с манкипатчем, используя bind, которая генерирует нативную функцию:
(function () < const < fetch: originalFetch >= window; window.fetch = function fetch(. args) < console.log("Вызов fetch перехвачен:", . args); return originalFetch(. args); >.bind(window.fetch); // >)(); window.fetch.toString(); // → "function fetch() < [native code] >" isNativeFunction(window.fetch); // → true
…Или вы сделаете манкипатч функции, перехватив вызовы apply() с помощью ES6 Proxy, что сделает функцию снаружи похожей на нативную:
window.fetch = new Proxy(window.fetch, < apply: function (target, thisArg, argumentsList) < console.log("Вызов fetch перехвачен:", . argumentsList); Reflect.apply(. arguments); >, >); window.fetch.toString(); // → "function fetch() < [native code] >" isNativeFunction(window.fetch); // → true
Остановимся на этом.
Моя точка зрения такова: разработчики могут легко сделать так, чтобы манкипатч не был заметен, если вы проверяете функцию toString() .
Я думаю, зачастую вам не следует заботиться о крайних случаях, описанных выше. Но если захотите сделать это, можете попробовать покрыть их дополнительными проверками.
- вы можете использовать одноразовые iframe, чтобы получить «чистое» значение toString() и использовать его в строгом сравнении;
- вы можете вызвать несколько .toString().toString() , чтобы убедиться, что функция toString() не переопределена;
- вы можете надеть шляпу метапрограммиста и сделать манкипатч конструктора Proxy , чтобы определить, является ли проксируемой нативная функция (потому что, следуя спецификациям, невозможно определить, является ли что-то Proxy );
- и т.п.
Все зависит от того, насколько глубоко вы хотите проникнуть в кроличью нору toString() .
Но стоит ли? Можно ли охватить все крайние случаи?
Получение чистой функции из iframe
Если вам нужно вызвать «чистую» функцию (вместо того, чтобы проверять, есть ли манкипатч у нативной функции) — можно получить ее из iframe с таким же источником (same-origin):
// Создаем новый iframe с тем же источником. // Вы, вероятно, захотите добавить некоторые стили для его скрытия и, в конечном итоге, удалить его из DOM позже. const iframe = document.createElement("iframe"); document.body.appendChild(iframe); // Новый iframe создаст свой собственный "чистый" объект window, так что вы сможете захватить интересующую вас функцию оттуда. const cleanFetch = iframe.contentWindow.fetch;
Хотя я думаю, что этот подход все же лучше, чем проверка функции с помощью toString() , но он имеет некоторые существенные ограничения:
- Из-за строгой политики безопасности контента (CSP) или из-за того, что ваш код не работает в браузере, iframe может быть недоступен.
- Хоть это и маловероятно, другая сторона может сделать манкипатч API iframe. Таким образом, вы все еще не можете на 100% доверять объекту window созданного iframe.
- Нативные функции, которые манипулируют DOM (например, document.createElement ), не будут работать с этим подходом, потому что они будут нацелены на DOM созданного iframe, а не на родительский.
Данное решение было предложено в треде lobstre.rs.
Использование сравнения ссылок для проверки того, что у функции есть манкипатч
Если безопасность является первостепенной задачей, я думаю, следует использовать другой подход: сохранить ссылку на «чистую» нативную функцию и позже сравнить с ней функцию с потенциальным манкипатчем:
Используя строгое сравнение ссылок, мы избегаем всех лазеек toString() . Это работает даже при использовании Proxy , потому что оно не может перехватить сравнение .
Главный недостаток этого подхода заключается в том, что он может быть непрактичным. Он требует сохранения исходной ссылки на функцию перед запуском любого другого кода в вашем приложении (чтобы быть уверенным, что она все еще не тронута), что иногда вы не сможете сделать (например, если вы создаете библиотеку).
Могут быть способы сломать этот подход, но на момент написания мне не было известно о них. Дайте знать, если я что-то упустил!
Итак, как понять, была ли переопределена нативная функция JavaScript?
Я могу посчитать на пальцах одной руки, сколько раз мне нужно было проверить, есть ли у функции манкипатч.
Так или иначе, мое мнение (или, лучше, «предположение») касательно этого вопроса заключается в том, что, в зависимости от варианта использования, может и не быть надежного способа определить манкипатч.
- Если вы контролируете всю веб-страницу, вы можете написать свой код заранее, сохранив ссылки на функции, которые хотите проверить, когда они еще «чисты», и сравнить их позже.
- В противном случае, если вы можете использовать iframe, вы можете создать скрытый одноразовый iframe и взять оттуда «чистую» функцию — понимая, что вы все еще не можете быть на 100% уверены, что iframe API не имеет манкипатча.
- Иначе, учитывая динамическую природу JavaScript, вы можете либо использовать простую проверку toString().includes("[native code]") (понимая, что злоумышленники могут легко остаться незамеченными), либо добавить массу проверок безопасности, чтобы покрыть большинство (но не всех) пограничных случаев.
Дальнейшее чтение и связанные ресурсы
- StackOverflow: Is there a way to check if a native Javascript function was monkey patched?
- StackOverflow: Detect if function is native to browser
- StackOverflow: How to determine that a JavaScript function is native (without testing ‘[native code]‘)
- David Walsh: Detect if a Function is Native Code with JavaScript
Нативный js или react?
Немного поизучал react в надежде начать применять на практике для удобства написания кода и легкости масштабирования проекта с возможностью многократного использования готовых решений в новых проектах.
Что первое мне бросилось в глаза, так это ощутимая древовидная структура файлов, которая с увеличением проекта всегда будет расти. Затем в файлах много импорта и экспорта, которые надо держать в голове. Наследование и оборачивание контейнеров в контейнер, наследование классов, проброс свойств и наконец рендеринг. Ну и, конечно, синтаксис, к которому надо привыкнуть и перестроиться.
Если мне надо, к примеру, обработать нажатие на кнопку Like или submit для отправки сообщения на сервер, то я традиционно возьму и напишу функции: обработки нажатия элемента, фэтчинга и рендеринга изменённых данных или ответа в модальном окне. Все это в одном - двух файлах и кода немного. В react, сдаётся мне, что придётся проделать больше работы и затронуть больше чем два файла. .
От сюда и вопрос к знатокам реакт : это действительно с ростом проекта заметно облегчает жизнь и ускоряет процесс разработки фронта по сравнению с нативным js или пока ещё живым jQuery? или это просто модный альтернативный framework со своими предпочтениями и нишей?
- Вопрос задан более двух лет назад
- 3280 просмотров
1 комментарий
Простой 1 комментарий