Я сталкиваюсь с некоторыми проблемами с объединением двух объектов с помощью свойств getters/seters, которые деградируют в значения. Как это предотвратить? Нужно ли клонировать его вручную?
Ниже, надуманный пример моего pb:
function Factory1() {
const p = {};
return {
get prop1 () { return p.prop; },
set prop1 (value) { p.prop = value; }
};
}
function Factory2() {
const p = {};
return {
get prop2 () { return p.prop; },
set prop2 (value) { p.prop = value; }
}
}
const obj1 = Factory1();
const obj2 = Factory2();
const obj3a = {...Factory1(), ...Factory2()};
const obj3b = Object.assign(Factory1(), Factory2());
console.log('obj1.prop1 =>', Object.getOwnPropertyDescriptor(obj1, 'prop1'));
console.log('obj2.prop2 =>', Object.getOwnPropertyDescriptor(obj2, 'prop2'));
console.log('spread prop1 =>', Object.getOwnPropertyDescriptor(obj3a, 'prop1'));
console.log('spread prop2 =>', Object.getOwnPropertyDescriptor(obj3a, 'prop2'));
console.log('assign prop1 =>', Object.getOwnPropertyDescriptor(obj3b, 'prop1'));
console.log('assign prop2 =>', Object.getOwnPropertyDescriptor(obj3b, 'prop2'));
Простой пример:
function Factory1() {
return {
get prop1 () { return 42; }
};
}
const obj1 = Factory1();
const obj2 = Object.assign({}, Factory1())
console.log('obj1.prop1 =>', Object.getOwnPropertyDescriptor(obj1, 'prop1'));
// result
// obj1.prop1 => { get: [Function],
// set: undefined,
// enumerable: true,
// configurable: true }
console.log('obj2.prop1 =>', Object.getOwnPropertyDescriptor(obj2, 'prop1'));
// result
// obj2.prop1 => { value: 42,
// writable: true,
// enumerable: true,
// configurable: true }
По запросу я попытаюсь проиллюстрировать, с каким типом кода я сталкиваюсь. Конечно, это конкатенация извлечений кода, отправленного в несколько модулей.
import axios from 'axios';
function createAxios (options = {}) {
const axiosClient = axios.create(options);
axiosClient.defaults.withCredentials = false;
axiosClient.defaults.headers.common['Accept'] = 'text/html';
return {axiosClient};
}
function WithQuery ({axiosClient}) {
// This is a sample server that supports CORS.
var sampleUrl = 'http://html5rocks-cors.s3-website-us-east-1.amazonaws.com/index.html';
return {
query (url) {
return axiosClient.get(url || sampleUrl);
}
};
}
function WithLastModified (context) {
let lastModified;
context.axiosClient.interceptors.response.use(function (response) {
const {headers} = response;
console.log('header last-modified:', headers['last-modified']);
lastModified = headers['last-modified'];
return response;
});
return {
getLastModified () {
return lastModified;
},
get lastModified () {
return lastModified;
}
}
}
function build (options) {
const httpClient = createAxios(options);
return Object.assign({},
httpClient,
{search: WithQuery(httpClient)},
WithLastModified(httpClient));
}
const api = build();
api.search.query().then(() => {
console.log('get lastModified:', api.lastModified); // not working, always undefined
console.log('getLastModified:', api.getLastModified()); // work
});
Этот тип заводских методов используется для ввода зависимостей и добавления функциональности через псевдомиксины к конечному объекту.
Если вы проверите свой код, вы заметите, что даже получая дескрипторы и добавляя их к новому объекту, ваши аксессоры будут иметь доступ к factoryN
p
внутренней области factoryN
(эти factoryN
доступа).
То есть вы собираетесь мутировать один и тот же целевой объект, даже если вы определяете новые дескрипторы в новые экземпляры объектов.
Вывод: если вы не перефразируете свой вопрос, чтобы объяснить, какова ваша фактическая цель, я бы сказал, что нет способа решить проблему.
Я не уверен, что понимаю ваш оператор на отдельной локальной переменной p, определенной на 2 разных закрытиях. Моя забота о obj1.prop1 и obj2.prop2 get/set превращается в простое значение на obj3a
Возьмите свой собственный код:
function Factory1() {
// This is a function scoped reference
const p = {};
return {
get prop1 () { return p.prop; },
set prop1 (value) { p.prop = value; }
};
}
p
- ссылка с привязкой к функциям, а все возвращенные аксессоры - это замыкания, которые фиксируют p
.
Если вы возьмете эти аксессоры и добавите их в другой объект, p
все равно укажет на захваченную ссылку. Таким образом, когда вы устанавливаете prop1
во многих объектах, все они будут устанавливать один и тот же целевой объект p
!
p
определенной для двух различных замыканий. Меня беспокоит то, что obj1.prop1
и obj2.prop2
get / set превратились в простые значения в obj3a
.
p
, тогда да, вам придется создать метод ручного клонирования.