HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

JS 规范又双叒要更新了

  • 2019-06-28
  • 本文字数:9659 字

    阅读完需:约 32 分钟

JS规范又双叒要更新了

JavaScript 目前依旧很受欢迎。如 GitHub 的报告Octoverse中的图表所示,JavaScript 是 GitHub 多年来最常用的语言。此外,Stack Overflow 最近的“2019开发者调查报告”也将 JavaScript 列为最受欢迎的技术。



GitHub 最流行语言的变迁


ECMAScript 2015 和随后的 ECMAScript 规范看起来也被众多开发者顺利接受了。



“2018年JS现状”中的JavaScript偏好


本文将介绍 ECMAScript 2018 的主要功能,以及预计将包含在 ECMAScript 2019 和 2020 规范中的提案。


注明:本文的内容基于截止 2019 年 6 月的已知信息。文章中的内容和事实可能会随时间推移发生变化。

一些改动和新闻

有些改变不会对 JavaScript 的语言层面产生直接影响,但可能会带来间接影响,例如影响环境和生态系统等。

TC39 的变化

TC39 是一个讨论 JavaScript 标准规范的技术委员会,已决定从 2019 年开始改变其运营结构。TC39 每年召开六次会议,规模已经发展到每次有 40 到 60 人参会的程度。


这个委员会以前是主席和副主席的运营结构,现在改为由三位联合主席(Aki Braun(PayPal)、Brian Terlson(微软)和 Yulia Startsev(Mozilla))共同负责的架构。他们还在 2019 年 3 月开设了官方网站


在 TC39 联合主席 Aki Braun 撰写的文章“TC39 的一年(多)历程”中介绍了 TC39 会议的进展和成果。


2018 年 7 月初,npm 加入了ECMA InternationalTC39

SharedArrayBuffer

Meltdown和Spectre安全漏洞影响,浏览器厂商已更改其默认设置,禁用了自 2018 年 1 月 5 日起使用的SharedArrayBuffer对象


除 Chrome 之外,其他浏览器依旧保持着这种设置。Chrome 67 版之后通过站点隔离重新激活了该对象(参阅https://bugs.chromium.org/p/chromium/issues/detail?id=821270)。

微软 Edge 改用 chromium 引擎

2018 年 12 月 6 日,微软宣布将其 Edge 浏览器转向 Chromium 引擎(参阅“微软Edge,通过开源协作让Web受益”,震惊业界。


在 2019 年 1 月 29 日举行的 TC39 会议期间,场下微软问答环节针对 Edge 的引擎转换披露了以下事实:


  • 没有开源旧引擎的计划。

  • 现有 JavaScript 引擎ChakraCore将继续更新,但没有长期更新计划。


ChakraCore 团队成员 Limin Zhu 评论说:除了浏览器,还有很多项目在使用 ChakraCore。因此尽管 Edge 改变了方向,我们的团队仍将继续支持 ChakraCore(参阅“微软Edge向Chromium迁移以及ChakraCore的未来”)。


可以从微软 Edge 内部通道站点下载基于 chromium 的 Edge(Canary/Dev/Beta 版本)。


微软将 Edge 转向 Chromium 引擎的目的和未来计划可参阅这篇文章“微软Edge与开源Chromium:我们的意图”


从开发者的角度来看,微软 Edge 的这种转变可以减轻跨浏览器开发的负担和困难。


但是从 Web 生态系统的角度来看,此举可能会带来令人担忧的结果。因为这会减少浏览器的多样性。


你可能还记得 Internet Explorer 处于垄断地位的时代,当时许多网站只支持 Internet Explorer;类似地,基于 chromium 的浏览器越来越多也不是什么好事情。


有关多样性的担忧,请参阅文章“Chrome正在变成新的Internet Explorer 6“和 Mozilla 的“再见,EdgeHTML”

模块支持

ECMAScript 2015 引入了模块支持,现在模块作为基本功能已经广泛应用。


接下来看看动态 import()语法和原生模块支持的概况与当前状态,进一步扩展模块的应用范围。

动态 import()

基于Promise的import()语法可以动态加载模块。之前该提案在第 3 阶段停留了一阵儿,但最终于 6 月 6 日达到“第4阶段”并进入 ECMAScript 2020 规范。



import("./myModule.mjs")      .then(module => {        ...    });// using async/await(async () => {    const module = await import("./myModule.mjs");    ...})();
复制代码


Firefox 从 60 版开始可以设置 javascript.options.dynamicImport 标志(flag)来使用 import()语法,Firefox 67 开始默认启用该设置。


微软 Edge(旧引擎版本)尚不支持 import()语法,但是基于 chrome 的 Edge 发布时可能会提供支持。

原生模块加载

从 2018 年 5 月发布的 Firefox 60 开始,Firefox 可以无需标志就使用原生模块(ESM)(参阅文章“Firefox 60——模块和其他更新”)。2017 年 9 月发布的 Node.js 8.5.0 实验性地支持 ESM。


Node.js 中的 ESM 需要–experimental-modules 标志,如下例所示。在这)情况下,CommonJS 的’request()'将被禁用以加载模块。


node --experimental-modules my-app.mjs
复制代码


Node.js 基金会为提供 ESM 的官方支持组建了“模块团队”。模块团队的工作分为 4 个阶段:


  • 阶段 0:从当前 Node 分支,但删除了 Node 8.5.0 之后版本中的大部分–experimental-modules 实现。

  • 阶段 1:添加“最小内核”,凡是工作组认为会在新的 ES 模块实现中出现的模块都会包含进去。

  • 阶段 2:在实现中加入足够多的功能,这些功能应该对主流用户有益,从而构建出最小可行产品。

  • 阶段 3:改善用户体验并扩展 MVP。


这项工作目前正处于第3阶段

ECMAScript 2018

ECMAScript 2018于 2018 年 6 月宣布。

异步迭代器

异步运算符枚举异步流数据,其操作类似于典型的运算符,并使用语法形式 for — await — of。异步运算符和普通运算符之间的区别在于前者返回的是 Promise 对象。


async function test() {      // Regular Iterator    for (const i of list) ...// Async Iterator    for await (const i of asyncList) ...}
复制代码


处理异步调用流时可以创建异步运算符工厂。


// example from: https://jakearchibald.com/2017/async-iterators-and-generators/async function* asyncRandomNumbers() {    const url = "https://www.random.org/integers/?num=1&min=1&max=100&col=1&base=10&format=plain&rnd=new";while (true) {        const response = await fetch(url);        const text = await response.text();        yield Number(text);    }}(async function() {    let i = 0;for await (const number of asyncRandomNumbers()) {        console.log(++i, "=>", number);        if (i === 10) break;    }})();// 1 "=>" 65// 2 "=>" 62// ...
复制代码

对象 Rest/Spread 属性

与 ECMAScript 2015 中的 Rest 参数和 Spread 运算符规范一样,此提案引入了对象字面量(literal)的对象解析分配和传播属性。


// Rest propertylet { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };  x; // 1  y; // 2  z; // { a: 3, b: 4 }// Spread propertylet n = { x, y, ...z };  n; // { x: 1, y: 2, a: 3, b: 4 }
复制代码

删除模板字面量语法限制

模板字面量删除了对转义序列使用的限制。


标记模板字面量是接收模板并返回修改后的字符串的函数。传递给函数的字符串可以是以下类型之一:


  • Cooked:转义序列已被解释。

  • Raw:转义序列是普通文本。模板字符串中的非解释值由 String.raw()方法处理。


function tagFunc(str, substs) {      return str;}const result = tagFunc`\u{4B}`;  result;  // ["K"]  result.raw; // ["\u{4B}"]
复制代码


以前,如果模板在反斜杠后有一些字符序列会被视为非法,并且不返回原始字符串。


  • \u:Unicode(例如\u004B)

  • \x:十六进制(例如\x4B)

  • \positive:八进制(例如\141)


ECMAScript 2018 移除了与转义序列相关的所有语法限制,并以原始形式返回字符串。在这种情况下,解释的值返回 undefined。


const result = tagFunc`\131`;  result;  // [undefined]  result.raw; // ["\131"]
复制代码


查看http://2ality.com/2016/09/template-literal-revision.html了解有关模板字面量的问题和解决方案的更多信息。

Promise.prototype.finally

与 try…catch 语句的 finally 语法一样,此提案引入了对 Promise 对象的类似用法。


finally 语法是在最后无条件执行的代码块,与 Promise 对象的处理状态(‘resolve’或’reject’)无关。调用 Promise 对象后,无论结果如何都将执行此代码块。


let isLoading = true;fetch("https://www.random.org/integers/?num=1&min=1&max=100&col=1&base=10&format=plain&rnd=new")  .then(function(res) {    if(res) {        return res.text();    }throw new TypeError("Error");}).then(function(text) { /* Success */ }).catch(function(error) { /* Error */ }).finally(function() {    // will be performed regardless success or error    isLoading = false;});
复制代码


查看MDN的Promise.prototype.finally文档了解更多信息。

正则表达式

新增了几个正则表达式提案。


  • 正则表达式的 s 标志。点(.)能匹配所有字符,但\r 和\n 是例外。为了解决这个问题引入了新的 s 标志。


// previous/./test("a");  // true/./.test("\n");  // false// dotAll flag/./s.test("\n");  // true
复制代码


  • RegEx 命名捕获组。它可以命名一个捕获组。(?<name>pattern)将添加到捕获组模式,然后使用该名称作为捕获的引用。


const rx = /(?<year>[0-9]{4})-(?<month>[0-9]{2})/;  const match = rx.exec('2018-03');  match.groups.year; // 2018  match.groups.month; // 03
复制代码


  • RegExp Lookbehind 断言。在正则表达式中,一个模式的值由字符串跟随(先行)或不跟随(负向先行)。相比之下,这个提案提供了寻找特定模式以前进(后行)或不前进(负向后行)的能力。


// positive lookahead/aa(?=bb)/.test("aabb"); // true// negative lookahead/aa(?!bb)/.test("aac");  // true// positive lookbehind/(?<=aa)bb/.test("aabb");  // true// negative lookbehind/(?<!=aa)bb/.test("bbbb");  // true
复制代码


  • RegEx Unicode 属性转义。Unicode 属性转义是在设置了 u 标志的正则表达式中新增的可用转义序列类型。


/^\p{White_Space}+$/u.test('\t \n\r');  // true /^\p{Script=Greek}+$/u.test('μετά');  // true
复制代码

ECMAScript 2019

ECMAScript 2019尚处于候选草案状态。根据之前版本的发布日期推算,2019 最终版本预计将在 2019 年 6 月左右公布。

Array.prototype.flat()/ Array.prototype.flatMap()

Array.prototype.flat()方法和 Array.prototype.flatMap()方法以递归方式查找指定深度的子数组元素,并创建一个连接到其中的新数组。


// Array.prototype.flat[1, 2, [3, 4]].flat();  // [1, 2, 3, 4][1, 2, [3, 4, [5, 6]]].flat(1);  // [1, 2, 3, 4, [5, 6]]// Array.prototype.flatMap[1, 2, 3, 4].map(x => [x * 2]);  // [[2], [4], [6], [8]][1, 2, 3, 4].flatMap(x => [x * 2]);  // [2, 4, 6, 8]
复制代码


关于**.flat()**命名的小故事:

最初使用的名称是“.flatten()”。但是,MoTools(一个应用广泛的遗留库)有一个类似的名称“array.prototype.flatten()”,提供了类似的功能。如果继续使用“.flatten()”,可能会在使用 MoTools 的网站上出问题。

为了避免潜在的冲突,.flatten()被改名为.flat()。此外“.smoosh()“也是候选之一;还有人建议改变 ECMAScript 2019 中 MoTools 的 flatten()行为(参阅https://github.com/mootools/mootools-core/issues/2797)。但这可能让许多不再更新的网站崩溃,Tom Dale 的推文指出了这一点(他参与了 Ember 和 SproutCore 的开发)。



https://twitter.com/tomdale/status/971288054966247430

Object.fromEntries()

Object.fromEntries()将键值对列表转换为对象。


const entries = new Map([      ['foo', 'bar'],    ['baz', 42]]);Object.fromEntries(entries);  // { foo: "bar", baz: 42 }
复制代码

String.prototype.trimStart()/ .trimEnd()

删除字符串开头的空格(.trimLeft())或删除字符串末尾的空格(.trimRight())。


const greeting = "   Hello world!   ";greeting.trimStart();  // "Hello world!   "  greeting.trimEnd();  // "   Hello world!"
复制代码

Symbol.prototype.description 属性

Symbol.prototype.description 属性返回 Symbol 对象的可选只读描述。


// will return 'Test Description'Symbol("Test Description").description;
复制代码

可选的 catch 绑定

可选的[catch 绑定提案]((https://github.com/tc39/proposal-optional-catch-binding)是说,如果 try…catch 语句中的 catch 语法中未使用参数,则允许省略参数。


// Traditional waytry { ··· } catch(e) { ··· }// Optional catch binding// if don't need the use of parameter, it can be omittedtry { ··· } catch { ··· }
复制代码

Array.prototype.sort()稳定性

当对具有 10 个以上元素的数组排序时,Array.prototype.sort()方法使用了不稳定的快速排序算法。为了确保数组正确对齐,ECMAScript 2019 对 Array.prototype.short()使用了 Timsort 算法。


此规范目前适用于所有 JavaScript 引擎。但基于 ChakraCore 的微软 Edge 对包含超过 512 个元素的数组会出现排序错误。


下面的截图显示了 Edge 和 Firefox 上的稳定性测试结果。如图所示,Edge 出错了。



稳定性测试结果:(左)Edge 17.17134/(右)Firefox 66.0.2


更详细的讨论参阅:https://docs.google.com/presentation/d/1mHvxDciqsAchhjepMZlU5fn1DBvglCXSjDWUEtsPGvI/edit#slide=id.g41da6c5107_0_0

格式良好的 JSON.stringify

RFC 8259指定要编码为 UTF-8 格式的 JSON 文本用于 JSON 对象数据交换。但是当使用 JSON.stringify()时,一些 UTF-16 代码(从 0xD800 到 0xDFFFF 的字符被归类为“代理”)不会编码为 UTF-8。


ECMAScript 2019 会返回一个转义序列,而不是返回一个无效的、Unicode 字符串,如下图所示(Edge)。



Edge 和 Firefox 上的 JSON.stringify()结果


更多详细信息请查看提案文档

包含 JSON

ECMAScript 声明 JSON 是 JSON.parse 的一个子集,但事实并非如此,因为 JSON 字符串可以包含未转义的 U+2028 LINE SEPARATOR 和 U+2029 PARAGRAPH SEPARATOR 字符。


该提案建议扩展 ECMA-262,允许这些字符不将 JSON 分解为 ECMAScript 的子集。


// if ECMA is superset of JSON, these must be trueeval('"\u2028"') === "\u2028"  // true  eval('"\u2029"') === "\u2029"  // true
复制代码


详细信息请查看提案文档

Function.prototype.toString 修订

根据 ECMAScript 2016 中的定义,Function.prototype.toString()的结果可能因引擎而异。ECMAScript 2019 确保返回定义的原始代码(参阅https://tc39.es/Function-prototype-toString-revision/)。


返回函数中定义的代码时,ECMAScript 2019 使用以下算法返回函数中定义的代码字符串:


  • 换行符:\r\n(Windows)或\n(macOS)都以 Unix 样式返回\n。

  • 内置函数:未通过 ECMAScript 定义的所有代码(主要是内置函数)将作为[native code]返回。


isNaN.toString();  // "function isNaN() { [native code] }"
复制代码



不同浏览器中“isNaN.toString()”的结果:


  • 通过 Function 和 GeneratorFunction 动态创建的函数:引擎必须创建适当的源代码并将其附加到函数上。

  • 其他情况下:抛出 TypeError。


更多详细信息查看http://2ality.com/2016/08/function-prototype-tostring.html

ECMAScript 2020

截至 2019 年 3 月 1 日,TC39 repo master 分支已升级为 ECMAScript 2020(参阅提交日志)。


此时,ECMAScript 2020 中已完成的提案(阶段 4)只有 String.prototype.matchAll()和 import(),但将来完成提案的列表会加入更多项目。


String.prototype.matchAll()方法与 String.prototype.match()的工作方式类似。前者与 g(global)/y(sticky)标志一起使用时,返回包含匹配字符串和匹配详细信息的迭代器。


const str = "test1test2";  const rx = /t(e)(st(\d?))/g;str.match(rx);  // ["test1", "test2"]for (const match of str.matchAll(rx)) {      // 1: ["test1", "e", "st1", "1", index: 0, input: "test1test2"]    // 2: ["test2", "e", "st2", "2", index: 5, input: "test1test2"]    match;}
复制代码

一些新的或未完成的提案

下面来看一些尚未进入最后阶段的有趣提案。

globalThis

通常,访问顶级对象要通过浏览器环境中的“window”对象。


作为执行环境的扩展,新提案中访问顶级对象的方式也发生了变化。


  • 在 Node.js 环境中,通过“global”对象访问顶级对象。

  • HTML5 规范有“Window”和“WindowProxy”,而 ECMAScript 2015 规范中这两个对象都能用来访问顶级对象。


查看https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Inner_and_outer_windows了解 Window 和 WindowProxy 对象的差异。


以下代码是在所有环境下获取顶级对象(“global”)引用的最简单方法。但是这种方法会导致 Chrome 应用中的内容安全政策(CSP)违规。(参阅https://github.com/paulmillr/es6-shim/issues/301)。


var global = Function('return this')();
复制代码


知名的 ES6 兼容 shim 库——ES6 shim,使用下面的函数来获取全局对象,这是目前常用且最好的方法。


// https://github.com/paulmillr/es6-shim/blob/003ee5d15ec1b05ae2ad5ddad3c02fcf8c266e2c/es6-shim.js#L176var getGlobal = function () {      /* global self, window, global */    // the only reliable means to get the global object is    // `Function('return this')()`    // However, this causes CSP violations in Chrome apps.    if (typeof self !== 'undefined') { return self; }    if (typeof window !== 'undefined') { return window; }    if (typeof global !== 'undefined') { return global; }    throw new Error('unable to locate global object');};
复制代码


新提案“globalThis”提供了访问顶级对象的方法,摆脱了与环境的关联性。该提案目前处于第 3 阶段,尚未最终确定。但在 Chrome 71 和 Firefox 65 以及 Node.js 12 中,globalThis 对象可以按如下方式使用:


globalThis.setTimeout;  // window.setTimeout
复制代码


关于“globalThis”这个名字:

与“Array.prototype.flat()”案例类似,这个提案一开始命名为“global”。但是使用这个名称会让 flickr.com 崩溃(https://github.com/tc39/proposal-global/issues/20),所以就改为“globalThis”了。

类字段声明

Babel 7.1.0(2018 年 9 月 17 日发布)版本开始可以使用类字段声明。但这个提案尚未达到最后阶段,此时仍处于“第 3 阶段”。


该提案以更直观,更简单的方式为类变量引入了声明性语法。


初始化(Initialization):通过构造函数初始化实例变量。


class MyClass {      constructor() {        this.x = 1;        this.y = 2;    }}
复制代码


例变量可以使用类字段定义为以下代码的//Initializer 部分,初始化区域在构造函数运行之前运行。


class MyClass {      // Initializer    x = 1;    y = 2;    log = console.log("Initializer");    constructor() {        console.log("Constructor:", this.x, this.y);    }}new MyClass();  // Initializer// Constructor: 1 2
复制代码


私有声明(private declaration):以前 JavaScript 没有提供声明“private”的方式,许多开发者使用下划线(“_”)前缀作为约定。但这并不能真正实现私有化(不过的确有一种方法让变量或方法私有化运行)。


function MyClass() {      this._x = 1;    this._y = 2;}MyClass.prototype.getX = function() {      return this._x;}
复制代码


私有声明器使用数字符号(#)作为前缀来明确声明它是私有的。以“#”开头的变量或方法只能在类块中访问。


class MyClass {      #foo; // private field    constructor(foo) {        this.#foo = foo;    }    incFoo() {        this.#foo++;    }}
复制代码


声明和访问:以下是以各种形式的声明和访问类字段的简单示例。


class MyClass {      A = 1;  // (a) instance field    static B = 2;  // (b) static class field    #C = 3;  // (c) private field    getPrivate() {        return this.#C;    }}new MyClass().A;  // 1MyClass.B;  // 2new MyClass().getPrivate();  // 3
复制代码


更多详细信息请查看http://2ality.com/2017/07/class-fields.html

内置模块

内置模块规范现在处于“第 1 阶段”,与 ESM 一样。与通常 ESM 的不同之处在于它们是“内置的”,并随浏览器本身一起分发。


内置模块不直接对全局暴露。它们仅通过导入语法可用。如果浏览器支持内置模块,则使用“std:”前缀+模块名称导入这些模块,如下所示。此示例中加载的是KV Storage模块


import {storage, StorageArea} from "std:kv-storage";
复制代码


KV Storage 模块和导入映射提案与内置模块规范密切相关。它们俩不属于 ECMAScript 规范,而属于 WICG(Web Incubator 社区组)。


KV Storage 模块:Chrome 74 增加了第一个内置模块 KV Storage。KV Storage 解决了 localStorage 的性能问题,并继承了简单 API 的优势。


  • 在 Chrome 74 中,可以使用 chrome://flags/#enable-experimental-web-platform-features 标志启用 KV Storage。

  • 请参阅“内置模块演示”页面中的 KV Storage演示


KV Storage 具有与 Map 对象类似的 API。字符串和可序列化数据类型可用作键值。它返回一个 Promise 或 Async 迭代器,它们会被异步处理。


两个命名导出分别是“storage”和“StorageArea”。


  • storage:StorageArea 类的实例,名称为 default(默认存储数据库为“kv-storage:default”)。

  • StorageArea:适用于需要额外隔离的情况(例如,存储数据并希望避免与通过默认的 storage 实例存储的数据冲突的第三方库)。StorageArea 数据存储在名为 kv-storage:$ {name}的 IndexedDB 数据库中,其中名称是 StorageArea 实例的名称。


import {storage} from "std:kv-storage";const main = async () => {    const oldPreferences = await storage.get("preferences");  document.querySelector("form")    .addEventListener("submit", async () => {       const newPreferences = Object.assign({}, oldPreferences, {         // Updated preferences go here...       });       await storage.set("preferences", newPreferences);  });};main();
复制代码


导入映射:导入映射提案允许控制 JavaScript import 语句和 import()表达式获取的 URL,并允许在非导入上下文中复用此映射。


导入映射为内置模块提供 Polyfill 和回落,使它们能够将当前不可用的模块标识符映射到 URL 上(参阅https://docs.google.com/document/d/1vFQzbmxg9ilpg8CT_P8roEYcpTfZ06Q5N4J9-ZQqqZo/edit)。


例如,内置模块 KV Storage 目前仅在 Chrome 中可用。在支持的浏览器中不会出现加载问题,但对于没有提供支持的浏览器来说,就需要加载 KV Storage 的 polyfill 了。


以下示例介绍了导入映射的用法。定义模块的映射并使用 import 语句的关键 URL 值。


在没有提供支持的浏览器中,导入 URL 被识别后作为普通导入 URL 处理。如果浏览器提供了支持,它们将根据映射信息流动。


<!-- The import map is inlined into your page -->  <script type="importmap">  {  "imports": {    "/path/to/kv-storage-polyfill.mjs": [       "std:kv-storage",  // if has native support       "/path/to/kv-storage-polyfill.mjs" // otherwise load polyfill    ]  }}</script><!-- Then any module scripts with import statements use the above map -->  <script type="module">    import {storage} from '/path/to/kv-storage-polyfill.mjs';// Use `storage` ...</script>
复制代码

结语

JavaScript 仍在不断变化。事实证明它之所以成为多年来最流行的语言是有道理的。浏览器和 Node.js 对新版 ECMAScript 版本的支持也愈加完善,甚至会提前支持一些尚未完成的提案。



在这种透明而强大的标准化流程帮助下,不断进化的 JavaScript 成为了可靠而强大的语言。


前路漫漫,我们携手共进吧!


英文原文:https://medium.com/@alberto.park/status-of-javascript-ecmascript-2019-beyond-5efca6a2d233


2019-06-28 19:415722

评论

发布
暂无评论
发现更多内容

GitHub下载量从19暴涨到5W,这份架构师学习路线只用了一晚

程序员万金游

学习资料 #java #编程 #程序员 #学习

9月《中国数据库行业分析报告》已发布,47页干货带你详览 MySQL 崛起之路!

墨天轮

MySQL 数据库 oceanbase 国产数据库 StoneDB

动力电池电芯正负极缺陷检测

矩视智能

深度学习 机器视觉

软件测试/测试开发丨ChatGPT自动生成基于PO的数据驱动测试框架

测试人

Python 人工智能 软件测试 数据驱动 ChatGPT

文心一言 VS 讯飞星火 VS chatgpt (110)-- 算法导论10.2 1题

福大大架构师每日一题

福大大架构师每日一题

用友BIP商业网络-银企联助力新钢联集团结算效率高效提升

用友BIP

银企联

Spring扩展-BeanFactoryPostProcessor

OpenHarmony Meetup深圳站招募令

OpenHarmony开发者

软件开发项目管理体系,支撑体系,测试体系文档大全

金陵老街

“套壳”OpenAI,注定消亡!全球首个 20 万字大模型发布丨 RTE 开发者日报 Vol.63

声网

人工智能 RTE 实时互动

Infuse for Mac(音视频播放器) 7.6.1完整激活版

mac

苹果mac Windows软件 Infuse 多媒体播放软件

专家观点∣小议事项会计兼评用友事项会计中台产品

用友BIP

事项会计 冶金

2.0版本佛萨奇系统开发(源码搭建)

V\TG【ch3nguang】

技术干货:解密最受欢迎的开源 Serverless 框架弹性技术实现

阿里巴巴云原生

阿里云 开源 Serverless 云原生

新华网专访樊冠军:让YonGPT成为企业服务领域的高智商、全能型选手

用友BIP

2023全球商业创新大会

Java-WebSocket vs Netty-WebSocket 资源占用

FunTester

如何使用CSS和JavaScript实施暗模式?

互联网工科生

CSS JavaScript 暗模式

IDO官网预售 设置您的IDO:开始您的IDO开发之旅

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 IDO代币预售

济源钢铁∣数智化转型实现超越周期的增长

用友BIP

智能制造

Spring扩展-Aware

玩转HarmonyOS专项测试,轻松上架“五星”高品质应用

HarmonyOS开发者

【问题记录】Nginx使用域名作为upstream时,需要配置SNI

陈德伟

nginx 虚拟主机 proxy_pass SNI

智慧地球质押挖矿系统开发详情

l8l259l3365

Mac电脑视频处理软件 VideoProc Converter 4K直装中文版

胖墩儿不胖y

Mac软件 视频处理工具 视频工具

CHM文件阅读器 CHM Viewer Star 免激活最新版

mac大玩家j

Mac软件 文件阅读器 文件管理软件

为什么都在说实时数据传输?

RestCloud

ETL 实时数据 CDC

设计行业中如何保证图纸设计稿在数据传输中不会泄密

镭速

数据传输 文件传输

关于企业如何替换FTP和加速FTP的问题

镭速

替换FTP 加速FTP

JS规范又双叒要更新了_语言 & 开发_Jae Sung Park_InfoQ精选文章