Как присвоить объект по значению, а не по ссылке?
Если правильно понял// ES5
const newObj = Object.assign({}, sourceObj);

// ES6
const newObj = { ...sourceObj };
Вам определенно нужен deepClone
Можно взять готовый например из lodash, но я бы предложил Вам свою реализацию.
Пока писал ее в ответ, понял, что в очередной раз мой ответ превращается в целую статью, поэтому разместил ее на хабре: https://habr.com/ru/post/466535/
Ну или можете просто скопировать код и использовать:function deepClone(source) {
	return ({
		'object': cloneObject,
		'function': cloneFunction
	}[typeof source] || clonePrimitive)(source)();
}

function cloneObject(source) {
	return (Array.isArray(source)
		? () => source.map(deepClone)
		: clonePrototype(source, cloneFields(source, simpleFunctor({})))
	);
}

function cloneFunction(source) {
	return cloneFields(source, simpleFunctor(function() {
		return source.apply(this, arguments);
	}));
}

function clonePrimitive(source) {
	return () => source;
}

function simpleFunctor(value) {
	return mapper => mapper ? simpleFunctor(mapper(value)) : value;
}

function makeCloneFieldReducer(source) {
	return (destinationFunctor, field) => {
		const descriptor = Object.getOwnPropertyDescriptor(source, field);
		return destinationFunctor(destination => Object.defineProperty(destination, field, 'value' in descriptor ? {
			...descriptor,
			value: deepClone(descriptor.value)
		} : descriptor));
	};
}

function cloneFields(source, destinationFunctor) {
	return (Object.getOwnPropertyNames(source)
		.concat(Object.getOwnPropertySymbols(source))
		.reduce(makeCloneFieldReducer(source), destinationFunctor)
	);
}

function clonePrototype(source, destinationFunctor) {
	return destinationFunctor(destination => Object.setPrototypeOf(destination, Object.getPrototypeOf(source)));
}