If you want to know why that happen the answer is simple, hoisting moves all the declarations to the top of his scope, so:
console.log(this.abc); //undefined
console.log(abc in this); //true
console.log(abc); //undefined
function abc() {
console.log("hello");
}
console.log(abc); //ƒ abc(){console.log("hello");
so in the inner function, the function abc() is declared at the top of the current scope staying almost at the same position, but just the declaration, so the var abc is declared then assigned, when you try access at the bottom he already knows the function, in the first console.log where you get undefined
console.log(abc) the function _abc is not decalred yet, but in the second example you have access to it because it access the windows object and get the abc.
so in short terms, javascript first initialize variables, since at the second console.log all the variables are already declared and they are declared at the window object, accessing abc on this works fine.