Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Прокси/обертка для замены undefined на null

#javascript


С сервера приходит "разреженный" json вида

[
    { a: 1, b: 2 }, 
    { a: 2,       c: 3 }, 
    {       b: 2, c: 3 }
]


т.е. массив объектов, в каждом из которых могут быть свойства a, b, c. Список свойств
заранее известен, и он достаточно большой (около 40 штук). 

Заполненность каждого элемента достаточно малая (2-3 свойства).

Выражение 

data[0].c


возвращает undefined. Нужет какой-то способ заставить его возвращать null (т.к. есть
куча уже написанного кода, который ожидает именно null).

Желательно решение, работающее в IE8+. 
__defineGetter__ умер не родившись, Harmony Proxy не поддерживается до Edge. 

Писать некрасивый код, который шел бы по списку объектов и выставлял все 40 свойств
у каждого в null не хотелось бы.

UP: речь идет не о каком-то хитром хаке ради замены семантики undefined на null во
всем приложении. Цель - сэкономить на сериализации, чтобы избежать передачи пачки бесполезных
данных с сервера. Потому что никакая семантика не оправдывает передачу

{ a: 1, b: 2, x : null, x : null, x : null, x : null, x : null, 
 x : null, x : null, x : null, x : null, x : null, 
 x : null, x : null, x : null, x : null, x : null, 
 x : null, x : null, x : null, x : null, x : null, 
 x : null, x : null, x : null, x : null, x : null, 
 x : null, x : null, x : null, x : null, x : null, 
 x : null, x : null, x : null, x : null, x : null, 
 x : null, x : null, x : null, x : null, x : null, 
 x : null, x : null, x : null, x : null, x : null, 
 x : null, x : null, x : null, x : null, x : null, 
 }, 


вместо { a: 1, b: 2 }. Сервер знает о существовании свойства, и о том, что оно -
null, клиент знает о существовании свойства, и о том, что оно null. Соответственно,
"переписать" - не решение.
    


Ответы

Ответ 1



Можно попытаться использовать решение на базе прототипов. Основная идея -- установить в качестве прототипа каждого из передаваемых объектов объект, содержащий значения по умолчанию (те самые поля с null). Раз нужна поддержка IE8+, то решения на базе Object.create, Object.setPrototypeOf и __proto__ не будут работать без полифилов. Зато, можно использовать обычную функцию-конструктор и не боятся за кроссбраузерность. Вот пример реализации: var ObjWrapper = function(obj) { // Поскольку объект разреженный, этот цикл будет иметь // небольшое число итераций. for (var i in obj) { if (!obj.hasOwnProperty(i)) { continue; } this[i] = obj[i]; } }; // Мы можем использовать всего ОДИН объект в качестве прототипа. // Это позволяет экономить память, не занимая ее кучей null-свойств // каждого обернутого объекта. ObjWrapper.prototype = { a: null, b: null, c: null, d: null, e: null // Задание null-свойств можно оптимизировать с использованием цикла, // хотя это уже детали. }; var obj = new ObjWrapper({a: 'test'}); console.log(obj.c); // выведет null вместо undefined При использовании такого подхода нужно иметь в виду два момента: Конструкция obj.hasOwnProperty('d') выдаст false, если оборачиваемый объект не имеет свойства d. В ряде случаев это может быть критичным. Все равно придется использовать цикл, при десериализации массива и оборачивать каждый его элемент.

Ответ 2



есть куча уже написанного кода, который ожидает именно null Переписать. Потому что undefined == null не просто так.

Комментариев нет:

Отправить комментарий