您当前所在位置: > 网游 > 网游百科

前端主流的 Javascript,缺失了哪些技能?

时间:2019-06-18 16:07:43  来源:  作者:网络

原标题:前端主流的 Javascript,缺失了哪些技能?

最近这几年,Java 的使用规模有了很大的增长。在这篇博文里,本文作者将和大家探讨现在 Java 还缺少的内容。

作者 | Axel Rauschmayer

译者 | 彼得

责编 | 屠敏

出品 | CSDN(ID:CSDNNews)

以下为译文:

注:

  1. 我将只列出我自己认为最重要的功能缺失。虽然现在的 Java 还有很多有用的功能没有实现,但本文中,我不想罗列太多。
  2. 我的选择是很主观的。
  3. 几乎所有在本博客中提到的内容都在TC39的候选列表中。也就是说,您也可以将本博文作为未来Java内容的预览。

有关前两个问题的更多想法,请参阅语言设计部分(http://2ality.com/2019/01/future-js.html#language-design)。

数值

根据数值来比较对象

现在,Java 只是对元数据类型(比如,字符串)才使用数值进行比较。也就是对这些元数据类型,根据它们包含的内容进行比较:

> 'abc'=== 'abc'

true

在对象之间,是根据对象的引用进行比较的。即任何一个对象只能和它自己相同:

> {x: 1, y: 4} === {x: 1, y: 4}

false

如果我们能够创建可以通过数值进行比较的对象,这会将非常有帮助:

> #{x: 1, y: 4} === #{x: 1, y: 4}

true

另一个方法是引入一种新的类来表示(具体细节待定):

@[ValueType]

classPoint{

// ···

}

注:这种方法是通过修饰符来说明该类是基于数值来进行比较的类。该方法是根据这个建议草案提出的(https://github.com/littledan/proposal-reserved-decorator-like-syntax)。

将对象放入数据结构中

由于对象是按引用进行比较的,因此像下面这样将它们放入ECMA的数据结构(如Map)中是没有什么实际意义:

constm = newMap();

m. set({x: 1, y: 4}, 1);

m. set({x: 1, y: 4}, 2);

assert.equal(m.size, 2);

这个问题可以通过自定义值的类型来解决,也可以通过自定义Set元素和Map键值的管理方法来实现。例如:

  • 通过哈希表定义的Map:这需要一个检查元素是否相等的方法,同时也需要一个创建哈希代码的方法。当你使用哈希代码的时候,需要对象保持不变。否则,就很容易破坏数据结构。
  • 通过排序树定义的 Map:这需要一个检查元素是否相等的方法,以便管理 Map 中存储的值。

大整数(BigInt)

Java 中的 Number 类型都是 64 位(双精度)的。对于整数来说,有53位来表示整数的数值还有1位的符号位来表示正负。也就是,只能精确表示53位以内的整数,对于超出53位的整数,没有办法精确区分它们:

> 2 ** 53

9007199254740992

> (2 ** 53) + 1 // can’t be represented

9007199254740992

> (2 ** 53) + 2

9007199254740994

在某些情况下,这是一个很大的限制。现在,有一个对于大整数(BigInt)的建议。根据该建议,整数的精度可以根据需要进行扩展:

> 2n ** 53n

9007199254740992n

> (2n ** 53n) + 1n

9007199254740993n

大整数(BigInt)也支持类型转换,这样就可以得到固定位数的整数:

constint64a = BigInt.asUintN( 64, 12345n);

constint64b = BigInt.asUintN( 64, 67890n);

constresult = BigInt.asUintN( 64, int64a * int64b);

十进制运算

基于 IEEE 754 的规范,Java 中的 Number 类型都是64位(双精度)的。因为这些数是以二进制来表示,所以在进行小数运算的时候,你不可避免地会遇到四舍五入的问题:

> 0 .1+ 0 .2

0 .30000000000000004

在科学计算和金融领域,这是一个比较突出的问题。现在,有一个正处在初始阶段的关于10进制数值的表示方法的提议。如果该提议获得通过,数值可能会以如下方式表示,请注意在小数后面的m用于表示十进制数值:

> 0 .1m+ 0 .2m

0 .3m

数值分类

现在,在 java 中,对数值进行分类是一件非常麻烦的事:

  • 首先,你需要决定是否使用 typeof 或 instanceof 方法。
  • 其次, typeof 方法有一个众所周知的奇特实现,它认为空值 null 是对象(object)。我个人认为它把函数(function)归结为对象(object)也是比较奇特的。

> typeofnull

'object'

> typeoffunction() {}

'function'

> typeof[]

'object'

  • 第三,instanceof 方法对于其它领域的对象(如 frame 对象)不能正常工作。

对于上述的这些问题,可以通过创建特定的 Java 库来解决。以后,如果有时间,我自己会试着实现。

函数式编程

更多的表达式

和 C 语言风格类似的编程语言都对于表达式和程序语句做了明确的区分:

// Conditional expression

letstr1 = someBool ? 'yes': 'no';

// Conditional statement

letstr2;

if(someBool) {

str2 = 'yes';

} else{

str2 = 'no';

}

在函数式语言中,任何对象都是表达式。使用表达式将使你能在任何表达式的上下文中使用表达式:

letstr3 = do{

if(someBool) {

'yes'

} else{

'no'

}

};

以下的代码是一个更实际的例子。如果没有 do 的表达式,为了避免作用域内的变量 result,就需要立即调用 arrow 函数来实现:

constfunc = (() =>{

letresult; // cache

return()=>{

if(result === undefined) {

result = someComputation();

}

returnresult;

}

})();

有了 do 表达式,你的代码会更简洁:

constfunc = do{

letresult;

()=>{

if(result === undefined) {

result = someComputation();

}

returnresult;

};

};

匹配:析构 switch

在 Java 中,直接处理对象是件很容易的事。但是,它没有基于对象结构的切换方法。在建议中提供的事例如下:

constresource = awaitfetch(jsonService);

case(resource) {

when { status: 200, headers: { 'Content-Length': s}} -> {

console.log( `size is ${s}`);

}

when { status: 404} -> {

console.log( 'JSON not found');

}

when {status} if(status >= 400) -> {

thrownewRequestError(res);

}

}

如上可见,新的 case 语句在某些方面类似于 switch 语句,但使用析构函数来处理 case 命令。在使用嵌套数据结构时(例如在编译器中),这种功能都很有用。模式匹配方案现在处于第一阶段。

管道(Pipeline)操作

对于管道(pipeline)操作,有两个互相竞争的提案。现在,我们先看一下"智能管道"提案;另外一个提案是"F# 管道"。

管道(pipeline)操作的基本思想可以用下面的递归调用来说明:

consty = h(g(f(x)));

但是,管道的概念没有反映出来我们思考的逻辑顺序。我们可以把我们对于上面公式的思考逻辑归纳为下面几步:

  • 以变量X开始;
  • 调用函数F()处理变量X;
  • 对于前面的结果调用函数G()来处理;
  • 对于前面的结果调用函数H()来处理;
  • 把计算结果赋值给变量Y。

使用管道操作,可以使我们更好地描述我们的思考逻辑:

consty = x |> f |> g |> h;

换而言之,下面两个表达式是一样的:

f(123)

123 |> f

另外,管道操作还支持部分应用的功能。该功能类似于 .bind()函 数,下面两个表达式是一样的:

123|> f( #)

123|> (x => f(x))

管道操作的一个重要优势在于你可以像使用方法一样使用函数,而不用进行类型转换:

import{ map} from 'array-tools';

constresult = arr |> map(#, x => x * 2);

我们拿一个稍微长一点的例子来总结一下。这个例子来自于提议草案并稍作改动:

promise

|> await#

|> # || throw new TypeError(

`Invalid valuefrom${promise}`)

|> capitalize // function call

|> # + '!'

|> newUser.Message( #)

|> awaitstream.write( #)

|> console.log // method call

;

并发

Java 对于并发的支持一直比较有限。进程并发事实上的标准是 Worker API,它在 Web 浏览器和 node.js 中可用(在 v11.7 及更高版本中没有标志)。

在 Node.js 中,对于 Worker API 可以像下面这样使用:

const{

Worker, isMainThread, parentPort, workerData

} = require( 'worker_threads');

if(isMainThread) {

constworker = newWorker(__filename, {

workerData: 'the-data.json'

});

worker.on( 'message', result => console.log(result));

worker.on( 'error', err => console.error(err));

worker.on( 'exit', code => {

if(code !== 0) {

console.error( 'ERROR: '+ code);

}

});

} else{

const{readFileSync} = require( 'fs');

constfileName = workerData;

consttext = readFileSync(fileName, { encoding: 'utf8'});

constjson = JSON.parse(text);

parentPort.postMessage(json);

}

相对来讲,Worker 的方式是比较重量级的实现。每一种都需要有自己的领域(全局变量等)。我希望在将来能看到一个更量级的实现。

标准库

现在,Java 明显落后于其他语言的一个方面是它的标准库支持。最小的标准库支持确实有合理的一面,因为它们依赖的外部库会很快地发展和变化。但是,还是有一些非常有用的核心功能需要实现。

用模块替代命名空间(namespace)对象

Java 的标准库是在它支持模块之前创建的。因此,很多方法是被放在命名空间对象(例如 Object,Reflect,Math和JSON)中的:

  • Object.keys()
  • Reflect.ownKeys()
  • Math.sign()
  • JSON.parse()

如果能把这些方法放到特定的模块中,那就更好了。必须通过特殊的 URL 才能使用它们。比如可以使用 std 前缀:

// Old:

assert.deepEqual(

Object.keys({a: 1, b: 2}),

[ 'a', 'b']);

// New:

import{keys} from 'std:object';

assert.deepEqual(

keys({a: 1, b: 2}),

[ 'a', 'b']);

使用这种方法的好处是:

  • Java 将会变得更加模块化(这可以加快启动时间并减少内存消耗)。
  • 调用导入的函数比调用存储在对象中的函数速度更快。

支持 iterables(同步和异步)的工具函数(Helper)

iterables 能提供很多便利,包括只有在需要的时候才计算数值和支持许多数据源。但是,目前 Java 对 iterables 提供的工具函数却很少。比如,现在如果你要筛选、映射或减少 iterable,则只能将它转换为数组:

constiterable = newSet([ -1, 0, -2, 3]);

constfilteredArray = [...iterable].filter( x=>x >= 0);

assert.deepEqual(filteredArray, [ 0, 3]);

如果 Java 能有对 iterables 支持的工具函数,你就可以直接过滤 iterables:

constfilteredIterable = filter(iterable, x => x >= 0);

assert.deepEqual(

// We only convert the iterable to an Array, so we can

// check what’s in it:

[...filteredIterable], [ 0, 3]);

下面是更多可能的 iterables 工具函数的示例:

// Count elements in an iterable

assert.equal(count(iterable), 4);

// Create an iterable over a part of an existing iterable

assert.deepEqual(

[ ...slice(iterable, 2)],

[ -1, 0]);

// Number the elements of an iterable

// (producing another – possibly infinite – iterable)

for( const[i,x] of zip(range(0), iterable)) {

console.log(i, x);

}

// Output:

// 0, -1

// 1, 0

// 2, -2

// 3, 3

请注意:

  • 更多 iterators 的工具函数示例,请参考 Python 的 itertools。
  • 在 Java 中,支持 iterables 的每个工具函数都应该有两个版本:一个用于支持同步 iterables,另一个用于支持异步 iterables。

不可改变的数据

希望 Java 最好能对非破坏性数据转换提供更多支持。两个相关的库是:

  • Immer 是比较轻量级的,它可与普通对象和队列一起使用。
  • 相对而言,immutable.js 功能更强大也更重量级,它有自己的数据结构。

对于日期和时间的更好支持

Java 内置的对日期和时间的支持有许多奇怪的地方。也正因为如此,才建议大家在最基本的任务之外的其他任务中才使用系统的日期和时间库。

值得庆幸的是,现在人们正在研究日期和时间方面的更好的 API:

constdateTime = newCivilDateTime( 2000, 12, 31, 23, 59);

constinstantInChicago = dateTime.withZone( 'America/Chicago');

可能不太需要的功能

可选链接(chaining)的优缺点

当前一个比较普遍的提议是对于可选链接的支持。根据该提议,以下两个表达式是等效的:

obj?.prop

(obj === undefined|| obj === null) ? undefined: obj.prop

这一功能尤其适用于属性链:

obj? .foo? .bar? .baz

但是,这个功能也有缺点:

  • 很难管理深度嵌套结构。
  • 在访问数据时有较高的容错性,这样会隐藏可能的问题,使它们直到很晚的时候才能被发现,并且很难调试。

可选链接的一个替代方案是在某个特定的位置提取一次信息:

  • 可以编写一个工具函数来提取数据。
  • 也可以编写一个函数,其输入是深度嵌套的数据,其输出则是简单、规范化的数据。

无论采用以上哪种方法,您都能进行检查。早一点发现存在的问题。

更多资料:

  • Carl Vitullo 著“过度防御编程”(https://medium.com/@vcarl/overly-defensive-programming-e7a1b3d234c2)
  • Cory House 著 Twitter 里的线程(https://twitter.com/housecor/status/1088419498846244864)

我们需要运算符重载吗?

现在,有些人正在为运算符重载做前期的准备工作,但我觉得中缀函数应用程序可能已经足够了(尽管目前没有针对它的提议):

import{BigDecimal, plus} from 'big-decimal';

constbd1 = newBigDecimal( '0.1');

constbd2 = newBigDecimal( '0.2');

constbd3 = bd1 @plusbd2; // plus(bd1, bd2)

中缀函数应用的好处是:

  • 可以创建 Java 已经支持的运算符之外的其他运算符。
  • 与普通函数应用相比,嵌套表达式具有更好的可读性。

这是嵌套表达式的一个例子:

a @plus b @minus c @ timesd

times(minus(plus(a, b), c), d)

有趣的是,pipeline 操作符也有助于提高代码的可读性:

plus(a, b)

|> minus( #, c)

|> times( #, d)

其他内容

这些是我偶尔会错过的一些事情,我也不认为它们像我之前提到的内容那样重要:

  • 连锁的异常(Chained exceptions):能够捕获错误,添加更多的信息,然后再次抛出错误;

newChainedError(msg, origError)

  • 可组合正则表达式:

re `/^${RE_YEAR}-${RE_MONTH}-${RE_DAY}$/u`

  • 转义正则表达式的文本(对.replace()很重要):

> constre = newRegExp( RegExp.escape( ':-)'), 'ug');

> ':-) :-) :-)'.replace(re, '

相关下载

玩家评论

手滑了?冯绍峰被曝否认出轨后取关赵丽颖,名字显示关注列表前端_fsf

原标题:手滑了?冯绍峰被曝否认出轨后取关赵丽颖,名字显示关注列表前端 10日有网友爆料一名刚结婚没多久的男星在女方怀孕期间出轨,而爆料中“fsf”“赵详情>>

阅读: 11
日期: 2019-08-11
QQ教程:[6]设置始终保持在其他窗口前端

QQ设置始终保持在其他窗口前端呢?那么,请看下面的教程。攻略对象电脑1台 教程1份步骤分解1下载安装软件【QQ】,如下图所示;2选中软件,右键单击,选择【打开】,如下图所示;3输入登陆账详情>>

阅读: 17
日期: 2019-06-30
怎么将potplayer设置为最前端播放

大家都知道,pot player是和kmpplayer齐名的公认的最好的播放软件之一,它以其强大的播放功能被人们所称赞。但是由于功能太多,所以很多时候不如其他播放器方便。但是一旦上手,其详情>>

阅读: 66
日期: 2019-06-28
让你的页面打开速度飞快-Web 前端优化技术

页面的加载速度直接关联着用户的体验。研究表明,用户最满意的打开网页时间是2-5秒,如果等待超过10秒,99%的用户会关闭这个网页。那么如何优化网页的加载速度呢,下面将从几个方面讲解。1.减少详情>>

阅读: 0
日期: 2018-08-27
初入前端(新手)

【什么是web应用】1、什么是webweb本意是蜘蛛网和网的意思,在互联网中是需要用浏览器浏览的网页2、什么是web应用web应用就是应用在web上的应用,就是b/s架构模式【b/s,c/s模式应用详情>>

阅读: 2
日期: 2018-08-27
程序员用软件生成前端代码,前端妹子看完直接傻眼!却遭领导批评

作为程序员经常会有一些口头禅,比如说“代码复用思想”,“写高质量的代码”,“代码在精不在多”,“思路比努力更重要”,这些话中大多强调的是策略的重要性,在工作中,勤奋固然重要,如果能在勤奋的基础上强调详情>>

阅读: 5
日期: 2018-08-27
学习Web前端开发过程中需避开的5个错误!

作为初入职场的我们,在学习与工作中,总是会遇到不同的挫折。虽然有些错误与某一个具体的行为相关,但有些错误却是所有Web开发人员都需要面对的挑战。因此,通过研究,体验和观察,千锋武汉Web培训小编总结详情>>

阅读: 6
日期: 2018-08-21
移动端调试痛点?—五款前端开发利器,web前端开发HTML5 CSS JS

之所以写这个总结,还要从上周的一次移动端项目的debug说起。那天,测试小姐姐拿着自己的iphone6s过来找我,说页面打不开。我想:这怎么可能,我手机里挺好的呀,Chrome调试工具也没报详情>>

阅读: 4
日期: 2018-08-21
史彦泽:对前端需求链的关注,决定下一阶段企业核心竞争力的关键

8月10日,由ITValue和钛媒体集团联合举办的2018IT价值峰会在海南三亚成功举行。本次大会围绕“复盘、重构”的主题,回顾了过去10年科技、商业环境的变化。过去10年里,随着云计算、大数据、人详情>>

阅读: 5
日期: 2018-08-15
纯前端表格控件SpreadJS V11.2新版本发布,全面支持React和Vue

SpreadJS是一款基于HTML5的纯Java电子表格和网格功能控件,在外观、功能和操作上都与Excel高度类似,在表格数据处理上比Grid类控件更为优秀,被开发人员誉为“可嵌入详情>>

阅读: 22
日期: 2018-08-13
WEB2.0时代到来,WEB前端开发是从网页制作演变而来的

随着现在来前端的又是时间,前端的世界已经开始进入了下一个阶段,传统的网页制作已经逐渐被现在的状态解决了,传统的网页制作中耗时成本长,前期的切图已经逐渐跟不上现在的发展速度。但是随着现在技术的发展,许详情>>

阅读: 6
日期: 2018-08-12
怎样入门前端HTML+CSS

今天小编给想学前端的同学们讲一下怎样入门前端。小编虽然不是专业的程序员,但是前端也算及格,写一些页面完全能应。小编的前端是自学的,在学习的过程中,我的感受就是:网上有很多视频,有免费的也有付费的,但详情>>

阅读: 17
日期: 2018-08-04
5大JavaScript前端框架简介

小编推荐:Fundebug专注于Java、微信小程序、微信小游戏,Node.js和Java实时BUG监控。真的是一个很好用的bug监控费服务,众多大佬公司都在使用。译者按:简要介绍五大前端框架特详情>>

阅读: 1
日期: 2018-08-02
HTML5前端教程:Gulp前端自动化工具

gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器;它不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成;使用它,我们不仅可以很愉快的编写代码,而且详情>>

阅读: 14
日期: 2018-08-01
初学者必看!Web前端开发你可以这样入手!

Web前端在最近几年的发展令人瞩目,成为最近炙手可热的岗位。随着人才需求的增加,企业给Web前端开发工程师开出的薪资也是持续上扬。这种盛况自然而然就引发了众多朋友进入这个行业。想要涉足该领域,好的技详情>>

阅读: 8
日期: 2018-07-30
AKGq701配纯笛耳放前端hm700和hm603有差别么

小编为您搜罗的答案:应该有吧详情>>

阅读: 2
日期: 2018-07-08
[教育攻略]前端开发自学方法全攻略 详解怎么玩

1.前端开发是怎样的?1.1前端开发是什么?【起源】:Web前端开发是从【网页制作】演变而来的。在互联网的演化进程中,网页制作是Web1.0时代的产物,那时网站的主要内容都是静态的,使详情>>

阅读: 4
日期: 2018-06-23
[教育攻略]前端开发必看书籍和网站 详解怎么玩

1.前端开发是怎样的?1.1前端开发是什么?【起源】:Web前端开发是从【网页制作】演变而来的。在互联网的演化进程中,网页制作是Web1.0时代的产物,那时网站的主要内容都是静态的,使详情>>

阅读: 8
日期: 2018-06-23
Web前端应用十种常用技术

Web前端应用十种常用技术,随着JS与XHTML的应用普及,越来越多的web界面应用技术出现在网站上,比如我们常见的日历控件,搜索下拉框等,这些web界面应用技术大大的详情>>

阅读: 7
日期: 2018-04-17
前端射击人物介绍 角色特别深入分析 详解怎么玩

前端射击人物角色特点全面介绍,我们在游戏中随着收集的齿轮逐渐的变多,那么我们就能够不断地解锁更多的人物,每一种人物都有着他们独特的作用和能力,玩家利用好这些,我们就能够在过关的道路上变详情>>

阅读: 3
日期: 2018-03-31
前端射击新手 高分技巧分享 详解怎么玩

前端射击攻略高分通关技巧讲解,玩家在游戏中我们要不断的躲避各种障碍物,收集齿轮来提升我们的实力,游戏中关卡的障碍物还是非常的多的,玩家想要能够成功跨越坚持更久获得高分,还是比较困难的,详情>>

阅读: 8
日期: 2018-03-31
精彩推荐