区块链技术博客
www.b2bchain.cn

【WWDC21 10030】高级 Web 内容开发求职学习资料

本文介绍了【WWDC21 10030】高级 Web 内容开发求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

作者:乐鹰神骑俊,iOS开发者,目前从事智能家居设备连接控制方向的工作 :)

审核:折腾范儿_唯敬,iOS/前端 开发者,就职于阿里巴巴,喜欢研究跨平台动态化混合前端相关的内容,目前从事移动应用客户端/前端相关开发工作。

【WWDC21 10030】高级 Web 内容开发

本文基于session 10030 – Develop advanced web content 梳理

引言

Web 应用作为互联网内容的重要组成部分,近些年随着 Web2.0 概念的蓬勃发展和包括 WebAssembly、WebGL2.0 等技术的演进,Web 应用在很多场景下已经具备和原生相媲美的性能,Apple 在过去的一年中为 Web 应用带来了哪些改进,Safari 和 Webkit 又新添了一些怎样有趣又好玩的功能呢,让我们跟随 WWDC21 一起来探索一下吧~

Tips:

  • 本文主要面向使用 JavaScript、WebAssembly、WebGL 的 Web 应用开发者。

  • 本文提及部分特性或 API 在 Safari14.2 以下版本中可能暂未支持,可以使用 Safari Technology Preview – 14.2 调试。

  • 具体 API 的使用和支持情况可以参考 MDN Web Docs ,但文档更新可能会有延迟。

  • 文末有示例代码链接。

本文知识目录:

【WWDC21 10030】高级 Web 内容开发

JavaScript 语法增强

1. 使用 # 修饰类的属性、静态变量、方法,保证它们仅在类的内部可见。

需要注意的是增加 # 后,# 已经是名称的一部分,比如 #_startTime 才是一个完整的变量名。

//class with private variable and function class PrivateStopWatchWithOneButton {   // 使用 # 定义私有变量     #_startTime = 0;    // 使用 # 定义私有静态变量     static #stopWatchCount = 0;      click(){         if (!this.#_startTime) {             this.#start();         }else{             this.#stop();         }     }      // 使用 # 定义私有方法     #start() {         PrivateStopWatchWithOneButton.#stopWatchCount++;         this.#_startTime = Date.now();         console.log('StopWatch started');     } }  function demo(){     var counter = new StopWatchWithOneButton();     counter.click();     counter.#stopWatchCount = 0; //SyntaxError   counter.#start();//SyntaxError }

2. WeakRef 一种新的弱引用方法

Map 和 Set 是 JavaScript 中常用的集合类型,为了实现更高效的垃圾回收,在部分情况下需要通过 WeakMapWeakSet 实现对集合对象的弱引用,但是 WeakMapWeakSet 没有 Iterator 接口,因而无法实现迭代的逻辑。所以 Apple 今年给出了几个新的接口,比如通过 WeakRef 获得对象的弱引用,同时可以通过 FinalizationRegistry 得知弱引用的对象被垃圾回收的时机,然后在注册的回调中执行一些清理操作。

其中关键的几个概念:

WeakRef:允许您保留对另一个对象的弱引用,而不会阻止被弱引用对象被 GC 回收 FinalizationRegistry:可以让你在对象被垃圾回收时请求一个回调。 deref:返回 WeakRef 实例的目标对象,如果目标对象已被垃圾收集,则返回 undefined 。

下面是一段伪代码:

class StopWatchWithOneButton {     _startTime = 0;     click(){     //...   }     //some detail implimentation... }  const allStopWatches  = new Map(); var nextAvailableIdentifier = 1; function removeStopwatch(identifier){   /*   当 map 中引用的 StopWatchWithOneButton 对象由于某种原因 (生命周期结束 / 手动销毁) 被系统回收后,   需要将当前的 Map 数据清理一下。   */     allStopWatches.delete(identifier); }  // 通过 FinalizationRegistry 新建一个注册表,同时注册关联的回调函数 const finalizationRegistry = new FinalizationRegistry(removeStopwatch);  function createStopwatch(){     let identifier = nextAvailableIdentifier++;     let stopwatch = new StopWatchWithOneButton();    //WeakRef()获得 stopwatch 的弱引用     allStopWatches.set(identifier, new WeakRef(stopwatch));   /*    将 stopwatch 注册到 finalizationRegistry 这个注册表中,当 stopwatch 被垃圾回收时,   便会调用上面的 removeStopwatch 函数,实现 allStopWatches 这个 map 数据的清理。   */     finalizationRegistry.register(stopwatch, identifier);      return stopwatch; }  function clickAllStopwatches(){     console.log('ready to click all buttons');   for(let weakStopwatch in allStopWatches.values()){     //迭代获取 weakStopwatch,通过 deref() 判断对象是否被 GC     weakStopwatch.deref()?.click();   } }

但是由于 FinalizationRegistry 的运行依赖于 GC,GC 的运行又依赖于 event loop 机制,所以存在一些不确定性。比如回调时机可能和你预期的不一致,所以在使用之前要评估下你的场景是否适用这几个方法,避免掉到坑里。

3. 采用 await 方式 import Module

await 这个概念出现在了很多的编程语言中,它的最主要特征就是简化异步调用,让代码的可读性极大增强。原来 await 只能在 async 函数中使用,但是现在也可以在 import module 的时候使用,让 module 之间的依赖管理变得更加简单,比如像下面这样:

<!-- wait until module is imported with top-level await--> <script type='module' id='inline-module'>     var stopwatch;     try{         let {StopWatchWithOneButton} = await import('./stopwatchInModule.js');         stopwatch = new StopWatchWithOneButton();     } catch(error){       console.log(error);     } </script>  //Another file stopwatchInModule.js export class StopWatchWithOneButton {     _startTime = 0;     click(){     //...   }     //some detail implimentation... }

上述 await 方法的使用,有以下两个效果:

  • stopwatch = new StopWatchWithOneButton(); 会在 import 执行完成之后再执行。

  • 如果被 import 的 stopwatchInModule.js 中有异步任务执行,stopwatch = new StopWatchWithOneButton(); 会在异步任务执行完成后继续执行。

需要注意的是,await 用来 import module 的时候仅在 module 类型的 script 中有效,其他类型的 script 会直接报错。

4. 在 worker 中使用 module

由于 JavaScript 采用的是单线程模型,Web Worker 则为 JavaScript 创造了多线程环境,主线程可以通过创建 Worker 在子线程中执行一些脚本,将一些计算密集型或者高延迟的任务放到后台运行,保证 UI 交互的流畅性。而 module 则可以实现动态 import、对加载和执行实现优化、实现依赖管理。所以在 Worker 中使用 Module 可以更轻松的将一些 heavy work 转移到后台线程。module 现在可以应用于多种不同类型的 Worker 中,比如: WebWorker、ServiceWorker 和 Worklet。

具体的使用方法如下:

// 在 web worker 中的用法 let worker = new Worker(moduleScriptURL,{type:"module"}) // 在 service worker 中的用法 nivagator.serviceWorker.register(scriptURL,{type:"module"}); // 在 worklet 中的用法 var audioContext = new AudioContext(); dusioContext.audioWorklet.addModule(moduleScriptURL);

5. Internationalization API 的更新

【WWDC21 10030】高级 Web 内容开发

今年更新了 5 个国际化的 API, 他们的功能在图片中一目了然了,具体如下:

  • Intl.NumberFormat 设置数字显示格式
  • Intl.DateTimeFormat 根据不同国家设置时间 / 日期的显示格式
  • Intl.Segmenter 根据不同语言的语法规则进行分词
  • Intl.ListFormat 根据不同语言的语法进行连词
  • Intl.DisplayNames 自动根据当前页面设置的语言,展示语言切换内容

其中最值得一提的是 Intl.Segmenter,可以实现语句的分词功能,在做一些算法的时候进行分词是一项基本的工作,在此基础之上可以做很多有趣的功能,更详细的代码参见 demo,感兴趣的同学不妨一试。

WebAssembly

2008 年很多浏览器中开始引入 JITs,实现了 JS 运行速度的骤然提升,而 WebAssembly 被认为可能是 Web 应用性能提升的又一个转折点,funkykarts 就是一个采用 WebAssembly 的例子,其实 funkykarts 的源码是使用 C++ 来实现的,那在 Web 中的这一切又是怎么做到的呢?

【WWDC21 10030】高级 Web 内容开发

WebAssembly 可以理解为一种 web 版的汇编,其实它并不是一种编程语言,但是可为 C/C++/Rust 等高级语言提供一个高效的编译目标,使 Web 应用程序获得和原生 App 相媲美的性能。这就意味着,对于一个现成的 Native 应用,为了将它移植到 web 中,不需要从头开始编写 JavaScript 代码,通过 WebAssembly 将它编译成浏览器支持的 wasm 模块,然后通过 Webassembly API 执行调用即可。这一过程如下图所示:

【WWDC21 10030】高级 Web 内容开发

上图中 Emscripten 是一种生成 wasm 的工具,目前常见的这类工具还包括:

编程语言 Center Aligned
C/C++ Emscripten
Rust wasm-pack
TypeScript AssemblyScript
asm.js Binaryen
Java 字节码 TeaVM

目前 Chrome、FireFox 和 Safari 都已支持 WebAssembly,在具体的功能上还存在些微差异,具体的支持情况可以参考下图。更详细的信息可以在 WebAssembly 官网 找到。其中的第一列 Your browser 指的是我打开网页时使用的 Safari Technology Preview(V14.2)。

【WWDC21 10030】高级 Web 内容开发

从上图可以出今年 Apple 在最新版本的 Safari 上对 WebAssembly 增加了多项功能的支持,具体包括在以下几个方面:

  • 通过采用新的内存指令让批量内存操作具备更好的性能。比如批量的复制和初始化操作。

  • 通过新的指令告诉用户进程在部分情况下无需捕获异常。比如在 float 和 int 之间转换时的正溢出。

  • 新增了符号扩展运算符,实现低位数转高位数,所谓的低位数转高位数的基本原理就是在低位数的左边补上低位数的符号位,直到数字位数达到要求。用来实现 WebAssembly 的 i64 类型和 JavaScript 的 BigInt 数据类型之间的转换,这一改进可以提高代码的执行速度并且比之前的实现方法更加简单。

  • 增加了新的引用类型,允许 WebAssembly 模块持有 JavaScript 和 DOM 对象的引用,并且可以传递和保存它们。

  • 通过数据流式的下载和编译,缩短了整体执行时间。

New Web APIs

在 10030 这个 session 中,还提供了一系列 API 的更新,这部分 API 各自适用于不同的场景,有些功能还是很有意思的,比如 Speech Recogintion 可以借助 Siri 引擎实现实时文本转换,Web Share 功能今年新增了文件共享,而 Storage Access 在保证用户 Cookies 安全性的前提下增加了适用范围。下面分别介绍一下它们:

【WWDC21 10030】高级 Web 内容开发

1. WebGL2.0

WebGL 是实现页面渲染的不二法门,可以帮助开发者在 Web 中实现非常绚丽的画面效果,就像下图这样,Apple 这次在 Safari 和 Webkit 中为我们带来了 WebGL2.0 的支持,下面我们就简单解下什么是 WebGL2.0:

【WWDC21 10030】高级 Web 内容开发

WebGL2.0 是基于 OpenGL ES 3.0 实现的 Web API,核心是 WebGL2RenderingContext 接口,在 WebGL1.0 的基础上增加了很多的新特性,比如:

  • 增加了 3D 纹理,能够渲染出像云朵一样的 volumetric effects (容积效果)。

  • 它的 WebGLSampler 可以用来存储一系列采样参数,在着色器中使用纹理更加灵活。

  • 增加了 Transform Feedback 来帮助在 GPU 上实现高性能的粒子系统效果。

文字描述有点抽象,从效果图中简单感受下可以带给用户的体验吧~

作者:乐鹰神骑俊,iOS开发者,目前从事智能家居设备连接控制方向的工作 :)

审核:折腾范儿_唯敬,iOS/前端 开发者,就职于阿里巴巴,喜欢研究跨平台动态化混合前端相关的内容,目前从事移动应用客户端/前端相关开发工作。

【WWDC21 10030】高级 Web 内容开发

本文基于session 10030 – Develop advanced web content 梳理

引言

Web 应用作为互联网内容的重要组成部分,近些年随着 Web2.0 概念的蓬勃发展和包括 WebAssembly、WebGL2.0 等技术的演进,Web 应用在很多场景下已经具备和原生相媲美的性能,Apple 在过去的一年中为 Web 应用带来了哪些改进,Safari 和 Webkit 又新添了一些怎样有趣又好玩的功能呢,让我们跟随 WWDC21 一起来探索一下吧~

Tips:

  • 本文主要面向使用 JavaScript、WebAssembly、WebGL 的 Web 应用开发者。

  • 本文提及部分特性或 API 在 Safari14.2 以下版本中可能暂未支持,可以使用 Safari Technology Preview – 14.2 调试。

  • 具体 API 的使用和支持情况可以参考 MDN Web Docs ,但文档更新可能会有延迟。

  • 文末有示例代码链接。

本文知识目录:

【WWDC21 10030】高级 Web 内容开发

JavaScript 语法增强

1. 使用 # 修饰类的属性、静态变量、方法,保证它们仅在类的内部可见。

需要注意的是增加 # 后,# 已经是名称的一部分,比如 #_startTime 才是一个完整的变量名。

//class with private variable and function class PrivateStopWatchWithOneButton {   // 使用 # 定义私有变量     #_startTime = 0;    // 使用 # 定义私有静态变量     static #stopWatchCount = 0;      click(){         if (!this.#_startTime) {             this.#start();         }else{             this.#stop();         }     }      // 使用 # 定义私有方法     #start() {         PrivateStopWatchWithOneButton.#stopWatchCount++;         this.#_startTime = Date.now();         console.log('StopWatch started');     } }  function demo(){     var counter = new StopWatchWithOneButton();     counter.click();     counter.#stopWatchCount = 0; //SyntaxError   counter.#start();//SyntaxError }

2. WeakRef 一种新的弱引用方法

Map 和 Set 是 JavaScript 中常用的集合类型,为了实现更高效的垃圾回收,在部分情况下需要通过 WeakMapWeakSet 实现对集合对象的弱引用,但是 WeakMapWeakSet 没有 Iterator 接口,因而无法实现迭代的逻辑。所以 Apple 今年给出了几个新的接口,比如通过 WeakRef 获得对象的弱引用,同时可以通过 FinalizationRegistry 得知弱引用的对象被垃圾回收的时机,然后在注册的回调中执行一些清理操作。

其中关键的几个概念:

WeakRef:允许您保留对另一个对象的弱引用,而不会阻止被弱引用对象被 GC 回收 FinalizationRegistry:可以让你在对象被垃圾回收时请求一个回调。 deref:返回 WeakRef 实例的目标对象,如果目标对象已被垃圾收集,则返回 undefined 。

下面是一段伪代码:

class StopWatchWithOneButton {     _startTime = 0;     click(){     //...   }     //some detail implimentation... }  const allStopWatches  = new Map(); var nextAvailableIdentifier = 1; function removeStopwatch(identifier){   /*   当 map 中引用的 StopWatchWithOneButton 对象由于某种原因 (生命周期结束 / 手动销毁) 被系统回收后,   需要将当前的 Map 数据清理一下。   */     allStopWatches.delete(identifier); }  // 通过 FinalizationRegistry 新建一个注册表,同时注册关联的回调函数 const finalizationRegistry = new FinalizationRegistry(removeStopwatch);  function createStopwatch(){     let identifier = nextAvailableIdentifier++;     let stopwatch = new StopWatchWithOneButton();    //WeakRef()获得 stopwatch 的弱引用     allStopWatches.set(identifier, new WeakRef(stopwatch));   /*    将 stopwatch 注册到 finalizationRegistry 这个注册表中,当 stopwatch 被垃圾回收时,   便会调用上面的 removeStopwatch 函数,实现 allStopWatches 这个 map 数据的清理。   */     finalizationRegistry.register(stopwatch, identifier);      return stopwatch; }  function clickAllStopwatches(){     console.log('ready to click all buttons');   for(let weakStopwatch in allStopWatches.values()){     //迭代获取 weakStopwatch,通过 deref() 判断对象是否被 GC     weakStopwatch.deref()?.click();   } }

但是由于 FinalizationRegistry 的运行依赖于 GC,GC 的运行又依赖于 event loop 机制,所以存在一些不确定性。比如回调时机可能和你预期的不一致,所以在使用之前要评估下你的场景是否适用这几个方法,避免掉到坑里。

3. 采用 await 方式 import Module

await 这个概念出现在了很多的编程语言中,它的最主要特征就是简化异步调用,让代码的可读性极大增强。原来 await 只能在 async 函数中使用,但是现在也可以在 import module 的时候使用,让 module 之间的依赖管理变得更加简单,比如像下面这样:

<!-- wait until module is imported with top-level await--> <script type='module' id='inline-module'>     var stopwatch;     try{         let {StopWatchWithOneButton} = await import('./stopwatchInModule.js');         stopwatch = new StopWatchWithOneButton();     } catch(error){       console.log(error);     } </script>  //Another file stopwatchInModule.js export class StopWatchWithOneButton {     _startTime = 0;     click(){     //...   }     //some detail implimentation... }

上述 await 方法的使用,有以下两个效果:

  • stopwatch = new StopWatchWithOneButton(); 会在 import 执行完成之后再执行。

  • 如果被 import 的 stopwatchInModule.js 中有异步任务执行,stopwatch = new StopWatchWithOneButton(); 会在异步任务执行完成后继续执行。

需要注意的是,await 用来 import module 的时候仅在 module 类型的 script 中有效,其他类型的 script 会直接报错。

4. 在 worker 中使用 module

由于 JavaScript 采用的是单线程模型,Web Worker 则为 JavaScript 创造了多线程环境,主线程可以通过创建 Worker 在子线程中执行一些脚本,将一些计算密集型或者高延迟的任务放到后台运行,保证 UI 交互的流畅性。而 module 则可以实现动态 import、对加载和执行实现优化、实现依赖管理。所以在 Worker 中使用 Module 可以更轻松的将一些 heavy work 转移到后台线程。module 现在可以应用于多种不同类型的 Worker 中,比如: WebWorker、ServiceWorker 和 Worklet。

具体的使用方法如下:

// 在 web worker 中的用法 let worker = new Worker(moduleScriptURL,{type:"module"}) // 在 service worker 中的用法 nivagator.serviceWorker.register(scriptURL,{type:"module"}); // 在 worklet 中的用法 var audioContext = new AudioContext(); dusioContext.audioWorklet.addModule(moduleScriptURL);

5. Internationalization API 的更新

【WWDC21 10030】高级 Web 内容开发

今年更新了 5 个国际化的 API, 他们的功能在图片中一目了然了,具体如下:

  • Intl.NumberFormat 设置数字显示格式
  • Intl.DateTimeFormat 根据不同国家设置时间 / 日期的显示格式
  • Intl.Segmenter 根据不同语言的语法规则进行分词
  • Intl.ListFormat 根据不同语言的语法进行连词
  • Intl.DisplayNames 自动根据当前页面设置的语言,展示语言切换内容

其中最值得一提的是 Intl.Segmenter,可以实现语句的分词功能,在做一些算法的时候进行分词是一项基本的工作,在此基础之上可以做很多有趣的功能,更详细的代码参见 demo,感兴趣的同学不妨一试。

WebAssembly

2008 年很多浏览器中开始引入 JITs,实现了 JS 运行速度的骤然提升,而 WebAssembly 被认为可能是 Web 应用性能提升的又一个转折点,funkykarts 就是一个采用 WebAssembly 的例子,其实 funkykarts 的源码是使用 C++ 来实现的,那在 Web 中的这一切又是怎么做到的呢?

【WWDC21 10030】高级 Web 内容开发

WebAssembly 可以理解为一种 web 版的汇编,其实它并不是一种编程语言,但是可为 C/C++/Rust 等高级语言提供一个高效的编译目标,使 Web 应用程序获得和原生 App 相媲美的性能。这就意味着,对于一个现成的 Native 应用,为了将它移植到 web 中,不需要从头开始编写 JavaScript 代码,通过 WebAssembly 将它编译成浏览器支持的 wasm 模块,然后通过 Webassembly API 执行调用即可。这一过程如下图所示:

【WWDC21 10030】高级 Web 内容开发

上图中 Emscripten 是一种生成 wasm 的工具,目前常见的这类工具还包括:

编程语言 Center Aligned
C/C++ Emscripten
Rust wasm-pack
TypeScript AssemblyScript
asm.js Binaryen
Java 字节码 TeaVM

目前 Chrome、FireFox 和 Safari 都已支持 WebAssembly,在具体的功能上还存在些微差异,具体的支持情况可以参考下图。更详细的信息可以在 WebAssembly 官网 找到。其中的第一列 Your browser 指的是我打开网页时使用的 Safari Technology Preview(V14.2)。

【WWDC21 10030】高级 Web 内容开发

从上图可以出今年 Apple 在最新版本的 Safari 上对 WebAssembly 增加了多项功能的支持,具体包括在以下几个方面:

  • 通过采用新的内存指令让批量内存操作具备更好的性能。比如批量的复制和初始化操作。

  • 通过新的指令告诉用户进程在部分情况下无需捕获异常。比如在 float 和 int 之间转换时的正溢出。

  • 新增了符号扩展运算符,实现低位数转高位数,所谓的低位数转高位数的基本原理就是在低位数的左边补上低位数的符号位,直到数字位数达到要求。用来实现 WebAssembly 的 i64 类型和 JavaScript 的 BigInt 数据类型之间的转换,这一改进可以提高代码的执行速度并且比之前的实现方法更加简单。

  • 增加了新的引用类型,允许 WebAssembly 模块持有 JavaScript 和 DOM 对象的引用,并且可以传递和保存它们。

  • 通过数据流式的下载和编译,缩短了整体执行时间。

New Web APIs

在 10030 这个 session 中,还提供了一系列 API 的更新,这部分 API 各自适用于不同的场景,有些功能还是很有意思的,比如 Speech Recogintion 可以借助 Siri 引擎实现实时文本转换,Web Share 功能今年新增了文件共享,而 Storage Access 在保证用户 Cookies 安全性的前提下增加了适用范围。下面分别介绍一下它们:

【WWDC21 10030】高级 Web 内容开发

1. WebGL2.0

WebGL 是实现页面渲染的不二法门,可以帮助开发者在 Web 中实现非常绚丽的画面效果,就像下图这样,Apple 这次在 Safari 和 Webkit 中为我们带来了 WebGL2.0 的支持,下面我们就简单解下什么是 WebGL2.0:

【WWDC21 10030】高级 Web 内容开发

WebGL2.0 是基于 OpenGL ES 3.0 实现的 Web API,核心是 WebGL2RenderingContext 接口,在 WebGL1.0 的基础上增加了很多的新特性,比如:

  • 增加了 3D 纹理,能够渲染出像云朵一样的 volumetric effects (容积效果)。

  • 它的 WebGLSampler 可以用来存储一系列采样参数,在着色器中使用纹理更加灵活。

  • 增加了 Transform Feedback 来帮助在 GPU 上实现高性能的粒子系统效果。

文字描述有点抽象,从效果图中简单感受下可以带给用户的体验吧~

作者:乐鹰神骑俊,iOS开发者,目前从事智能家居设备连接控制方向的工作 :)

审核:折腾范儿_唯敬,iOS/前端 开发者,就职于阿里巴巴,喜欢研究跨平台动态化混合前端相关的内容,目前从事移动应用客户端/前端相关开发工作。

【WWDC21 10030】高级 Web 内容开发

本文基于session 10030 – Develop advanced web content 梳理

引言

Web 应用作为互联网内容的重要组成部分,近些年随着 Web2.0 概念的蓬勃发展和包括 WebAssembly、WebGL2.0 等技术的演进,Web 应用在很多场景下已经具备和原生相媲美的性能,Apple 在过去的一年中为 Web 应用带来了哪些改进,Safari 和 Webkit 又新添了一些怎样有趣又好玩的功能呢,让我们跟随 WWDC21 一起来探索一下吧~

Tips:

  • 本文主要面向使用 JavaScript、WebAssembly、WebGL 的 Web 应用开发者。

  • 本文提及部分特性或 API 在 Safari14.2 以下版本中可能暂未支持,可以使用 Safari Technology Preview – 14.2 调试。

  • 具体 API 的使用和支持情况可以参考 MDN Web Docs ,但文档更新可能会有延迟。

  • 文末有示例代码链接。

本文知识目录:

【WWDC21 10030】高级 Web 内容开发

JavaScript 语法增强

1. 使用 # 修饰类的属性、静态变量、方法,保证它们仅在类的内部可见。

需要注意的是增加 # 后,# 已经是名称的一部分,比如 #_startTime 才是一个完整的变量名。

//class with private variable and function class PrivateStopWatchWithOneButton {   // 使用 # 定义私有变量     #_startTime = 0;    // 使用 # 定义私有静态变量     static #stopWatchCount = 0;      click(){         if (!this.#_startTime) {             this.#start();         }else{             this.#stop();         }     }      // 使用 # 定义私有方法     #start() {         PrivateStopWatchWithOneButton.#stopWatchCount++;         this.#_startTime = Date.now();         console.log('StopWatch started');     } }  function demo(){     var counter = new StopWatchWithOneButton();     counter.click();     counter.#stopWatchCount = 0; //SyntaxError   counter.#start();//SyntaxError }

2. WeakRef 一种新的弱引用方法

Map 和 Set 是 JavaScript 中常用的集合类型,为了实现更高效的垃圾回收,在部分情况下需要通过 WeakMapWeakSet 实现对集合对象的弱引用,但是 WeakMapWeakSet 没有 Iterator 接口,因而无法实现迭代的逻辑。所以 Apple 今年给出了几个新的接口,比如通过 WeakRef 获得对象的弱引用,同时可以通过 FinalizationRegistry 得知弱引用的对象被垃圾回收的时机,然后在注册的回调中执行一些清理操作。

其中关键的几个概念:

WeakRef:允许您保留对另一个对象的弱引用,而不会阻止被弱引用对象被 GC 回收 FinalizationRegistry:可以让你在对象被垃圾回收时请求一个回调。 deref:返回 WeakRef 实例的目标对象,如果目标对象已被垃圾收集,则返回 undefined 。

下面是一段伪代码:

class StopWatchWithOneButton {     _startTime = 0;     click(){     //...   }     //some detail implimentation... }  const allStopWatches  = new Map(); var nextAvailableIdentifier = 1; function removeStopwatch(identifier){   /*   当 map 中引用的 StopWatchWithOneButton 对象由于某种原因 (生命周期结束 / 手动销毁) 被系统回收后,   需要将当前的 Map 数据清理一下。   */     allStopWatches.delete(identifier); }  // 通过 FinalizationRegistry 新建一个注册表,同时注册关联的回调函数 const finalizationRegistry = new FinalizationRegistry(removeStopwatch);  function createStopwatch(){     let identifier = nextAvailableIdentifier++;     let stopwatch = new StopWatchWithOneButton();    //WeakRef()获得 stopwatch 的弱引用     allStopWatches.set(identifier, new WeakRef(stopwatch));   /*    将 stopwatch 注册到 finalizationRegistry 这个注册表中,当 stopwatch 被垃圾回收时,   便会调用上面的 removeStopwatch 函数,实现 allStopWatches 这个 map 数据的清理。   */     finalizationRegistry.register(stopwatch, identifier);      return stopwatch; }  function clickAllStopwatches(){     console.log('ready to click all buttons');   for(let weakStopwatch in allStopWatches.values()){     //迭代获取 weakStopwatch,通过 deref() 判断对象是否被 GC     weakStopwatch.deref()?.click();   } }

但是由于 FinalizationRegistry 的运行依赖于 GC,GC 的运行又依赖于 event loop 机制,所以存在一些不确定性。比如回调时机可能和你预期的不一致,所以在使用之前要评估下你的场景是否适用这几个方法,避免掉到坑里。

3. 采用 await 方式 import Module

await 这个概念出现在了很多的编程语言中,它的最主要特征就是简化异步调用,让代码的可读性极大增强。原来 await 只能在 async 函数中使用,但是现在也可以在 import module 的时候使用,让 module 之间的依赖管理变得更加简单,比如像下面这样:

<!-- wait until module is imported with top-level await--> <script type='module' id='inline-module'>     var stopwatch;     try{         let {StopWatchWithOneButton} = await import('./stopwatchInModule.js');         stopwatch = new StopWatchWithOneButton();     } catch(error){       console.log(error);     } </script>  //Another file stopwatchInModule.js export class StopWatchWithOneButton {     _startTime = 0;     click(){     //...   }     //some detail implimentation... }

上述 await 方法的使用,有以下两个效果:

  • stopwatch = new StopWatchWithOneButton(); 会在 import 执行完成之后再执行。

  • 如果被 import 的 stopwatchInModule.js 中有异步任务执行,stopwatch = new StopWatchWithOneButton(); 会在异步任务执行完成后继续执行。

需要注意的是,await 用来 import module 的时候仅在 module 类型的 script 中有效,其他类型的 script 会直接报错。

4. 在 worker 中使用 module

由于 JavaScript 采用的是单线程模型,Web Worker 则为 JavaScript 创造了多线程环境,主线程可以通过创建 Worker 在子线程中执行一些脚本,将一些计算密集型或者高延迟的任务放到后台运行,保证 UI 交互的流畅性。而 module 则可以实现动态 import、对加载和执行实现优化、实现依赖管理。所以在 Worker 中使用 Module 可以更轻松的将一些 heavy work 转移到后台线程。module 现在可以应用于多种不同类型的 Worker 中,比如: WebWorker、ServiceWorker 和 Worklet。

具体的使用方法如下:

// 在 web worker 中的用法 let worker = new Worker(moduleScriptURL,{type:"module"}) // 在 service worker 中的用法 nivagator.serviceWorker.register(scriptURL,{type:"module"}); // 在 worklet 中的用法 var audioContext = new AudioContext(); dusioContext.audioWorklet.addModule(moduleScriptURL);

5. Internationalization API 的更新

【WWDC21 10030】高级 Web 内容开发

今年更新了 5 个国际化的 API, 他们的功能在图片中一目了然了,具体如下:

  • Intl.NumberFormat 设置数字显示格式
  • Intl.DateTimeFormat 根据不同国家设置时间 / 日期的显示格式
  • Intl.Segmenter 根据不同语言的语法规则进行分词
  • Intl.ListFormat 根据不同语言的语法进行连词
  • Intl.DisplayNames 自动根据当前页面设置的语言,展示语言切换内容

其中最值得一提的是 Intl.Segmenter,可以实现语句的分词功能,在做一些算法的时候进行分词是一项基本的工作,在此基础之上可以做很多有趣的功能,更详细的代码参见 demo,感兴趣的同学不妨一试。

WebAssembly

2008 年很多浏览器中开始引入 JITs,实现了 JS 运行速度的骤然提升,而 WebAssembly 被认为可能是 Web 应用性能提升的又一个转折点,funkykarts 就是一个采用 WebAssembly 的例子,其实 funkykarts 的源码是使用 C++ 来实现的,那在 Web 中的这一切又是怎么做到的呢?

【WWDC21 10030】高级 Web 内容开发

WebAssembly 可以理解为一种 web 版的汇编,其实它并不是一种编程语言,但是可为 C/C++/Rust 等高级语言提供一个高效的编译目标,使 Web 应用程序获得和原生 App 相媲美的性能。这就意味着,对于一个现成的 Native 应用,为了将它移植到 web 中,不需要从头开始编写 JavaScript 代码,通过 WebAssembly 将它编译成浏览器支持的 wasm 模块,然后通过 Webassembly API 执行调用即可。这一过程如下图所示:

【WWDC21 10030】高级 Web 内容开发

上图中 Emscripten 是一种生成 wasm 的工具,目前常见的这类工具还包括:

编程语言 Center Aligned
C/C++ Emscripten
Rust wasm-pack
TypeScript AssemblyScript
asm.js Binaryen
Java 字节码 TeaVM

目前 Chrome、FireFox 和 Safari 都已支持 WebAssembly,在具体的功能上还存在些微差异,具体的支持情况可以参考下图。更详细的信息可以在 WebAssembly 官网 找到。其中的第一列 Your browser 指的是我打开网页时使用的 Safari Technology Preview(V14.2)。

【WWDC21 10030】高级 Web 内容开发

从上图可以出今年 Apple 在最新版本的 Safari 上对 WebAssembly 增加了多项功能的支持,具体包括在以下几个方面:

  • 通过采用新的内存指令让批量内存操作具备更好的性能。比如批量的复制和初始化操作。

  • 通过新的指令告诉用户进程在部分情况下无需捕获异常。比如在 float 和 int 之间转换时的正溢出。

  • 新增了符号扩展运算符,实现低位数转高位数,所谓的低位数转高位数的基本原理就是在低位数的左边补上低位数的符号位,直到数字位数达到要求。用来实现 WebAssembly 的 i64 类型和 JavaScript 的 BigInt 数据类型之间的转换,这一改进可以提高代码的执行速度并且比之前的实现方法更加简单。

  • 增加了新的引用类型,允许 WebAssembly 模块持有 JavaScript 和 DOM 对象的引用,并且可以传递和保存它们。

  • 通过数据流式的下载和编译,缩短了整体执行时间。

New Web APIs

在 10030 这个 session 中,还提供了一系列 API 的更新,这部分 API 各自适用于不同的场景,有些功能还是很有意思的,比如 Speech Recogintion 可以借助 Siri 引擎实现实时文本转换,Web Share 功能今年新增了文件共享,而 Storage Access 在保证用户 Cookies 安全性的前提下增加了适用范围。下面分别介绍一下它们:

【WWDC21 10030】高级 Web 内容开发

1. WebGL2.0

WebGL 是实现页面渲染的不二法门,可以帮助开发者在 Web 中实现非常绚丽的画面效果,就像下图这样,Apple 这次在 Safari 和 Webkit 中为我们带来了 WebGL2.0 的支持,下面我们就简单解下什么是 WebGL2.0:

【WWDC21 10030】高级 Web 内容开发

WebGL2.0 是基于 OpenGL ES 3.0 实现的 Web API,核心是 WebGL2RenderingContext 接口,在 WebGL1.0 的基础上增加了很多的新特性,比如:

  • 增加了 3D 纹理,能够渲染出像云朵一样的 volumetric effects (容积效果)。

  • 它的 WebGLSampler 可以用来存储一系列采样参数,在着色器中使用纹理更加灵活。

  • 增加了 Transform Feedback 来帮助在 GPU 上实现高性能的粒子系统效果。

文字描述有点抽象,从效果图中简单感受下可以带给用户的体验吧~

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 【WWDC21 10030】高级 Web 内容开发求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们