首页 » 网站建设 » phpkindedit应用技巧_一文解决现代编程措辞选择艰难敕令式编程

phpkindedit应用技巧_一文解决现代编程措辞选择艰难敕令式编程

访客 2024-11-27 0

扫一扫用手机浏览

文章目录 [+]

如何理解某种编程措辞的优缺陷?某种编程措辞是否适用于我的项目?面对此类问题,如果乞助于搜索引擎,输入“最佳编程措辞”,结果会罗列一堆文章,涵盖 Python、Java、JavaScript、C#、C++、PHP 等,并且大多对各措辞的优缺陷表述得模棱两可。
我本人很不喜好去读此类文章,由于个中许多部分内容的表述并不到位,短缺实战借鉴意义,而且行文生硬。
因此我试撰本文来做一次深入总结,去伪存真。

本文概述了当前广为利用乃至可能小众的当代编程措辞,力争做到只管即便客不雅观、值得一读,并不带个人偏见。
各措辞按推举程度从低到高依次列出。

phpkindedit应用技巧_一文解决现代编程措辞选择艰难敕令式编程

服膺,并不存在所谓完美的编程措辞。
有的措辞非常适用于后端/API 开拓,而有的措辞则非常适用于系统编程。

文中按当今两大通用措辞家族分类,即C衍生措辞家族和元措辞(Meta Language,ML)衍生措辞家族。

对付开拓职员而言,编程措辞只是工具箱中的工具,更主要的是如何选择得当的工具去完成事情。
我衷心希望本文有助于读者选取适宜自身项目的编程措辞。
做出精确的选择,可降落数月乃至数年的开拓事情量。

哪些编程措辞特性值得关注?

很多编程措辞排行榜文章,紧张比拟的是措辞利用广泛度、开拓职员收入期望值等成分。
在软件领域,虽然大规模的社区和生态系统的确有所裨益,但措辞的利用情形并非好的排行指标。
本文另辟路子,采取的评判依据紧张考虑措辞的强大之处和不敷之处。

为表示所列措辞的推举程度,文中利用“赞”()、“否”()和“尚可”(,即不赞也不否)三种 emoji。

那么该当比较哪些特性?换句话说,除了措辞利用广泛性,还有哪些特性更能代表措辞的受欢迎程度?

类型系统(Type System)

类型系统倍受大量开拓职员的青睐,这也是为什么 TypeScript 之类的措辞日渐大行其道。
在我看来,类型系统去除了大量的程序缺点,更随意马虎实现重构。
但是否具有类型系统,只是本文考虑的部分评判成分。

支持类型系统的编程措辞,最好同时具备类型推断(type inference)。
一个好的类型系统,不用明确地标出函数署名(function signature),也能支持对大部分类型的推断。
不幸的是,大多数编程措辞供应的仅是基本的类型推断功能。

更进一步,支持代数数据类型(Algebraic Data Types,ADT)的类型系统评分更高。

强大的类型系统,还应支持高等类类型(higher-kinded types)。
高等类类型是对泛型(generics)的更高阶抽象,支持编程职员在更高的抽象层上编程。

只管大家对类型系统寄予厚望,但还有一些比静态类型(static typing)更主要的特性。
因此在选择一门编程措辞时,不能只看是否支持类型系统,

学习难度

即便编程措辞是完美无瑕的,如果一位新手上船须要前期投入数月乃至是数年的精力,那么又会有多少人利用呢?另一方面,很多编程范式须要数年的韶光才能逐渐完善。

好的编程措辞需对新手友好,节制它们不应花费大量学习韶光。

空值

我将 1965 年创建的空值引用(null reference)称为“亿万美元缺点”。
当时,我正设计首个完备类型系统,用于面向工具措辞中的引用。
目标是确保所有对引用的利用是绝对安全的,并由编译器自动实行检讨。
我无法克制添加空值引用的诱惑,完备由于空值引用非常易于实现。
近四十年来,这一设计导致了不计其数的缺点、漏洞和系统崩溃,可能造成了数十亿美元的酸心丢失。

— 空值引用的创立者 Tony Hoare

为什么说空值引用是不好的?由于空值引用毁坏了类型系统。
一旦默认为空值,那么就不能依赖编译器检讨代码的有效性。
任何空值都是一枚随时可能引爆的炸弹。
如果没能想到所利用的值的确为空值,那么会产生什么后果?会涌现运行时缺点。

function capitalize(string) { return string.charAt(0).toUpperCase() + string.slice(1);}capitalize("john"); // -> "John"capitalize(null); // 未捕获类型缺点:不能读取为空值的属性“charAt”。

复制代码

为确保所处理的值并非空值,开拓职员必须对运行时做手工检讨。
纵然是静态类型措辞,空值引用也毁坏了类型系统的很多优点。

function capitalize(string) { if (string == null) throw "string is required"; return string.charAt(0).toUpperCase() + string.slice(1);}

复制代码

运行时检讨也称为“空值防护”(null guards),在现实中可归为一种不良的编程措辞设计。
一方面,引入样板代码毁坏了编程风格。
更糟的是,它并不能确保我们是否检讨了空值。

好的编程措辞,应在编译时做类型检讨,判断值的存在与否。

因此,支持空值检讨机制的编程措辞应加分。

缺点处理

捕获非常并不是一种好的缺点处理办法。
抛出非常本身没有问题,但仅适用于程序没有办法规复而必须崩溃这类非常情形。
非常和空值一样,会毁坏类型系统。

如果将非常作为缺点处理的首选办法,那么就无法获知函数是返回了期望值,还是发生了故障。
抛出非常的函数也无法实现复合(Compose)。

function fetchAllComments(userId) { const user = fetchUser(userId); // 可能抛出非常。
const posts = fetchPosts(user); // 可能抛出非常 return posts // posts可能为空值,这会再次导致非常。
.map(post => post.comments) .flat();}

复制代码

无法获取部分数据而导致全体程序崩溃,这显然并非一种好的做法。
只管我们不肯望发生这种情形,但它的确会发生。

一种做法是手工检讨是否天生非常,但是在编程过程中可能会忘却对非常做检讨,因此这种做法是非常不可靠的,而且会在代码中添加大量额外处理。

function fetchAllComments(userId) { try { const user = fetchUser(userId); const posts = fetchPosts(user); return posts .map(post => post.comments) .flat(); } catch { return []; }

复制代码

目前已有更好的缺点处理机制,支持在编译时对潜在缺点做类型检讨。
因此,默认无需采取非常处理的编程措辞也应加分。

并发

当前业界正处于摩尔定律的末端,即处理器不会再大规模提速。
我们身处多核 CPU 时期,所有的当代运用必须能很好地利用多核技能。

不幸的是,大多数当前在用的编程措辞都是设计用于单核打算时期的,实质上并不能有效地支持多核处理。

一种亡羊补牢的设计,是在后期供应支持并发的软件库。
但这只是给措辞打了补丁,并非从根本上就针对并发设计,不能称为良好的开拓体验。
一些当代措辞内建了对并发的支持,例如 Go、Erlang 和 Elixir 等。

不可变性

我认为大型的面向工具程序,须要办理由于大规模可变工具间关联所导致的繁芜图构造。
否则在调用方法时,必须得把握并牢记该方法的功能和副浸染。

—— Rich Hickey,Clojure 创建者。

当前的编程事情中,利用不可变值越来越常见。
即便是 React 这样的当代 UI 软件库,也考虑利用不可变值。
对支持不可变数值供应一等支持的编程措辞,我们会给出更高的评判。
这完备是由于不可变性避免了编程中涌现许多软件毛病。

什么是不可变状态?简而言之,便是数据不会发生改变。
例如,大多数编程措辞中的字符串。
字符串转为大写,并不会去改变原始的字符串,而是返回一个新的字符串。

为确保任何事情都不发生改变,不可变性对上述理念做了进一步扩展。
变动不可变数组,总是会返回一个新的数组,而非原始数组。
更新用户名,将返回一个包含更新后用户名的新用户工具,并不改变原始工具。

不可变状态不做任何共享,因此无需操心线程安全所导致的繁芜性。
不可变性使得代码更易于并行化。

不对状态做任何变动的函数,称为“纯函数”(Pure)。
纯函数更易于测试和推断。
利用纯函数,无需操心函数体之外事情,可聚焦于函数本身。
不用像面向工具编程中那样必须牢记全体工具图,这样极大地简化了编程开拓。

生态系统和工具链

一种编程措辞可能本身并没有多少亮点,但如果其具有大型的生态系统,这会令措辞更具吸引力。
具备良好的软件库,可以节省数月乃至数年的开拓事情。

显著的例子便是 JavaScript 和 Python。

速率

措辞的编译速率如何?程序的启动速率如何?运行时的性能如何?所有这些都是影响评判中的考虑成分。

出身年代

只管并非绝对,常日新推出的措辞要比原来的措辞更好。
只是由于新措辞会吸取了前辈的履历教训。

C++

下面从最糟糕、也可能是打算机科学中最大缺点的 C++措辞开始。
当然,我并不认为 C++是一种很好的当代编程措辞。
但 C++当前依然得到广泛运用,在此必须提及。

措辞家族:C

措辞特性

C++可称为糟糕透顶的措辞……如果项目局限于 C,意味着不会有任何机会被 C++屈曲的“工具模型”搞砸。

—— Linux 创立者 Linus Torvalds

C++中添补了各种特性,力争无所不能,但在在个中任何一项上都不能说出色。
C++支持 goto、指针、引用、面向工具编程、操作符重载,以及各种非生产特性。

为什么说 C++不好?在我看来,最大问题在于 C++颇具年头了。
C++是在 1979 年设计的。
在当时设计者短缺履历,关注点发散,虽然所添加的特性在当时看来是彷佛好的做法。
C++得到了非常广泛的利用,这意味着为个中支持各种用例而添加了更多特性,导致特性成堆。

速率

C++的编译韶光出奇的慢,乃至比 Java 慢很多,只管与 Scala 不相上下。

但在运行时性能和启动韶光上,C++程序表现非常精良。

生态系统和工具

上图的推文给出了很好的阐明。
C++编译器的缺点信息对新手并不友好。
常日并未指出导致缺点的确切缘故原由,须要开拓职员花韶光查找。

垃圾回收

我曾希望在 C++0x 标准中至少考虑可选地支持垃圾回收,但这在技能上存在问题。

—— C++的创建者 Bjarne Stroustrup

垃圾回收从未添加到 C++中,而手工内存管理非常易于出错。
开拓职员必须操心如何手工开释和分配内存。
我对利用非垃圾回收措辞的经历影象深刻,个中大量的毛病在当前支持垃圾回收措辞中可轻易避免。

面向工具编程的失落败考试测验

我提出了“面向工具”一词,但并没有没有顾及 C++。

—— 面向工具编程的创建者 Alan Kay

面向工具编程是一项很好的技能,涌现于上世纪六十年代后期,当时 C++刚涌现。
不幸的是,不同于 Smalltalk 等措辞,C++在实现面向工具编程中涌现了几个致命缺点,导致好的理念变成噩梦。

好的一方面是,不同于 Java,至少在 C++中面向工具是可选的。

学习难度

C++是一种繁芜的低层(low level)措辞,不具备任何自动内存管理机制。
由于特性纷杂,初学者必须花费大量韶光学习。

并发

C++设计用于单核打算时期,只支持大略的并发机制,这还是在近十年中添加的。

缺点处理

抛出并捕获缺点是 C++的首选缺点处理机制。

不可变性

未内置对不可变数据构造的支持。

空值

C++中所有引用均可为空值。

评判

C++的初衷是成为更好的 C 措辞,但这一初衷并未实现。

系统编程是 C++的最适宜利用场景。
但考虑到已具有 Rust 和 Go 等更好、更当代的替代措辞,系统完备可以不用 C++实现。
不管读者赞许与否,我不认为 C++具有任何优点。

是该闭幕 C++的时候了。

Java

Java 是自 MS-DOS 以来打算机领域中最令人困扰的事情。

—— 面向工具编程创始人Alan Kay

Java 涌如今 1995 年,比 C++晚了 16 年。
Java 是更大略的编程措辞,由此得到广泛利用。

措辞家族:C。

垃圾回收

比较 C++,Java 的最大优点是具有垃圾回收,这极大地肃清了各种软件毛病。

生态系统

Java 已经存在很永劫光,在后端开拓领域形成了大型生态系统,极大地降落了开拓包袱。

面向工具措辞

本文不会深入磋商面向工具编程的不敷。
详细剖析可阅读本文作者的另一篇文章,“面向工具编程:亿万美元灾害”。

在此给出打算机科学中一些最为精彩人士的意见:

抱歉,我多年前利用了“工具”一词。
该词使得很多人聚焦于一个更狭义的理念,虽然更广义的理念是通报。

—— 面向工具编程的创始人 Alan Kay

Alan Kay 是对的,许多主流面向工具编程措辞并未找准关注点。
它们聚焦于类和工具,而忽略了通报。
幸运的是,Erlang 和 Elixir 等一些当代编程措辞找准了方向。

受面向工具编程影响的编程措辞,会导致打算机软件冗长、可读性不好、描述性差、难修正和掩护。

—— Richard Mansfield

所有利用 Java、C#等面向工具编程措辞的开拓职员,如果曾具有利用非面向工具编程措辞的履历,对此应深有体会。

速率

大家都知道,Java 运行在 JVM 之上,而 JVM 的启动速率是出名的慢。
我曾看到有运行在 JVM 上的程序耗时 30 多秒才启动起来。
对付当代云原生程序,这是不可接管的。

一个大型项目,如果编译速率慢,就会对开拓职员的生产效率产生显著影响。
Java、Scala 等 JVM 措辞存在同样的问题。

但从好的一壁说,JVM Runtime 的性能还算不错。

学习难度

只管 Java 是一种相称大略的措辞,但 Java 以面向工具编程为主,这使得 Java 很难做到精良。
编写一个大略的 Java 程序可信手拈来,但是节制如何编写可靠、可掩护的面向工具代码,则须要十数年的 Java 功力。

并发

Java 设计于单核打算时期,和 C++一样,仅支持基本的并发特性。

空值

Java 中,所有引用均可为空值。

缺点处理

抛出并捕获缺点是 Java 的首选缺点处理机制。

不可变性

未内置对不可变数据构造的支持。

剖断

Java 在刚推出时,的确是一种很好的编程措辞。
但遗憾的是不同于 Scala 等措辞,Java 始终专注于面向工具编程。
Java 编程严重受模板代码的影响,冗余代码多。

Java 该当退居二线了。

C#

C#和 Java 并没有实质上的差异。
C#的早期版本,便是微软的 Java 实现。

C#具有 Java 的大部分优点。
C#于 2000 年推出,比 Java 晚 5 年,借鉴了 Java 的履历教训。

措辞家族:C

语法

C#在语法上一贯保持略微领先 Java。
只管是一种面向工具措辞,但 C#在办理模板代码问题上比 Java 有所改进。
很高兴看到 C#每个新版本都能改进语法。
例如,添加了表达体函数成员(expression-bodied function members)、模式匹配、元组等特性。

面向工具措辞

和 Java 一样,C#紧张针对面向工具编程。
面向工具编程的缺陷如上所列,在此不再详述。
下面列出一些有名人士的不雅观点。

我认为比较函数式措辞,面向工具措辞中缺失落可重用性。
问题在于,面向工具措辞须要处理其所供应的所有隐含(implicit)环境。
只管我们想要的只是一根喷鼻香蕉,但却得到了一只握着喷鼻香蕉的大猩猩,乃至是全体丛林。

—— Erlang 的创建者 Joe Armstrong

我完备赞许这个说法,比较函数式编程,命令式编程非常难以重用面向工具代码。

面向工具编程供应了瞄准确做法的一个反面教材……

—— 打算机科学先驱 Edsger W. Dijkstra

从我自己利用面向工具和非面向工具编程的履历看,我完备赞许面向工具代码更难以精确实现功能。

多范式(Multi-paradigm)

C#声称是一种多范式措辞,尤其是声称支持函数式编程,但我并不同意。
对函数供应一流支持(first-class functions),并不敷以称之为函数式措辞。

那么什么措辞可称为具备函数式特性?应至少内置支持不可变数据构造、模式识别、组合函数的管道操作符、代数数据类型(ADT)等特性。

并发

和 Java 一样,C#创立于单核打算时期,仅供应基本的并发支持。

空值 Nulls

C#中,所有引用均可为空。

缺点处理

抛出并捕获缺点是 C#的首选缺点处理机制。

不可变性

未内置对不可变数据构造的支持。

评判

只管我本人的职业生涯中紧张利用的是 C#,但还是对这种措辞评价不高。
与对 Java 的评判一样,我建议读者探求更当代的替代措辞。
C#在实质上依然是 Java,只是具有更当代的语法。

不幸的是,C#本身并不“sharp”。

Python

Python 早在 1991 年提出,和 JavaScript 并称当前利用最广的两种措辞。

措辞家族:C

生态系统

Python 软件库险些无所不能。
不同于 JavaScript,Python 不能用于 Web 前端开拓,但大规模的数据科学软件库填补了这方面的不敷。

学习难度

Python 措辞非常大略,初学者数周就能上手。

类型系统

Python 是动态类型的,因此谈不上须要类型系统。

速率

Python 是一种阐明性措辞,性能慢。
对性能有严格哀求的程序,可利用 Cython 替代原生的 Python。

相对付原生措辞,Python 的启动也相称慢。

工具

比拟其他的当代编程措辞,难免会对 Python 的依赖管理颇为失落望。
目前存在 pip、pipenv、virtualenv、pip freeze 等工具。
比较之下,JavaScript 只须要 NPM 这一种工具。

并发

Python 在创建时并未全面考虑并发,仅供应基本的并发特性。

空值

Python 中所有引用均可为空。

缺点处理

抛出并捕获缺点是 Python 的首选缺点处理机制。

不可变性

未内置对不可变数据构造的支持。

评判

很不幸,Python 并不供应对函数式编程的支持。
函数式编程非常适宜处理数据科学所面对的问题。
即便是在 Python 善于的 Web 爬虫领域,Elixir 等函数式措辞表现更好。

我并不推举利用 Python 完成大型项目,该措辞在构建中并未充分地考虑软件工程。

如果有更好的选择,不推举在数据科学之外利用 Python。
在数据科学领域,Julia 可能是 Python 的很好替代,只管比较 Python 而言,Julia 的生态系统近乎不存在。

Rust

Rust 是一种当代低层措辞,最初设计用于替代 C++。

措辞家族:C

速率

运行快速是 Rust 设计所秉持的初衷。
在编译性能上,Rust 程序要慢于 Go 程序,但运行时性能比 Go 稍快。

空值

至此,本文推举列表中终于涌现支持当代空值的措辞了。
Rust 中没有 null 或 nil 值,开拓职员利用 Option 模式。

// 源代码: https://doc.rust-lang.org/rust-by-example/std/option.html// 返回值或者是T类型的Some,或是None。
enum Option<T> { Some(T), None,}// 整数除法不会出错。
fn checked_division(dividend: i32, divisor: i32) -> Option<i32> { if divisor == 0 { // 缺点表示为None。
None } else { // 结果利用Some封装。
Some(dividend / divisor) }}// 该函数用于处理失落败的除操作。
fn try_division(dividend: i32, divisor: i32) { // 与其他列举一样,Option值可模式匹配。
match checked_division(dividend, divisor) { None => println!("{} / {} failed!", dividend, divisor), Some(quotient) => { println!("{} / {} = {}", dividend, divisor, quotient) }, }

复制代码

缺点处理

Rust 的缺点处理引入了当代函数式方法,利用特定的 Result 类型,声明可能会产生失落败的操作。
Result 模式非常类似于 Option 模式,只是在 None 的情形下依然有值。

// 结果或者是T类型的OK函数值,或是E类型的Err函数值。
enum Result<T,E> { Ok(T), Err(E),}// 存在失落败可能的函数。
fn random() -> Result<i32, String> { let mut generator = rand::thread_rng(); let number = generator.gen_range(0, 1000); if number <= 500 { Ok(number) } else { Err(String::from(number.to_string() + " should be less than 500")) }}// 处理函数的结果。
match random() { Ok(i) => i.to_string(), Err(e) => e,

复制代码

内存管理

在本文列出的当代编程措辞中,Rust 是唯一不供应垃圾回收的。
Rust 迫使开拓职员去考虑如何实现底层的内存管理,这影响了开拓职员的效率。

并发

由于 Rust 中短缺垃圾回收,因此实现并发是相称困难的。
开拓职员必须考虑“装箱”(boxing)和“钉住”(Pinning)。
这在具有垃圾回收机制的措辞中,常日是自动完成的。

不可变性

未内置对不可变数据构造的支持。

低层措辞

作为一种低层措辞,开拓职员的生产效率无法其他高层措辞比较。
同时,措辞的学习难度明显增大。

评判

Rust 非常适宜系统编程。
只管比 Go 更繁芜,但 Rust 供应了强大的类型系统。
Rust 供应了当代的空值更换和缺点处理方法。

为什么本文将 Rust 排在 TypeScript 和 JavaScript 之后?Rust 是一种设计用于系统编程的低层措辞,并非后端和 Web API 开拓的最适宜选项。
Rust 短缺垃圾回收机制,未内置对不可变数据构造的支持。

TypeScript

TypeScript 措辞编译为 JavaScript,通过对 JavaScript 添加静态类型,意在成为一种“更好的 JavaScript”。
类似于 JavaScript,TypeScript 同样用于前端和后端开拓。

TypeScript 由同是 C#设计者的 Anders Hejlsberg 设计的,因此代码看上去非常类似 C#,可认为是一种用于浏览器的 C#。

措辞家族:C。

JavaScript 的超集

TypeScript 将自己定位为 JavaScript 的超集,这有助于人们采取。
毕竟大多数人对 JavaScript 耳熟能详。

但作为 JavaScript 的超集,更多程度上是一种缺陷。
这意味着 TypeScript 继续了 JavaScript 的全部问题,局限于 JavaScript 所有的不良设计决策。

例如,该当没有开拓职员喜好 this 关键词吧。
但 TypeScript 依然刻意原封照搬。

再有,其类型系统时常令人感到奇怪。

[] == ![]; // -> 为真NaN === NaN; // -> 为假!

复制代码

换句话说,TypeScript 具有 JavaScript 的所有缺点。
一种糟糕措辞的超集并不会变身成为一种精良的措辞。

生态系统

TypeScript 完备分享了 JavaScript 弘大的生态系统。
这是其最大优点。
特殊是比较 Python 等措辞,NPM 非常好用。

缺陷在于,并非所有的 JavaScript 软件库都可在 TypeScript 中利用,例如 Rambda/Immutable.js 等。

类型系统

个人觉得,TypeScript 的类型系统毫无亮点。

好的一壁是乃至供应对 ADT 的支持。
例如下面给出的差别联合(discriminated union)类型:

// 源代码来自https://stackoverflow.com/questions/33915459/algebraic-data-types-in-typescriptinterface Square { kind: "square"; size: number;}interface Rectangle { kind: "rectangle"; width: number; height: number;}interface Circle { kind: "circle"; radius: number;}type Shape = Square | Rectangle | Circle;function area(s: Shape) { switch (s.kind) { case "square": return s.size s.size; case "rectangle": return s.height s.width; case "circle": return Math.PI s.radius 2;

复制代码

下面是利用 ReasonML 实现的同样代码:

type shape = | Square(int) | Rectangle(int, int) | Circle(int);let area = fun | Square(size) => size size | Rectangle(width, height) => width height | Circle(radius) => 2 pi radius;

复制代码

差别联合类型是在 TypeScript 2.0 中增长的,TypeScript 的语法尚未企及函数式措辞的高度。
例如,在 switch 中的字符串匹配易于出错,编译器无法在大小写缺点时给出警告。

TypeScript 仅供应基本的类型推断。
此外在利用 TypeScript 时,any 关键字的涌现频次难免过高。

空值

TypeScript 2.0 添加了对不可为空(non-nullable)类型的支持,利用编译器选项--strictNullChecks 启用。
但利用不可为空类型并非编程默认,也并非 TypeScript 的惯用做法。

缺点处理

TypeScript 中,利用抛出和捕获非常处理缺点。

新的 JavaScript 特性

新酷特性首先在 JavaScript 中得到支持,然后才是 TypeScript。
实验特性可利用 Babel 在 JavaScript 中得到支持,而在 TypeScript 中则无此功能。

不可变性

TypeScript 对不可变数据构造的处理,要显著劣于 JavaScript。
JavaScript 开拓职员可利用支持不可变性处理的软件库,但 TypeScript 开拓职员常日必须依赖原始数组或工具展开操作符(spread operator),即写入时复制(copy-on-write)。

const oldArray = [1, 2];const newArray = [...oldArray, 3];const oldPerson = { name: { first: "John", last: "Snow" }, age: 30};// 实行工具深拷贝(deep copy)非常繁琐。
const newPerson = { ...oldPerson, name: { ...oldPerson.name, first: "Jon" }

复制代码

正如上面代码所示,原生扩展操作符并不支持深拷贝(deep copy),而手工扩展深度工具非常繁琐。
大型数组和工具的拷贝的性能也非常不好。

但 TypeScript 中,readonly 关键字非常好用,用于定义属性是不可变的。
虽然如此,TypeScript 要对不可变数据构造供应很好支持,依然须要很多事情。

JavaScript 供应了一些操作不可变数据的很好软件库,例如 Rambda/Immutable.js。
但是,实现此类软件库对 TypeScript 的支持并非易事。

TypeScript 比拟 React

比较Clojure等从设计上考虑到不可变数据处理的措辞,在 JavaScript 和 TypeScript 中不可变数据的处理相对更为困难。

—— 原文引用自React官方文档

连续说缺陷。
前端 Web 开拓推举利用 React。

React 并未针对 TypeScript 设计。
最初,React 是针对函数式措辞设计的,本文稍后会详细先容。
二者在编程范式上存在冲突,TypeScript 是面向工具编程优先的,而 React 是函数优先的。

React 中,函数参数 props 是不可变的;而 TypeScript 中,没有内置供应适用的不可变数据构造支持。

在开拓中,TypeScript 比较 JavaScript、React 的唯一优点是,无需操心 PropTypes。

TypeScript 是否是 JavaScript 的超集?

这取决于开拓职员的认识。
至少我认为是的。
做为超集的最大优点,是可接入全体 JavaScript 生态系统。

为什么 JavaScript 的超集措辞备受关注?这与 Java、C#广为采取是同样的缘故原由,是由于背后有市场营销预算充足的大厂在供应支持。

评判

只管 TypeScript 常被认为是“更好的 JavaScript”,但我依然评判其劣于 JavaScript。
TypeScript 比较 JavaScript 的优点被浮夸了,尤其是对付利用 React 做前端 Web 开拓。

TypeScript 保留了 JavaScript 的所有不敷,实际上也继续了 JavaScript 中数十年积累不良设计决策,的确并非一种成功的交付,

Go

Go 设计上紧张考虑了提高多核处理器和大规模代码库的编程效率。
Go 的设计者们当时任职于谷歌,因对 C++的共同不喜而得到灵感。

措辞家族:C。

并发

并发是 Go 的杀手级特性。
Go 从实质上便是为并发而构建。
和 Erlang/Elixir 一样,Go 利用邮箱模型(Mailbox)实现并发。
不幸的是,goroutines 并未供应 Erlang/Elixir 进程那样的统一容错特性。
换句话说,goroutine 中的非常将导致全体程序宕机,而 Elixir 进程中的非常只会导致当提高程终止。

速率

编译速率是谷歌创建 Go 的一个主要考虑。
有个笑话,谷歌利用 C++编译代码的韶光就创建出了 Go。

Go 是一种高效的措辞。
Go 程序的启动韶光非常快。
Go 编译为原生代码,以是运行时速率也非常快。

学习难度

Go 是一种大略的措辞,如果得到有履历前辈的辅导,新手能在一个月内节制。

缺点处理

Go 并不支持非常,由开拓职员显式处理各种可能的缺点。
和 Rust 类似,Go 也返回两个值,一个是调用的结果,另一个是可能的缺点值。
如果统统运行正常,返回的缺点值是 nil。

不支持面向工具编程

虽然这么说有人会反对,但我个人认为,不支持面向工具特性是很大的上风。

重申 Linux Torvalds 的不雅观点:

C++是一种很糟的(面向工具)措辞……将项目局限于 C,意味着全体项目不会由于任何屈曲的 C++“工具模型”而搞砸。

—— Linux 创建者 Linus Torvalds

Linus Torvalds 公开对 C++和面向工具编程持批评态度。
限定编程职员在可选的范围内,是他完备精确的一壁。
事实上,编程职员的选择越少,代码也会更稳定。

在我看来,Go 可以回避了许多面向工具特性,免于重蹈 C++的覆辙。

生态系统

一些标准库的确很笨重。
大部分并不符合 Go 返回带外(out-of-band,OOB)缺点的自身哲学。
例如,有的库对索引返回-1 值,而非(int, error)。
还有一些库依赖全局状态,例如 flag 和 net/http。

Go 的软件库短缺标准化。
例如在缺点时,有的库返回(int, error),也有软件库返回-1 等值。
还有一些库依赖标识等全局状态。

Go 的生态系统规模远比不上 JavaScript。

类型系统

险些所有的当代编程措辞都具有某种形式的泛型,个中包括 C#和 Java,乃至是 C++也供应模板类。
泛型支持开拓职员重用不同类型的函数实现。
如果不支持泛型,那么开拓职员就必须对整型、双精度和浮点型单独实现加法函数,这将导致大量的代码冗余。
换句话说,Go缺失落对泛型的支持导致了大量冗余代码。
正如有人指出的,“Go”是“去写一些模板代码”(Go write some boilerplate)的缩写。

空值

不幸的是,纵然更安全的空值替代方案已存在数十年,Go 依然在措辞中添加了空值。

不可变性

未内置对不可变数据构造的支持。

评判

Go 并非一种好的措辞,但也谈不上不好,只是不足精良。
利用一种并不精良的措辞时需谨慎,由于这可能会导致我们在随后的二十年中陷入困境。

Will Yager 的博客文章“Why Go Is No Good”

如果你并非供职于谷歌,也没有面对类似谷歌的用例,那么 Go 可能并非好的选择。
Go 是一种最适宜系统编程的大略措辞,但并非 API 开拓的好选择。
缘故原由是由于我们有更多更好的替代措辞,本文稍后先容。

我认为总体而言,只管 G 的类型系统略弱,但比 Rust 还是略好。
Go 是一种大略的措辞,非常快,易于学习,并且具有出色的并发功能。
当然,Go 成功地实现了做为“更好的 C++”这一设计目标。

最佳系统编程措辞奖

最佳系统措辞奖付与 Go。
实至名归,Go 是系统编程的空想选择。
Go 是一种低层措辞,利用 Go 构建的大量成功项目,例如 Kubernetes,Docker 和 Terraform,证明其非常适宜系统编程。

JavaScript

作为当前最盛行的编程措辞,JavaScript 无需过多先容。

当然,将 JavaScript 排在 Rust、TypeScript 和 Go 之前是精确的。
下面给出缘故原由。

措辞家族:C

生态系统

生态系统是 JavaScript 的最大上风。
我们能想到的所有,,包括 Web 的前端和后端开拓,CLI 编程、数据科学,乃至是机器学习,都可利用 JavaScript。
JavaScript 可能具有供应任何功能的软件库。

学习难度

JavaScript 和 Python 都是非常随意马虎学习的编程措辞。
几周就能上手做项目。

类型系统

和 Python 类似,JavaScript 是动态类型的。
无需过多阐明,但是其类型系统时常看起来很奇怪:

[] == ![] // -> 为真NaN === NaN; // -> 为假[] == '' // -> 为真[] == 0 // -> 为真

复制代码

不可变性

在 TypeScript 一节中已经先容,展开操作符(spread operator)会影响性能,乃至并没有在拷贝工具时实行深拷贝。
只管有 Ramda/Immutable.js 等软件库,但 JavaScript 短缺对不可变数据构造的内建支持。

JavaScript 并非针对相应式设计的

在 JavaScript 中利用 React,必须借助 PropTypes。
但这也意味着必须去掩护 PropTypes,这会导致灾害性后果。

此外,如果在编程中不加把稳的话,可能会导致严重的性能问题。
例如:

<HugeList options=[] />

复制代码

这个看上去无害的代码会导致严重性能问题。
由于在 JavaScript 中, [] != []。
上面的代码会导致 HugeList 在每一次更新时重渲染,只管 options 值并未发生变革。
此类问题会不断叠加,直到用户界面终极无法相应。

关键字 this

关键字 this 该当是 JavaScript 中的最大反特性。
其行为持续表现不一致,在不同的情形下可能意味完备不同,其行为乃至取决于谁调用了指定的函数。
利用 this 关键字常日会导致一些细微而奇怪的缺点,难以调试。

并发

JavaScript 利用事宜循环支持单线程并发,无需考虑加锁等线程同步机制。
只管 JavaScript 在构建时并未考虑并发性,但与大多数其他措辞比较,更易于实现并发代码。

新的 JavaScript 特性

比较 TypeScript,新特性能更快地在 JavaScript 中支持。
即便是实验性特性,也可利用 Bable 支持在 JavaScript 中利用。

缺点处理 Error handling

抛出并捕获缺点是 JavaScript 的首选缺点处理机制。

评判

JavaScript 并非一种很好设计的措辞。
JavaScript 的最初版本仅用十天就拼凑出来,只管在后期版本中改动了许多缺陷。

抛开上述缺陷,JavaScript 依然是全栈 Web 开拓和很好选择。
如果加以适当的代码修炼和剖析,JavaScript 是一种很好的措辞。

标签:

相关文章

介绍皮肤设置,如何打造理想肌肤状态

随着科技的发展和人们对美的追求,皮肤设置已成为美容护肤的重要一环。如何根据皮肤类型、肤质、年龄等因素进行合理设置,已成为众多爱美人...

网站建设 2025-01-03 阅读1 评论0

介绍盖章制作,传承文化,彰显权威

自古以来,盖章在我国文化中具有重要的地位。从古代的官印、私印到现代的公章、合同章,盖章已成为一种独特的文化符号,承载着丰富的历史内...

网站建设 2025-01-03 阅读1 评论0

介绍监控破坏,技术手段与法律风险并存

随着科技的飞速发展,监控设备已遍布大街小巷,成为维护社会治安的重要手段。一些不法分子为了逃避法律制裁,开始研究如何破坏监控设备。本...

网站建设 2025-01-03 阅读1 评论0

介绍登录不上之谜,技术故障还是人为疏忽

随着互联网的普及,登录已成为人们日常生活中不可或缺的一部分。在享受便捷的登录不上这一问题也困扰着许多用户。本文将深入剖析登录不上之...

网站建设 2025-01-03 阅读1 评论0

介绍电脑键盘调出方法,让操作更高效

随着科技的发展,电脑已经成为了我们日常生活中不可或缺的工具。而电脑键盘,作为电脑输入设备,更是我们与电脑进行交流的桥梁。你是否知道...

网站建设 2025-01-03 阅读1 评论0

介绍磁力链,高效便捷的文件下载利器

在互联网高速发展的今天,文件下载已成为日常生活中不可或缺的一部分。而磁力链作为一种新型的文件下载方式,凭借其高效、便捷的特点,受到...

网站建设 2025-01-03 阅读1 评论0