Здравствуйте! У меня есть следующий код: <br/> <pre><code class="javascript">let arr=[{
key1:1,
key2:2,
key3:3,
children:{
render(){
console.log(this.key1,"Key");//undefined
}
}
}]</code></pre> <br/> Возможно ли создать объект `children`, который будет ссылаться на контекст родительского объекта, не используя переменную `arr`?
Да, вы можете создать объект `children`, который будет ссылаться на контекст родительского объекта, используя стрелочные функции или связывание контекста с помощью `.bind`, но без использования переменной `arr`. Вот два способа, как это сделать:
1. **Использование стрелочной функции**:
Стрелочные функции не имеют собственного контекста, поэтому они будут наследовать `this` от родителя. В вашем случае вы можете использовать стрелочную функцию внутри метода `render`.
```javascript
let arr = [{
key1: 1,
key2: 2,
key3: 3,
children: {
render: () => {
console.log(arr[0].key1, "Key"); // 1 Key
}
}
}];
arr[0].children.render();
```
2. **Использование метода `bind`**:
Вы можете явно привязать контекст метода `render` к родительскому объекту.
```javascript
let arr = [{
key1: 1,
key2: 2,
key3: 3,
children: {
render: function() {
console.log(this.key1, "Key"); // 1 Key
}
}
}];
arr[0].children.render.bind(arr[0])();
```
В обоих вариантах `render` имеет доступ к `key1` родительского объекта, что позволяет корректно вывести его значение в консоль. Однако в первом варианте вы всё равно обращаетесь к `arr`, что, по сути, является ссылкой на родительский объект.
Если же вы хотите избежать использования `arr` и хотите сделать это более "чисто", вот еще один способ, как это сделать, используя `Proxy`:
```javascript
const parentObj = {
key1: 1,
key2: 2,
key3: 3,
};
const childObj = {
render() {
console.log(this.key1, "Key"); // 1 Key
}
};
// Создание прокси, который будет передавать контекст родителя
const proxiedChild = new Proxy(childObj, {
get(target, prop, receiver) {
if (prop === "render") {
return target.render.bind(parentObj); // Привязываем метод к parentObj
}
return Reflect.get(target, prop, receiver);
}
});
proxiedChild.render(); // 1 Key
```
Таким образом, вы создаете объект `children`, который имеет контекст родительского объекта, не используя переменную `arr`.
<pre><code class="javascript">class Foo
{
constructor() {
this.key1 = 'key 1'
this.bar = new Bar(this)
}
}
class Bar {
constructor(parent) {
this.parent = parent
}
redner() {
console.log('Parent key 1:', this.parent.key1)
}
}</code></pre>
<pre><code class="javascript">function bindRootContext(obj, context = obj) {
return new Proxy(obj, {
get(target, key) {
const val = target[key];
if (val instanceof Function) {
return val.bind(Array.isArray(target) && Object.hasOwn(Array.prototype, key)
? target
: context
);
} else if (val instanceof Object) {
return bindRootContext(val, context);
}
return val;
},
});
}
const obj = bindRootContext({
name: 'Root',
a: {
name: 'A',
logName() { console.log(this.name); },
b: {
name: 'B',
logName() { console.log(this.name); },
arr: [
{
name: '666',
logName() { console.log(this.name); },
},
function() { console.log(this.name); },
],
c: {
name: 'C',
logName() { console.log(this.name); },
},
},
},
});
obj.a.b.c.logName(); // Root
obj.a.b.logName(); // Root
obj.a.logName(); // Root
obj.a.b.arr[0].logName(); // Root
obj.a.b.arr[1](); // Root</code></pre>