Первый, конечно. Никогда не стоит путать / смешивать нужды заказчика и нужды потребителя. Заказчик во многом прав, но скорей всего он сам не будет пользоваться своей же системой. Поэтому к его причудам нужно относиться осторожно и если они конфликтуют с нуждами пользователя — отстаивать вторые.
Моё мнение — любой програмный продукт должен прежде всего разрабатываться для нужд конечного пользователя. Так и только так. Хороший начальник знает, что именно это нужно для его бизнеса. И даже если нужды пользователя идут вразрез с желаниями дирекции, дирекция с удовольствием пересмотрит свои мнения, если дать им обоснование нужд клиента.
Вы издеваетесь, или троллите меня? :)
Вы предложили нерабочий (но зато native) вариант взамен моего рабочего, вот что. Потому я и сказал, что так не пойдёт.
var u = document.createElement('A');
u.href = 'relative/path/index.html';
alert(u.href); // relative/path/index.html, а не my.site.com/somepath/relative/path/index.html
Да, это костыль. И я бы и сам не стал его использовать в продакшне. Но это псевдо-атрибуты, и теоретически штука интересная.
В IE8, кстати, нормальных геттеров/сеттеров так и не сделали — только для DOM-объектов (опять же), но уже не через onproperychange.
Насчёт варианта с Mootools — во-первых, мне не нужен Mootools для этой штуки, а я так понимаю, что мне придётся его включать в проект. Во-вторых, Mootools загрязняет нативные объекты (в отличии от jQuery), что ИМХО тоже не хорошо.
Если ставить задачу, как разовый парсинг URL, то да, ваш вариант отлично подходит (за исключением засорения String.prototype). И я вижу вы потрудились над RegExp'ом ( устрашающе выглядит с первого взгляда :-) )
Ну вот представьте — у вас объект URL. updateUrl(...) мог бы находится в this, тогда у наблюдательного пользователя (скажем, использующего console.dir) возникнет вопрос — что оно тут делает? С чем его есть? Ответ — не с чем, это служебный метод. Поэтому его надо прятать с глаз долой.
Как это сделать? Можно спрятать в конструктор. Тогда будет создаваться по новенькой ф-ции updateUrl с каждым новым объектом. Но это неоправдано, нужна только одна ф-ция updateUrl.
Значит надо вынести и из конструктора, и из прототипа. Значит это должна быть внешняя ф-ция, но спрятанная в одноразовом замыкании (function(){/**/})()
Извиняюсь, насчёт №2 — тут я перепутал. Вы предлагаете использовать this.href = protocol + '//' + host + pathname + search + hash; но тут 2 момента:
1) Внутри ф-ции updateURL (из которой вы и привели фрагмент кода) нет никаких сведений ни про какие host, pathname, search и hash, т.к. они находятся внутри замыкания конструктора.
2) this.href = /* всё, что вы написали */ — привдёт к переопределению метода this.href.
А чтоб оно работало, надо реализовывать всё совсем по-другому :-)
1) Насчёт if (arguments.length) { — согласен, так лучше. 2) «Следующий таинственный фрагмент:» — вы что-то путаете. Первый фрагмент — для одной реализации. Второй фрагмент — для второй реализации. 3) «val.indexOf(»/") != 0" == «val.charAt(0) != '/'» — одно и то же. 4) Использовать «pathname.replace(/(\/|)$/, '/' + val)» более расточительно, чем мой вариант со split + join, хоть он и более громоздкий. Ну и мой вариант более читабелен. 5) «Про window.location.pathname лучше забыть» — вы наверное имеете ввиду relative pathname? Т.к. в целом про pathname ни в коем случае забывать нельзя :) Но если моя реализация действительно работает так, как вы описали, то это конечно бага. Зафикшу.
u.hash // #/f/o/l/d/e/r/s?c=3&d=4
Тут всё ок, всё, что правее первого # == hash
Да и разнобой принципов работы в разных браузерах (в FF — absolute, в IE — relative) — неприемлемо.
Вы предложили нерабочий (но зато native) вариант взамен моего рабочего, вот что. Потому я и сказал, что так не пойдёт.
u.href = 'relative/path/index.html';
alert(u.href); // relative/path/index.html, а не my.site.com/somepath/relative/path/index.html
Одинаково неправильно в IE6, IE7, IE8
В IE8, кстати, нормальных геттеров/сеттеров так и не сделали — только для DOM-объектов (опять же), но уже не через onproperychange.
Как это сделать? Можно спрятать в конструктор. Тогда будет создаваться по новенькой ф-ции updateUrl с каждым новым объектом. Но это неоправдано, нужна только одна ф-ция updateUrl.
Значит надо вынести и из конструктора, и из прототипа. Значит это должна быть внешняя ф-ция, но спрятанная в одноразовом замыкании (function(){/**/})()
Вот так я размышлял, когда писал код.
var u = new URL('http://domain.ru');
u.pathname('foo/bar/index.html');
u.href // получаем domain.ru/foo/bar/index.html. Тут вы что-то недосмотрели, всё работает прекрасно :-)
this.href = protocol + '//' + host + pathname + search + hash;но тут 2 момента:1) Внутри ф-ции
updateURL(из которой вы и привели фрагмент кода) нет никаких сведений ни про какиеhost, pathname, searchиhash, т.к. они находятся внутри замыкания конструктора.2)
this.href = /* всё, что вы написали */— привдёт к переопределению метода this.href.А чтоб оно работало, надо реализовывать всё совсем по-другому :-)
if (arguments.length) {— согласен, так лучше.2) «Следующий таинственный фрагмент:» — вы что-то путаете. Первый фрагмент — для одной реализации. Второй фрагмент — для второй реализации.
3) «val.indexOf(»/") != 0" == «val.charAt(0) != '/'» — одно и то же.
4) Использовать «pathname.replace(/(\/|)$/, '/' + val)» более расточительно, чем мой вариант со split + join, хоть он и более громоздкий. Ну и мой вариант более читабелен.
5) «Про window.location.pathname лучше забыть» — вы наверное имеете ввиду relative pathname? Т.к. в целом про pathname ни в коем случае забывать нельзя :) Но если моя реализация действительно работает так, как вы описали, то это конечно бага. Зафикшу.