Задача на хитрость. Обёртка метода. Apply. Bind. Function length.
Здравствуйте. Пишу обёртку для стандартных джаваскрипт функций. Возникает много вопросов, некоторые удаётся разрешить самому, но совет профессионалов был бы очень кстати.
Как правильно сделать обёртку для метода? Например есть метод Array.prototype.slice, который часто используется для преобразования объекта к массиву. Можно так: function slice (obj, begin, end) { return Array.prototype.slice.apply(obj, Array.prototype.slice.call(arguments, 1)); } Тут нам нужно избавиться от первого аргумента и для этого нужно преобразовать аргументы к массиву, это медленно. Можно так: function slice (obj, begin, end) { // Можно взять метод и непосредственно с функции, но для наглядности оставлю полную версию return Function.prototype.call.apply(Array.prototype.slice, arguments); } Тут возникает вопрос, поддерживает ли метод .apply arraylike объекты? Информация по этому вопросу расплывчата. Если нет, то придётся приводить к массиву, что в конечном итоге сведёт на нет оптимизацию. Может быть можно в рантайме определять поддержку и выдавать нужный вариант? Но это сложно и увеличит кол-во кода. Есть ещё вариант с .bind, но с его поддержкой тоже есть некоторые проблемы, плюс этот вариант не сохранит .length: var slice = Function.prototype.call.bind(Array.prototype.slice); Усложняем задачу. Есть такая вещь как https://github.com/es-shims/es-shim-api
var Function_prototype = Function.prototype; var Function_prototype_call = Function_prototype.call; var Function_prototype_apply = Function_prototype.apply; var Function_prototype_bind = Function_prototype.bind; // Удаляем все методы из прототипа Function_prototype.call = null; Function_prototype.apply = null; Function_prototype.bind = null; // Что дальше? // Что то типа такого var Array_prototype_slice = Array.prototype.slice; function slice (obj, begin, end) { // Восстановим .apply непосредственно на функции Function_prototype_call.apply = Function_prototype_apply; return Function_prototype_call.apply(Array_prototype_slice, arguments); delete Function_prototype_call.apply; // Удалим } Есть идеи получше? |
Аргументы begin и end опциональны. Явная передача их может привести к непредсказуемому поведению.
|
arguments в apply не то что поддерживается, а даже рекомендуется (в V8/Хроме - это один из паттернов, которые оптимизатор хорошо съедает)
А так - я тоже про остальное не совсем понял. Что надо сделать-то? |
Сделать такую обёртку, чтобы она продолжила работать даже после удаления методов .call, .apply и .bind из прототипа функций
|
Часовой пояс GMT +3, время: 22:41. |