It's not there because this
in JS is dynamic and depends on the scope.
- Arrow functions don't have their own scope, so
obj.first()
will not return you obj
but instead returns the global context (in a browser, usually window
) or undefined
when running in strict mode
!
- Functions via
function
do have a dedicated scope. However, when you call obj.other.sec()
, the context of this
in the sec
function points to obj.other
, not obj
.
- The function returned by
obj.other.sec()
does (or rather: can) create a new scope, since it's called without a context. But since it's also called without new
, this
points to the global context (see point 1).
Depending on what you want to achieve, the simplest solution is to replace this
with the correct context. For example, if you want all function to run in the context of obj
, just replace every this
with obj
:
const obj = {
name: 'Hi',
first: () => {
return obj;
},
other: {
name: 'last',
sec: function() {
obj.c = '2'
return function() {
obj.s = '3'
return obj;
}
}
}
}
const t = obj.other.sec()
console.log(t()) // <-- now logs `obj` with a `c` and an `s` property added
Or maybe you want varying context's:
const obj = {
name: 'Hi',
first: () => {
return obj;
},
other: {
name: 'last',
sec: function() {
obj.other.c = '2'
return function() {
obj.other.s = '3'
return obj.other;
}
}
}
}
const t = obj.other.sec()
console.log(t()) // <-- now logs `obj.other` with a `c` and an `s` property added
And in case obj.other.sec()
should return a new object that is not related to obj
or obj.other
, then... well... just return a new object:
const obj = {
name: 'Hi',
first: () => {
return obj;
},
other: {
name: 'last',
sec: function() {
obj.other.c = '2'
return function() {
return { s: 3 };
}
}
}
}
const t = obj.other.sec()
console.log(t()) // <-- now logs a new object with an `s` property
You can read more about the dynamic nature of this
on MDN