0

I've been reading a little bit into execution contexts and lexical scoping. From my understanding, if a function is declared, it will have a reference to the lexical environment (LE) that defined that function. for example,

var x = 20;
function foo() { 
  console.log(x);
}

So the reason why foo has access to variable x is because foo's LE has a reference to the LE which created foo which is the global LE so it can search through the scope chain until it finds x.

however for the following snippet:

var stacy = {
  name: 'stacy',
  age: 33,
  sayName: function() {
    console.log(this.name);
  }
}
  1. What is the LE of the object stacy? (I believe it would be the global LE)

  2. What is the LE of the sayName()? (if I omit the "this" keyword, why couldn't it find the variable "name" when the function couldn't find "name" in its own LE)?

james
  • 550
  • 8
  • 14
  • Lexical scoping pertains to code, not objects. The code in `sayName()` has a lexical scope. Also referencing `this` is a whole other thing than lexical scope. – Pointy Dec 07 '22 at 21:11
  • @Pointy so what is the lexical scope of sayName? – james Dec 07 '22 at 21:13
  • 1
    @james any variable that `sayName` tries to access that isn't directly defined in the `setName` function will look in the global scope – Samathingamajig Dec 07 '22 at 21:16
  • 2
    @Samathingamajig more accurately it will look within the same scope as the containing object is declared in. @james object properties are not variables, so the function won't even look at them unless you access them as properties, ie `stacy.name` (in which the function will find `stacy` in the outer scope) – pilchard Dec 07 '22 at 21:31
  • 2
    Object properties in a situation like your example are not part of any lexical scope. They are properties of an object, and they require a reference to the object in order to be accessed. – Pointy Dec 07 '22 at 21:32
  • Ok thank you guys :) it's much more clear to me now. – james Dec 07 '22 at 21:36

2 Answers2

2

I use "scope" instead of "LE" here, as the former is more common in JavaScript learning resources.

Functions have their own scope; objects do not. So while (1) the scope of stacy is indeed the global scope, (2) the code of sayName runs in its own scope, for which the parent scope is the global scope. this.name works because non-arrow functions have an additional binding this added to their scope, but name doesn't work because the object isn't a scope, it's just a data structure with a 'name' property. stacy.name would work, and you could declare a name variable with another var or let statement that would work in either scope.

Pixievolt No. 1
  • 780
  • 4
  • 15
0

Example 1:

var x = 20;

function foo() {
  console.log(x);
  console.log(this.x);
}

foo();

In the above example, if we do either console.log(x) or console.log(this.x), it will print the same value. Why so? Because the x is available as a variable to the function foo in its parent scope, it is also available as a property in the global object. The parent object for foo is the global object as it is defined and the function created using the function keyword has a bound context of its parent object by default. Now, look at the second example.

Example 2:

var stacy = {
  name: 'stacy',
  age: 33,
  sayName: function() {
    console.log(name);
    console.log(this.name);
    console.log(stacy.name);
  }
}

stacy.sayName();

In the second example, the console.log(name) and console.log(this.name) will not be equal but console.log(this.name) and console.log(stacy.name) will be equal as per above example's logic.

And the story will be different if use arrow function in place of the function keyword. In arrow function, this keyword refers to the global object.

  • how did you second example not throw a reference error when calling console.log(name) – james Dec 07 '22 at 22:09
  • Anything which is not defined in any of the available scopes in js will have a value undefined. But here in this case of StackOverflow's editor, there might be some definition already available in any of the wrapping js scripts. – Rohit Khandelwal Dec 07 '22 at 22:13
  • Also, js will not throw reference errors for an undefined variable. But if you try something like name.x, this will throw an error. – Rohit Khandelwal Dec 07 '22 at 22:18