Following the previous article [series] Learning Environment Records from the ECMAScript Specification for execution context (Middle), Object Environment Record and Global Environment Record

Object Environment Record

The most core feature of Object Environment Record is that it has a binding Object. The Object Env binds all the string attributes of the Object as identifiers in the env, so that these identifiers can be directly used in the corresponding scope. Attributes that are not strings are not bound as identifiers.

  • Env binds the binding object itself and inherited properties as identifiers
  • Env’s identifier bindings are also changed by adding or subtracting a binding object attribute, and all new bindings are mutable (even if the attribute is not writable).

The Object Env has the following specialized fields:

The field names An optional value paraphrase
[[BindingObject]] object The binding Object mentioned above
[[IsWithEnvironment]] Boolean Used to indicate whether the env iswithStatement created by

The execution logic of the Object Environment Record method

HasBinding ( N )

  • let: bindingObject = env.[[BindingObject]]
  • let: foundBinding = HasProperty(bindingObject, N)
  • If: foundBinding to false,return false.
  • if: envRec.[[IsWithEnvironment]] is false, return true
  • let: unscopables = Get(bindingObject, @@unscopables)
  • If Type(unscopables) is Object, then:
    • let: blocked = ToBoolean(? Get(unscopables, N))
    • If: blocked to true,return false
  • return true

Tc39.es /ecma262/#se…

@@unscopables is a built-in Symbol. For details, see developer.mozilla.org/zh-CN/docs/…

CreateMutableBinding ( N, D )

  • let: bindingObject = env.[[BindingObject]]
  • return DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }).

DefinePropertyOrThrow Object. DefineProperty method tc39.es/ ecMA262 /#se…

CreateImmutableBinding ( N, S )

Is not used in object env

InitializeBinding ( N, V )

  • Call env.setMutableBinding (N, V, false)

SetMutableBinding ( N, V, S )

  • let: bindingObject = env.[[BindingObject]]
  • let: stillExists = HasProperty(bindingObject, N)
  • If: stillExists is false and S is true, a ReferenceError is directly raised
  • return Set(bindingObject, N, V, S)

A Set is an attribute written to an object. It can be described in tc39.es/ ECMA262 /#se…

GetBindingValue ( N, S )

  • let: bindingObject = env.[[BindingObject]]
  • let: value = HasProperty(bindingObject, N)
  • If: value is false then:
    • If: S to false,returnundefined; Otherwise a ReferenceError is raised
  • return Get(bindingObject, N)

DeleteBinding ( N )

In the Object Env, the binding name N can be deleted only if the bind object attribute is [[64x]] = true

  • let: bindingObject = env.[[BindingObject]]
  • return bindingObject.[[Delete]] (N)

[[Delete]] [tc39.es/ ecMA262 /#se…

HasThisBinding ( )

  • return false

HasSuperBinding ( )

  • return false

WithBaseObject ( )

  • If: env.[[IsWithEnvironment]] is true,return env.[[BindingObject]]
  • else: return undefined

Global Environment Record

The Global Environment Record represents the outermost scope. It provides bindings for built-in Global objects, properties of Global objects, and all top-level declarations within script elements.

A Global Environment Record is logically a separate ENV, but in the standard definition, it is actually a combination of object Environment Record and Declarative Environment Record.

  • Object Environment Record contains all built-in global variables, NaN, undefined, Infinity, parseInt, parseFloat, etc. These are included in the binding of the Environment Record. Combined with the use of the with statement (which creates an object env), we can see why NaN can be written directly in code rather than global.nan. All of these attributes or methods can be referred to chapter 19 of the Standard (TC39.ES/ECMA262 /# SE…).

  • In addition to these built-in global variables, the Object Environment Record contains bindings declared by the following syntax: function declarations, Generator function declarations, async, asynchronous generator function declarations, and VAR declarations.

  • In addition to the above, other declarations in the global Environment are included in the Declarative Environment Record, such as the let, const, and class statements in the global Environment.

Fields and methods unique to the Global Environment Record

The Global Environment Record has the following additional fields:

The field names An optional value paraphrase
[[ObjectRecord]] Object Environment Record That is, the object Environment Record mentioned above
[[GlobalThisValue]] Object This value in the global scope. The host environment may provide any object as this value
[[DeclarativeRecord]] Declarative Environment Record The Declarative Environment Record mentioned above
[[VarNames]] String[] Under the global scope byFunction declaration,Generator function declaration,Asynchronous function declaration (Async),Asynchronous Generator function declarationandThe var statementA list of the resulting binding names

The Global Environment Record has the following additional methods:

Method names paraphrase
GetThisBinding() Returns the value of env’s this binding
HasVarDeclaration (N) Check if env exists with the name N and is passedFunction declaration,Generator function declaration,Asynchronous function declaration (Async),Asynchronous Generator function declarationandThe var statementThe binding created
HasLexicalDeclaration (N) Determine if env has a binding named N that was created by a lexical declaration. Lexical declarations include let, const, class, and so on
HasRestrictedGlobalProperty (N) Determines whether name N is a restricted property of the globe
CanDeclareGlobalVar (N) Determines whether CreateGlobalVarBinding(N) was successfully called
CanDeclareGlobalFunction (N) Determine CreateGlobalFunctionBinding (N) whether the call is successful
CreateGlobalVarBinding(N, D) The following is a separate introduction
CreateGlobalFunctionBinding(N, V, D) The following is a separate introduction

First key here introduce CreateGlobalVarBinding (N, D) and CreateGlobalFunctionBinding (N, V, D) these two methods:

– CreateGlobalVarBinding(N, D)

Used to create a binding in the Object Environment Record component and initialize it with an alias N, the initial value being undefined. The binding is a mutable binding, and if D is true, the binding may be removed. In addition, the global object will have an attribute named N, which will also be assigned a value

This explains why variables declared by var in global scope can pass “global”. Variable name “to access

– CreateGlobalFunctionBinding(N, V, D)

Used to create and initialize a function binding in the Object Environment Record component, where V is the initialization binding value (that is, the bound function). The binding is a mutable binding, and if D is true, the binding may be removed. In addition, the global object will have an attribute named N whose value is the function V

Execution logic of the Global Environment Record method

HasBinding ( N )

  • let: DclRec = env.[[DeclarativeRecord]]
  • If: dclrec.hasbinding (N), returns true
  • let: ObjRec = env.[[ObjectRecord]]
  • return ObjRec.HasBinding(N)

CreateMutableBinding ( N, D )

  • let: DclRec = env.[[DeclarativeRecord]]
  • If: dclrec.hasbinding (N) is true and raises TypeError directly
  • return DclRec.CreateMutableBinding(N, D).

CreateImmutableBinding ( N, S )

Similar to CreateMutableBinding, except that the CreateImmutableBinding method of DeclarativeRecord is called as the last step

InitializeBinding ( N, V )

  • let: DclRec = env.[[DeclarativeRecord]]
  • If: DclRec HasBinding (N) is true
    • return DclRec.InitializeBinding ( N, V )
  • Assert: If a binding named N exists, it must exist in the Object Environment Record
  • let: ObjRec = env.[[ObjectRecord]]
  • return ObjRec.InitializeBinding(N, V)

SetMutableBinding ( N, V, S )

  • let: DclRec = env.[[DeclarativeRecord]]
  • If: DclRec HasBinding (N) is true
    • return DclRec.SetMutableBinding ( N, V, S )
  • let: ObjRec = env.[[ObjectRecord]]
  • return ObjRec.SetMutableBinding ( N, V, S )

GetBindingValue ( N, S )

This is similar to the SetMutableBinding method above, except that the GetBindingValue methods of DclRec and ObjRec are called, respectively

DeleteBinding ( N )

  • let: DclRec = env.[[DeclarativeRecord]]
  • If: DclRec HasBinding (N) is true
    • return DclRec.DeleteBinding ( N )
  • let: ObjRec = env.[[ObjectRecord]]
  • let: globalObject = ObjRec.[[BindingObject]]
  • let: existingProp = HasOwnProperty(globalObject, N)
  • if: existingProp = true:
    • let:status = ObjRec.DeleteBinding(N)
    • : if the status is true:
      • let: varNames = envRec.[[VarNames]]
      • If N is an element of varNames, it is removed from varNames
    • return status
  • return true

HasThisBinding ( )

return true

Global env provides this binding

HasSuperBinding ( )

  • return false

WithBaseObject ( )

  • return undefined

Although there is an object env component in the Global env, this component is not created by the with statement, so undefined is always returned

GetThisBinding ( )

  • return env.[[GlobalThisValue]]

HasVarDeclaration ( N )

  • let: varDeclaredNames = envRec.[[VarNames]]
  • If: varDeclaredNames contains N,The return true
  • return false

HasLexicalDeclaration ( N )

  • let: DclRec = env.[[DeclarativeRecord]]
  • return DclRec.HasBinding(N)

HasRestrictedGlobalProperty ( N )

Used to determine whether identifier N is a property of the Global object. This property cannot be overridden by a global lexical declaration

  • let: ObjRec = env.[[ObjectRecord]]
  • let: globalObject = ObjRec.[[BindingObject]]
  • let: existingProp = globalObject.GetOwnProperty(N)
  • If: existingProp = undefined,return false
  • If: existingProp.[[signals]] works without any additional control system.return false
  • return true

CanDeclareGlobalVar ( N )

  • let: ObjRec = env.[[ObjectRecord]]
  • let: globalObject = ObjRec.[[BindingObject]]
  • let: hasProperty = HasOwnProperty(globalObject, N)
  • If: hasProperty is true,return true
  • return IsExtensible(globalObject)

IsExtensible can be understood as Object. IsExtensible methods

CanDeclareGlobalFunction ( N )

  • let: ObjRec = env.[[ObjectRecord]]
  • let: globalObject = ObjRec.[[BindingObject]]
  • let: existingProp = globalObject.GetOwnProperty(N)
  • If: existingProp = undefined,return IsExtensible(globalObject)
  • If: existingProp. [[Configurable]] is true,return true
  • ExistingProp has attribute Values {[[Writable]]: true, [[Enumerable]]: true },return true

return false

IsDataDescriptor(desc) is true if the attribute descriptor desc has neither writable nor value. Otherwise it is false

CreateGlobalVarBinding ( N, D )

This method creates a mutable binding in the Object Environment Record component of the Global Env and adds the identifier N to the [[varNames]] Record

  • let: ObjRec = env.[[ObjectRecord]]
  • let: globalObject = ObjRec.[[BindingObject]]
  • let: hasProperty = HasOwnProperty(globalObject, N)
  • let: extensible = IsExtensible(globalObject)
  • If: hasProperty is false and extensible to true:
    • Perform ObjRec. CreateMutableBinding (N, D)
    • Perform ObjRec. InitializeBinding (N, undefined)
  • let: varDeclaredNames = env.[[VarNames]]
  • If: varDeclaredNames does not already contain N, add N to the varDeclaredNames record
  • return

CreateGlobalFunctionBinding ( N, V, D )

  • let: ObjRec = env.[[ObjectRecord]]
  • let: globalObject = ObjRec.[[BindingObject]]
  • let: existingProp = globalObject.GetOwnProperty(N)
  • If: exists prop is undefined or exists ingProp.[[64x]] works without any additional information.
    • Let:descAttribute descriptor = PropertyDescriptor {[[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[64x]]: 64x}
  • Otherwise:
    • Let:desc= PropertyDescriptor {[[Value]]: V}
  • Do: DefinePropertyOrThrow(globalObject, N, desc)
  • Execute: Set(globalObject, N, V, false)
  • let: varDeclaredNames = env.[[VarNames]]
  • If: varDeclaredNames does not already contain N, add N to the varDeclaredNames record
  • return