Поиск по метке: JavaScript
IE8 и babel
В одном из проектов требуется на уровне ТЗ поддержка Internet Explorer 8. Спасибо, что не 7 :) Дошли руки до перевода кодовой базы на es6. Воткнул как обычно preset es2015, потестил, вроде всё работает, но дёрнул меня чёрт проверить и в старом ослике. Подохло там всё. Причём глюк настолько странный, что я невольно задвигал бровями. Перейду сразу к сути:
function init(){ console.log(1); }
var a = { init: function(){ console.log(2); } };
init();
Результат, конечно же, 1. Однако babel превратит сий код в:
"use strict";
function init() {
console.log(1);
}
var a = { init: function init() {
console.log(2);
} };
init();
Ключевое отличие ― именование метода. Теперь он тоже init. Зачем? Не ко мне вопрос. Может быть для упрощения отладки. Но с этого момента старый ишак возвращает 2. Оказывается это старый баг тогдашнего jscript-а.
Лечение: добавляем: plugins: ["transform-jscript"] к настройкам babel-я. Ну и соответственно тащим этот плагин. С этого момента babel будет генерировать вот таких вот монстров:
"use strict";
function init() {
console.log(1);
}
var a = { init: function() {
function init(){ console.log(2); }
init();
} };
init();
Очень бредово, если честно. Ведь можно было сохранить изначальный код в первозданном виде.
Загрузка binary-файла
Возникла задача ― загрузить с сервера XLSX-файл. Запрос ― POST. Файл, понятное дело, бинарный. На проекте уже подключена jQuery, и, первым делом, я решил воспользоваться её стандартным $.ajax. Сколько не бился ― так и не удалось получить blob-результат от запроса. Использовать же решение через iframe-ы и form-ы тоже не хотелось. Во-первых уж больно костыльно (привет 90-ые). во-вторых нужно будет ещё чудить с передачей параметров POST-запроса (content-type: json). Гуглил-гуглил, но ни одного вменяемого решения (которое не стыдно было бы утащить в проект) я так и не нашёл. Но, т.к. интересует поддержка только последних версий современных браузеров, удалось найти и применить более изящное и функциональное решение. Итак…
- Забудем про jQuery и воспользуемся нативным XMLHttpRequest-ом
- Указав ему responseType = 'blob'.
- Получившийся результат (blob) загоняем в URL.createObjectURL.
- В результате получим псевдо-URL ссылку, начинающуюся с "blob:".
Ну а дальше уже по-желанию. Я генерирую новый <a/>-тег, задаю ему нужные аттрибуты download и href (та самая blob-ссылка), вызываю у ссылки .click(). Апосля ссылку удаляю. Проверял в Firefox-е и Chrome-е.
Небольшая заготовка:
function loadBlob(params, data)
{
return new Promise((resolve, reject) =>
{
const xhr = _.assign(new XMLHttpRequest(),
{
onload(){ resolve(xhr.response); },
onerror(e){ reject(e.target.status); }
});
xhr.open(params.method || 'POST', params.url);
xhr.responseType = 'blob';
const contentType = params.contentType || 'application/json';
xhr.setRequestHeader('content-type', contentType);
if(contentType === 'application/json')
data = JSON.stringify(data);
xhr.send(data);
});
}
For-of и браузеры
Оказывается, браузеры по-разному относятся к итерированию цикла for-of. Судите сами:
for(const a of []) ; // chrome: ok, ff: syntax error
На что ругается Firefox? Говорит, что a указана, как константа, а используется как переменная. Но почему?
for(let a of [1, 2])
setTimeout(() => alert(a));
- Chrome: 1, 2
- Firefox: 2, 2
Всё просто. Chrome каждую итерацию пересоздаёт scope, а Firefox довольствуется одним. И если с const ошибка вылезет сразу (правда только в Firefox). То в случае чего-нибудь асинхронного ждите трудно-вылавливаемые баги, которые проявятся только в Firefox-е. В спеку мне лезть лень, но код генерируемый babel-ем ближе к Chrome-варианту. Кто прав?
Javascrpt ES6 и классы
Понемногу перебираюсь на JavaScript ES6 синтаксис. По мере появления его нативной поддержки в nodeJS и Chrome. ES6 таит в себе множество не очевидных вещей. Больше всего я их встретил в class-ах. Классы в ES6 это обширный набор синтаксического сахара для prototype. С ними писать код приятнее, да и сам синтаксис вынуждает подходить к этому дисциплинированнее. В этой мини-заметке я опишу пары интересных моментов:
- Синтаксис допускает только короткие имена методов;
- Тело класса описывает методы, которые будут помещены в prototype и статические методы, которые будут помещены в сам объект класса. Так вот… Таким образом вы можете поступить только с методами и generator-ми. Т.е. никаких хешей, никаких чисел, строк, регулярных выражений. Всё, что вы захотите поместить сверх методов и генераторов будет идти уже отдельными строками кода после описания класса;
- Это ограничение довольно понятно. Дескать дисциплинирует все подобные вещи определять в конструкторе и не позволяет переписывать детьми в прототипе. Но…
Почему то nodejs не поддерживает статические generator-ы. Не статические поддерживает, а на статические лови syntax error. Наверное это баг(static * name()); - Для удобного доступа к родительским методам (имею ввиду наследование классов) придуман super. Но… Если вы переопределяете конструктор класса, вы:
- Обязаны вызвать super, чтобы получить доступ к this.
- Да да. До этого момента this отсутствует как таковой. Соответственно вызвать родительский конструктор, предварительно задав какие-нибудь поля новому объекту, без бунов не получится. Зачем они так сделали? о_О.
- Методы и генераторы заданные в теле класса будут не-enumerable. Но для получения их списка можно воспользоваться: Object.getOwnPropertyNames(Object.getPrototypeOf(this)).
Пока что это все грабли на которые я наткнулся. В скором времени ожидается поддержка со стороны Firefox.
Переносы в тексте
В то время как браузеры умеют WebGL, анимации и многое другое, до сих пор не вменяемой поддержки таких значимых вещей как нормальная вёрстка таблиц, переносы в тексте, полноценная поддержка unicode-а в регулярных выражениях, justify-выравнивание и т.д.. Сий пост про переносы текста.
Итак. Что мы имеем? Мы имеем css3 свойство hyphen: auto. Но довольно унылую поддержку. Во-первых его не умеет ни Chrome, ни его клоны. Во-вторых его не умеет Firefox под linux. В третьих (в чём я не уверен) поддержка идёт на уровне встроенных словарей. Т.е. если вам потребовалась поддержка переносов в, к примеру, казахском тексте, вас снова ждёт облом. Но само свойство хорошо. В идеале вбив его можно забыть про все проблемы, ибо браузер сам их порешает.
Что у нас есть ещё вналичии? Есть такие опции как word-break, word-wrap, overflow-wrap, line-break. К сожалению никакая комбинация этих свойств не позволяет добиться нормальных переносов в таблице, которую перекашивает, как раз из-за отсутствия этих переносов. Например вы можете добиться вот такого вот результата:
Подробности под катом…