完全指南:从作用域规则到 polyfill 实战)
文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载全局对象是 JavaScript 运行时提供的“公共舞台”其中存放着语言内建对象如Array、Promise以及环境特有的值如浏览器中的window.innerHeight。本篇指南以《现代 JavaScript 教程》中“全局对象”一章为骨架结合本仓库 1-js/13-modules/01-modules-intro/article.md模块机制、1-js/03-code-quality/06-polyfills/article.mdpolyfill 与转译器以及 1-js/06-advanced-functions/04-var/article.md老旧的var等章节的源码级证据帮你彻底理解全局对象有哪些名字、var与let声明在全局作用域上的天壤之别、如何安全地向全局对象写入共享数据以及如何借助全局对象编写 polyfill 检测旧环境。什么是全局对象全局对象global object提供可在任何地方使用的变量和函数。默认情况下这些全局变量内建于语言或环境中无论代码写在哪个作用域都可以直接访问它们。不同 JavaScript 运行环境对全局对象有不同的命名环境全局对象名称浏览器windowNode.jsglobal其他环境可能有别的名字最近globalThis被作为全局对象的标准名称加入到了 JavaScript 中所有环境都应该支持该名称所有主流浏览器都已支持它。因此在实际编码中有一个实用建议如果你的脚本只在浏览器中运行可以放心使用window但如果脚本可能运行在其他环境Node.js、Web Worker 等则最好使用globalThis以保证代码跨环境的可移植性。全局对象的属性可以被直接访问全局对象的所有属性都可以被直接访问也就是说window上的属性等同于全局作用域中的变量alert(Hello); // 等同于 window.alert(Hello);反过来在全局作用域中用var声明的变量也会自动挂载到全局对象上从而获得“处处可见”的能力。var声明的全局变量会成为全局对象的属性在浏览器中使用var而不是let/const声明的全局函数和变量会成为全局对象的属性var gVar 5; alert(window.gVar); // 5成为了全局对象的属性函数声明特指在主代码流中具有function关键字的语句而不是函数表达式也有同样的效果。但请不要依赖这种行为它只是出于历史兼容性而保留的旧机制。现代脚本使用 JavaScript 模块import/export不会产生这种“污染全局对象”的效果。如果我们使用let声明就不会发生这种情况let gLet 5; alert(window.gLet); // undefined不会成为全局对象的属性为什么会这样从源码角度看这是var与let在声明语义上的本质区别。本教程 老旧的 var 一章详细讲解了var没有块级作用域、变量提升等“远古怪兽”特性——正是这种“函数作用域或全局作用域”的声明规则使得顶层var声明会与全局对象绑定而let/const采用块级词法作用域不会写入全局对象。如何显式地向全局对象写入共享值如果一个值非常重要以至于你想使它在全局范围内可用可以直接将其作为属性写入全局对象// 将当前用户信息全局化以允许所有脚本访问它 window.currentUser { name: John }; // 代码中的另一个位置 alert(currentUser.name); // John // 或者如果我们有一个名为 currentUser 的局部变量 // 从 window 显式地获取它这是安全的 alert(window.currentUser.name); // John这里蕴含着一个重要的最佳实践当局部作用域中存在同名变量时通过window.x显式访问全局对象属性是安全的可以避免名字遮蔽shadowing带来的歧义。不过教程同时也给出了严肃的忠告一般不建议使用全局变量全局变量应尽可能的少。与使用外部变量或全局变量相比函数获取“输入”变量并产生特定“输出”的代码设计更加清晰、不易出错且更易于测试。把共享数据显式挂到全局对象上应仅限于“项目级确实需要全局共享”的少量场景。模块环境下的全局变量真相在浏览器中每个script typemodule都有独立的顶级作用域模块之间看不到彼此的顶层变量。本仓库的示例 scopes.view/user.js 中let user John;声明了一个模块级变量另一个脚本试图直接访问它会报错而正确做法是像 scopes-working.view/user.js 那样用export let user John;导出再由 scopes-working.view/hello.js 通过import {user} from ./user.js导入使用。也就是说对于模块我们应该使用导入/导出交换数据而不是依赖全局变量。但如果你确实需要创建“窗口级别”的全局变量可以显式地赋值给window的一个属性例如window.user John——这样所有脚本无论是否带有typemodule都能看到它。需要注意的是模块章节同样强调创建这种全局变量并不是一个好的方式请尽量避免。使用全局对象检测环境并编写 polyfill我们使用全局对象来测试对现代语言功能的支持。例如测试环境中是否存在内建的Promise对象在版本特别旧的浏览器中不存在if (!window.Promise) { alert(Your browser is really old!); }如果没有例如我们使用的是旧版浏览器那么就可以创建 “polyfills”——添加环境不支持但在现代标准中存在的功能if (!window.Promise) { window.Promise ... // 定制实现现代语言功能 }polyfill 的底层原理动态语言的可修补性polyfill 之所以可行是因为JavaScript 是一种高度动态的语言脚本可以添加/修改任何函数甚至包括内建函数。这一点在本教程 Polyfill 和转译器 一章有详尽的展开。polyfill 的典型写法是“先检测、后修补”。比如Math.trunc(n)是一个“截断”数字小数部分的函数Math.trunc(1.23)返回1但一些非常过时的 JavaScript 引擎中并没有这个函数此时可以这样实现 polyfillif (!Math.trunc) { // 如果没有这个函数 // 实现它 Math.trunc function(number) { // Math.ceil 和 Math.floor 甚至存在于上古年代的 JavaScript 引擎中 return number 0 ? Math.ceil(number) : Math.floor(number); }; }同理现代语法层面的新特性如空值合并运算符??无法靠 polyfill 解决需要借助转译器Transpiler处理——例如 Babel 会把height height ?? 100;重写为height (height ! undefined height ! null) ? height : 100;。这就是“新语法用转译器、新内建函数用 polyfill”的分工原则转译器解析现代代码并改写为旧引擎能理解的语法结构polyfill直接向全局对象或内建对象补充缺失的函数实现。在实际项目中两个著名的 polyfill 库包括 core-js支持大量特性、允许按需引入等而 webpack 等现代构建系统提供了在每次代码变更时自动运行转译器的方法可无缝集成到开发流程中。总结全局对象包含应该在任何位置都可见的变量其中包括 JavaScript 的内建方法如Array和环境特有的值如浏览器中的window.innerHeight—— 窗口高度。全局对象有一个通用名称globalThis但更常见的是使用“老式”的环境特定名称例如window浏览器和globalNode.js。仅当值对于项目而言确实是全局的时候才应将其存储在全局对象中并且要保持数量最少。在浏览器中除非我们使用 模块否则使用var声明的全局函数和变量会成为全局对象的属性let/const则不会。为了使代码面向未来并更易于理解我们应该使用直接的方式访问全局对象的属性如window.x。一句话实践准则跨环境代码优先使用globalThis确实需要全局共享的数据用window.x ...显式写入并尽量少用而检测旧环境、补齐缺失内建能力polyfill时全局对象就是你最可靠的“侦察与修补”入口。赞分享文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载相关推荐深入理解 JavaScript 全局对象window、globalThis、全局变量与 Polyfill 实战Modern JavaScript Tutorial深入理解 JavaScript 全局对象window、globalThis、全局变量与 Polyfill 实战Modern JavaScript Tutor文档/教程前端Brython 与 JavaScript 互操作完全指南从 window 对象到 __BRYTHON__ 双向桥接Brython 与 JavaScript 互操作完全指南从 window 对象到 __BRYTHON__ 双向桥接 本文以 BrythonBrowser P编程语言语言运行时编译器前端深入解析 freeCodeCamp JavaScript 全局作用域Global Scope and Functions 挑战深入解析 freeCodeCamp JavaScript 全局作用域Global Scope and Functions 挑战 本篇文章以 freeCodeC前端后端教育上一篇揭秘悟空CRM技术架构TP5.0后端与Vue前端分离的实现原理下一篇终极指南3步快速掌握bkcrack轻松破解传统ZIP加密文件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考