Комментарии 32
Зная это, можно написать функцию, позволяющую различать нативные и пользовательские функции
isNative(isNative) => true
Люблю javascript ^^
Потому что в исходнике isNative присутствует постройка, по которой определяется нативность.
Потому что строчка native code
внезапно есть в тексте функции isNative :)
Корректная реализация видимо должна как-то так проверять:
function isNative (Ctor){
return typeof Ctor === 'function' && /\{\s*\[native code\]\s*\}$/.test(Ctor.toString())
}
// Used to resolve the internal `[[Class]]` of values
const toString = Object.prototype.toString;
// Used to resolve the decompiled source of functions
const fnToString = Function.prototype.toString;
// Used to detect host constructors (Safari > 4; really typed array specific)
const reHostCtor = /^\[object .+?Constructor]$/;
// Compile a regexp using a common native method as a template.
// We chose `Object#toString` because there's a good chance it is not being mucked with.
const reNative = RegExp('^' +
// Coerce `Object#toString` to a string
String(toString)
// Escape any special regexp characters
.replace(/[.*+?^${}()|[\]/\\]/g, '\\$&')
// Replace mentions of `toString` with `.*?` to keep the template generic.
// Replace thing like `for ...` to support environments like Rhino which add extra info
// such as method arity.
.replace(/toString|(function).*?(?=\\\()| for .+?(?=\\])/g, '$1.*?') + '$'
);
const isNative = value => {
const type = typeof value;
return type === 'function'
// Use `Function#toString` to bypass the value's own `toString` method
// and avoid being faked out.
? reNative.test(fnToString.call(value))
// Fallback to a host object check because some environments will represent
// things like typed arrays as DOM methods which may not conform to the
// normal native pattern.
: (value && type === 'object' && reHostCtor.test(toString.call(value))) || false;
};
isNative(isNative); // Покажет false
isNative(Symbol); // Покажет true
Различение встроенных и пользовательских функций
Только не забывать про использование bind:
const a = function() { console.log(1); }
a.toString()
"function() { console.log(1); }"
a.bind(this).toString()
"function () { [native code] }"
Реализация cached неудачная: нули, пустые строки, false, null и undefined функция кэшировать не будет, а будет каждый раз вычислять
fn.chache = [ {} ];
function fn( arg ) {
let chachedResult= fn.chache.find( ( x ) => { return x.arg === arg } );
if ( chachedResult )
return chachedResult.result;
let result;
... // вычисление result
fn.chache.push( { arg: arg, result: result } );
return result;
}
Тем более тут нет проблемы с null, undefined.
Тяжелые функции могут быть библиотечными, автор которых не считает нужным кэшировать. Да и вообще, код хуже читается, дублирование кода в разных местах весьма вероятно и т. п.
let chachedResult= fn.chache.find( ( x ) => { return x.arg === arg } );
Зачем вам тут O(n)
? Сделайте кеш с использованием new Map
или new WeakMap
.
кэшировании своих результатов без обёртки
Ну вы собственно сделали обёртку, просто не в виде метода, а в виде кода выше и кода ниже самих вычислений. Суть та же самая. От перестановки мест слагаемых...
А еще неудачное имя, так как это принято называть мемоизацией или memoization. А если правильно назвать, то смотри, можно и кучу готовых и проверенных годами решений найти, lodash например.
Осторожнее с утечками памяти. Кажется по-дефолту там используется {}
в качестве хранилища. Код какой-то сильно путанный, бегло пробежался. Предлагают использовать weakMap
в качестве альтернативы, но тут имейте ввиду что ничего кроме object-ов в качестве ключей тогда использовать будет нельзя.
Ну не то чтобы прям утечка памяти, просто по-умолчанию он не чистится. Жаль в JS нет встроенной возможности сделать кеш из серии "ну можно чистить, когда памяти не хватает". В любом случае, нужно использовать с умом: если вы знаете что функция хоть и тяжелая, но будет выпоняться для ограниченного набора элементов — почему бы и нет. Вот, скажем, у меня есть инструмент, где учитель может видеть результаты работы учеников. Максимальное количество закешированных элементов равняется количеству учеников. Не то чтобы стоит переживать.
А вот если речь идет об сложной обработке сложных строк, которые идут из пользовательского ввода, т.е. набор элементов может быть неограничен — стоит позаботиться о том, чтобы хранить только немного элементов (иногда вообще только последний результат).
export function cached<F: Function> (fn: F): F {
const cache = Object.create(null)
return (function cachedFn (str: string) {
if (!cache.hasOwnProperty(str)) cache[str] = fn(str);
return cache[str];
}: any)
}
if ( !cache[str] )
Что здесь, что во Vue одна и та же грубая ошибка: если исходная функция вернет любое «false» значение — кэш не сработает.
Как все мы знаем, в JavaScript существует шесть примитивных типов данных (Boolean, Number, String, Null, Undefined, Symbol) и один объектный тип — Object.С каких это пор Null является типом данных? Почему нету тогда типа NaN?
Вроде с самого начала, но сейчас 100% — http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types-null-type так же как undefined — отдельный тип. А NaN — число по стандарту IEEE 754
Их существует очень много:
— JavaScript паттерны проектирования 1
— JavaScript паттерны проектирования 2
— JavaScript — полезные функции
и т.д.
- Определение точного типа любого объекта
И ещё находятся люди, которые утверждают, что на языках с динамической типизацией прлще писать программы.
Зная это, можно написать функцию, позволяющую различать нативные и пользовательские функции
Ни разу не требовалось подобного, но очень хотелось бы увидеть реальный пример из практики. Заранее благодарю )
5 интересных JavaScript-находок, сделанных в исходном коде Vue