lizhongzhen11 / lizz-blog

前端学习
80 stars 6 forks source link

重学js —— 全局对象:值属性与函数属性(globalThis/Infinity/NaN/undefined/eval/isFinite/isNaN) #101

Open lizhongzhen11 opened 4 years ago

lizhongzhen11 commented 4 years ago

全局对象:值属性与函数属性(globalThis/Infinity/NaN/undefined/eval/isFinite/isNaN)

全局对象:

全局对象的值属性

全局对象的函数属性

eval(x)

eval 函数就是 %eval% 固有对象。

  1. 断言:执行上下文栈 至少有两个元素
  2. 定义 callerContext执行上下文栈 倒数第二个元素
  3. 定义 callerRealmcallerRealm领域
  4. 返回 ? PerformEval(x, callerRealm, false, false)

PerformEval( x, callerRealm, strictCaller, direct )

  1. 断言:如果 directfalse,那么 strictCaller 也是 false
  2. 如果 x 不是 String 类型,返回 x
  3. 定义 evalRealm当前领域记录
  4. 执行 ? HostEnsureCanCompileStrings(callerRealm, evalRealm)
  5. 定义 inFunctionfalse
  6. 定义 inMethodfalse
  7. 定义 inDerivedConstructorfalse
  8. 如果 directtrue
    1. 定义 thisEnvRec! GetThisEnvironment()
    2. 如果 thisEnvRecFunction Environment Records
      1. 定义 FthisEnvRec.[[FunctionObject]]
      2. 设置 inFunctiontrue
      3. 设置 inMethodthisEnvRec.HasSuperBinding()
      4. 如果 F.[[ConstructorKind]]derived,设置 inDerivedConstructortrue
  9. 以依赖于实现的顺序执行下面的子步骤,可能交叉解析和错误检测:
    1. 定义 script 为ECMAScript代码,其为 ! UTF16DecodeString(x) 解析结果,用于 目标符号 Script。如果解析失败,抛 SyntaxError 异常。如果检测到早期错误,抛 SyntaxError 异常(根据 错误处理和语言扩展)。
    2. 如果 script 包含 ScriptBodyfalse,返回 undefined
    3. 定义 bodyscriptScriptBody
    4. 如果 inFunctionfalse,且 body 包含 NewTarget,抛 SyntaxError 异常
    5. 如果 inMethodfalse,且 body 包含 SuperProperty,抛 SyntaxError 异常
    6. 如果 inDerivedConstructorfalse,且 body 包含 SuperCall,抛 SyntaxError 异常
  10. 如果 strictCallertrue,定义 strictEvaltrue
  11. 否则,定义 strictEvalscriptIsStrict
  12. 定义 runningContext运行时执行上下文
  13. 注意:如果 directtruerunningContext 将成为执行 直接eval执行上下文。如果 directfalserunningContext 将成为调用 eval 函数的 执行上下文
  14. 如果 directtrue
    1. 定义 lexEnvNewDeclarativeEnvironment(runningContext's LexicalEnvironment)
    2. 定义 varEnvrunningContext's VariableEnvironment
  15. 否则,
    1. 定义 lexEnvNewDeclarativeEnvironment(evalRealm.[[GlobalEnv]])
    2. 定义 varEnvevalRealm.[[GlobalEnv]]
  16. 如果 strictEvaltrue,设置 varEnvlexEnv
  17. 如果 runningContext 没有挂起暂停,则暂停 runningContext
  18. 定义 evalContext 为新的ECMAScript代码 执行上下文
  19. 设置 evalContext's Functionnull
  20. 设置 evalContext's 领域evalRealm
  21. 设置 evalContext's ScriptOrModulerunningContext's ScriptOrModule
  22. 设置 evalContext's VariableEnvironmentvarEnv
  23. 设置 evalContext's LexicalEnvironmentlexEnv
  24. evalContext 推入 执行上下文栈evalContext 现在是 运行时执行上下文
  25. 定义 resultEvalDeclarationInstantiation(body, varEnv, lexEnv, strictEval)
  26. 如果 result.[[Type]]normal
    1. 设置 result 为求值 body 的结果
  27. 如果 result.[[Type]]normalresult.[[Value]]empty
    1. 设置 resultNormalCompletion(undefined)
  28. 暂停 evalContext 且将其从 执行上下文栈 中移除
  29. 恢复 执行上下文栈 顶上下文为 运行时执行上下文
  30. 返回 Completion(result)

注意:如果调用上下文正在对形参初始化器求值或调用上下文的代码或者eval代码是 严格模式,那么eval代码不能在调用eval的上下文变量环境中实例化变量或函数绑定。上述绑定会在新的只有eval代码才能访问的变量环境中实例化。let, const, class 声明总是在新的词法环境进行实例化绑定。

isFinite( number )

先转 Number

isFinite(Infinity) // false
isFinite(NaN) // false
isFinite(-Infinity) // false
isFinite(0) // true
isFinite(2e64) // true
isFinite("0") // true
isFinite(9n) // Uncaught TypeError: Cannot convert a BigInt value to a number
isFinite(undefined) // false
isFinite(null) // true
isFinite({}) // false
isFinite([]) // true

isFinite 函数就是 %isFinite% 固有对象。

  1. 定义 num? ToNumber(number)
  2. 如果 numNaN+∞-∞,返回 false
  3. 否则返回 true

由于内部用的是 ToNumber 算法,所以对于对象,改写其 toString 方法返回有限值就能得到 true

const obj = {
  toString() {
    return 1
  }
}
Number(obj) // 1
isFinite(obj) // true

isNaN

对应 %isNaN% 固有对象。

isNaN(NaN) // true
isNaN({}) // true
  1. 定义 num? ToNumber(number)
  2. 如果 numNaN,返回 true
  3. 否则返回 false

内部用的是 ToNumber 算法,所以对于对象,改写其 toString 方法返回非 NaN 值就能得到 true

本篇结束,后续见下一篇