Добрый день!
Не знаю, будет ли кому интересно, но соорудил сегодня такое чудо: DeepClone, упихивающийся в 140 байт.
Если кто-то такое уже делал и постил, ткните, пожалуйста, носом. Я в формате твитов нашёл только неглубокие копирования. Ну и не исключаю, что какой-нибудь применённый хак находится в списке запрещённых препаратов приёмов, а за его использование полагаются страшные кары :)
Из недостатков — всё то же, что и у клонирования с помощью функции extend из jQuery: не ест стандартные объекты типов Boolean, String, Date, игнорирует prototype и constructor и зависает на кольцах.
Достоинство одно и, по-большей части, чисто эстетическое — размер.
Тестировал в Firefox, Chromium, Opera, IE8 и в умолчальном андроидном браузере.
Под катом — код и небольшой рассказ о том, как это работает.
Для начала, читабельная версия (назвается dup потому, что иначе в 140 байт не сжимается):
function dup(o) {
// "string", number, boolean
if(typeof(o) != "object") {
return o;
}
// null
if(!o) {
return o; // null
}
var r = (o instanceof Array) ? [] : {};
for(var i in o) {
if(o.hasOwnProperty(i)) {
r[i] = dup(o[i]);
}
}
return r;
}
Что здесь происходит:
Если объект — простой (строка, число, boolean), просто возвращаем его, дальше проверяем, что объект — не null (typeof(null) тоже == «object»). Теперь создаём результат (массив или объект) и пробегаем по свойствам, рекурсивно их клонируя.
В общем, всё просто. Теперь почти 300 байт надо ужать в два раза.
Вспоминаем некоторые вещи, которые нам помогут:
— typeof — это оператор, и ему скобки не нужны;
— у ?: приоретет самый низкий, так что скобки слева опять-таки можно опустить;
— null &— это null, а obj &— это obj;
— for(var i in null) проходит без ошибки, не делая ни одной итерации;
— параметры функции — тоже переменные, а вот передавать их все совершенно не обязательно. Это поможет нам сэкономить 4 байта на слове var с пробелом.
Исходя из этого, получаем:
function dup(o,i,r) {
if(typeof o != "object") return o;
r = o instanceof Array ? [] : o&
for(i in o)
if(o.hasOwnProperty(i))
r[i] = dup(o[i]);
return r
}
Ну, или в одну строку (139 букв):
function dup(o,i,r){if(typeof o!="object")return o;r=o instanceof Array?[]:o&for(i in o)if(o.hasOwnProperty(i))r[i]=dup(o[i]);return r}
Если же увеличить допустимый размер до 150-и символов, то можно добавить ещё и обработку ссылок на самих себя (не полное разруливание колец, конечно, но хоть что-то):
r[i] = (o[i] === o) ? r : dup(o[i]);
Или:
function dup(o,i,r){if(typeof o!="object")return o;r=o instanceof Array?[]:o&for(i in o)if(o.hasOwnProperty(i))r[i]=o[i]===o?r:dup(o[i]);return r}
Демка: pastehtml.com/view/buikhdvfe.html (чтобы посмотреть без обёртки от pastehtml, замените в ссылке слово «view» на «raw»)
Автор: lxyd