简体   繁体   中英

Javascript getComputedStyle - copy object without reference

I want to change the color of an input field border. But yet before changing, I need to save the initial CSS via getComputedStyle so that I can set all the initial CSS of the input field back. The problem is that the object of getComputedStyle is not fixed and changes dynamically.

I tried to copy the object into a new one without reference, but then I cannot use the property getPropertyValue because it is a different type of object. Is there any way how I could retrieve back the initial CSS of the input field?

My code is the following:

 const input_element = document.getElementById('text-id'); let computedStyle_fixed; function change_color() { // get computed style const computedStyle = window.getComputedStyle(input_element); // copy computed style into new object without reference computedStyle_fixed = JSON.parse(JSON.stringify(computedStyle)); // change the border color of the input field input_element.style.borderColor = 'red'; } function retrieve_color() { Array.from(computedStyle_fixed).forEach( key => element.style.setProperty(key, computedStyle_fixed.getPropertyValue(key), 'important') ) }
 <input type='text' id='text-id'> <button onclick='change_color()'>Change color</button> <button onclick='retrieve_color()'>Retrieve color</button>

There are a number of issues in your code. Firstly in this line:

const computedStyle = window.getComputedStyle(input_element);

window.getComputedStyle returns a CSSStyleDeclaration object . When copied using:

computedStyle_fixed = JSON.parse(JSON.stringify(computedStyle));

the object assigned to computedStyle_fixed is a plain object, not a CSSStyleDeclaration object. This has consequences in the retrieve_color function explained further down.

Then in:

Array.from(computedStyle_fixed)

Array.from expects the argument to be an array–like object with a length property or an iterable object. computedStyle_fixed is neither so the result is an empty array and the following forEach does nothing (because length is 0).

Within the forEach callback, there is:

computedStyle_fixed.getPropertyValue(key)

the computedStyle_fixed object doesn't have a getPropertyValue method (see above), so if that line is executed the result will be a type error.

To iterate the properties of the computedStyle_fixed object, use Object.keys and access properties using square bracket notation, not the (missing) getPropertyValue method, eg

Object.keys(computedStyle_fixed).forEach(key => 
   element.style.setProperty(key, computedStyle_fixed[key], 'important')
);

Other notes

Creating implicit globals like computedStyle_fixed is not recommended, declare them or set them as object properties.

Using JSON.stringify to create a shallow copy of an object is also not a good idea, it's much better to use Object.assign :

let computedStyle_fixed = Object.assign({}, computedStyle);

This also creates a plain object, not a CSSStyleDeclaration object.

from what I understood is that you need all the css properties of a element and store in an object.

you can use spread operator to do so.

const computedStyle = {...window.getComputedStyle(input_element)};

you can now use this like a normal object.

ex: console.log(computedStyle.backgroundColor);

I have solved it, I have just change a little the retrieve_color() function. But I thought that it would set the style of the input border exactly as it used to be initialy. If you look at the code at jsfiddle and click on change_color and then click on retrieve_color, you will see that the input does not look as it was (the border are different). Do you have any idea how I could get it back exactly as it was?

// the code    
https://jsfiddle.net/gfxjn4se/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM