Почему свойства этого объекта (DOMRect) недоступны для стандартных функций Javascript?

function test(o) {
    console.log("Object:", o);
    console.log("Assign test:", Object.assign({}, o));
    console.log("Keys test:", Object.keys(o));
    console.log("JSON test:", JSON.stringify(o));
}

var el = document.getElementById("question");                 /* or document.body */

test(el.style);                                               /* works as expected */
test(el.getBoundingClientRect());                             /* behaves like {} */
test(Object.assign(el.getBoundingClientRect(),{aaaa: 1111})); /* works... only for aaaa */

Зачем?

Выход (результаты теста)

Смотрите PasteBin.

Документация MDN

  1. Element.getBoundingClientRect ()
  2. DOMRect

1 ответ

Решение

Object.assign а также Object.keys работаем с собственными перечисляемыми свойствами. DOMRect свойства наследуются от DOMRectPrototype и не могут быть доступны этими методами.

Вы можете доказать это:

let rect = el.getBoundingClientRect();
rect.hasOwnProperty('x');                        // === false
Object.getPrototypeOf(rect).hasOwnProperty('x'); // === true

Я использовал Lodash _.assignIn который перебирает собственные и унаследованные свойства источника:

https://jsfiddle.net/msazmfxo/

ОБНОВИТЬ

На основании этого ответа 7vujy0f0hy нашел приемлемое решение:

var ownify = input => 
               Object.keys(Object.getPrototypeOf(input)).reduce((output,key) => 
                 Object.assign(output, {[key]: input[key]}), Object.assign({}, input));

test(ownify(el.getBoundingClientRect())); /* apparently works! */

(Хотя он повторяется только на одном уровне наследования, атрибуты с более глубоких уровней все равно будут отсутствовать)

Другие вопросы по тегам