译自Radix网站的文章,原文链接:https://radixweb.com/blog/typescript-vs-javascript,原文作者:Nihar Raval
正在寻找经验丰富的 JavaScript 开发团队来将您的应用创意变为现实?作为一名开发人员,如果您有机会参与 Web 开发项目,您一定了解 JavaScript 的工作原理。JavaScript 上市多年,已成为开发者社区中流行的脚本语言。但正如我们所知,如果一种技术或语言正在崛起,总会有另一种选择进入市场并与领先者展开激烈竞争。这里有一个新的竞争对手 ——TypeScript。随着 TypeScript 的日益普及,我们可以将其视为具有额外功能的 JavaScript 增强版。谈到 TypeScript,它是一种用于开发大型复杂应用程序的开源编程语言。TypeScript 由科技巨头之一——微软——于 2012 年开发,其创建背后的真正原因是处理大型应用程序。此外,Angular 还使用 TypeScript 进行 Web 开发服务。根据这项研究,TypeScript 和 JavaScript 分别是开发人员希望使用的第二和第三大流行语言。你知道为什么吗?实际上,JavaScript 被认为是应用程序和网页的主要脚本语言。因此,现在,我们可以将 JavaScript 用于TezJS 、React等前端框架,以及 Node.Js 和 Deno 框架的后端。但现在真正的问题是,JavaScript 是为创建大型复杂的 Web 应用程序而开发的吗?我想答案是否定的!在本文中,我们将比较这两种编程语言——TypeScript 与 JavaScript,它们之间的关系,它们的区别,并概述每种语言的优点。但在此之前,在此视频中快速了解 TypeScript 和 JavaScript 之间的差异。


let a = 'a'; a = 1; // throws: error TS2322: Type '1' is not assignable to type 'string'.
在 TypeScript 中,类型是可选的,任何 JavaScript 文件都是有效的 TypeScript 文件。虽然如果您的任何初始文件存在类型问题,编译器会通知您,但它仍会提供一个有效的 JavaScript 文件。TypeScript 将不负众望,随着时间的推移提高您的技能也很简单。first_name:string一个last_name:string. 好吧,你可以这样说:我希望我的类型是这样且那样的。联合类型允许您输入各种基本类型之一。例如,如果有一个返回result:stringor undefined,您可以这样说:我希望我的类型是这个或那个。当您将它们视为空间时,所有这些类型都有意义。
TypeScript 同时支持隐式和显式类型。如果您不显式编写类型,编译器将启用类型推断来识别您正在使用的类型。另一方面,明确编写它们会带来好处,例如协助其他团队成员阅读您的代码并验证您所看到的是编译器所看到的。// -- TypeScript -- //
function log(message: string = null) { }
// -- TypeScript compiled output -- //
function log(message) {
if (message === void 0) { message = null; }
}
// -- JavaScript with Babel -- //
function Log(message = null) { }
// -- Babel compiled output -- //
"use strict";
function Log() {
var message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
}
// -- TypeScript -- //
class Article {
name: string;
constructor(name: string) {
this.name = name;
}
}
// -- TypeScript compiled output -- //
var Article = /** @class */ (function () {
function Article(name) {
this.name = name;
}
return Article;
}());
// -- JavaScript with Babel -- //
class Article {
constructor(name) {
this.name = name;
}
}
// -- Babel compiled output -- //
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Article = function Article(name) {
_classCallCheck(this, Article);
this.name = name;
};
class Person
{
private name: string;
constructor (private name: string)
{
this.name = name;
}
name()
{
return “name is “ + this.name;
}
}
对于 JavaScript:var Person = (function()
{
function Person(personName)
{
this.name = personName;
}
Person.prototype.name= function()
{
return "My name is " + this.name;
}
return Person;
})();
| | |
| 编译时类型检查 | 使用 Vanilla JavaScript,类型验证在运行时执行。然而,这会增加运行时开销,这可以通过进行编译时验证来避免。 |
| 大型项目或多个开发人员 | TypeScript 可以在大型项目或许多开发人员一起工作时无缝运行。 |
| 易于使用新库或框架 | 假设,如果你正在使用 React 进行开发并且不熟悉它的 API,你可以获得 语法提示来帮助你识别和导航新界面。但是,它们都提供类型定义 |
| | |
| 小项目 | 对于代码较少的小型项目,TypeScript 可能有点矫枉过正。 |
| 框架支持 | 如果 TypeScript 不支持您选择的框架 – 例如EmberJS,那么您可能无法利用它的功能。 |
| 构建工具 | 要生成能运行的最终 JavaScript,TypeScript 需要有一个构建的步骤。不过,在不使用任何构建工具的情况下开发 JavaScript 应用正变得越来越少。 |
| 测试工作流程 | 如果您优秀的 JavaScript 开发人员已经在使用测试驱动开发,那么切换到 TypeScript 的好处可能不足以证明迁移成本是合理的。 |
| 范围 | Typescript | JavaScript |
| 开发者 | Microsoft in 2012 | Brendan Eich (Netscape),1995 年 |
| 定义 | TypeScript 是一种强大的面向对象语言,作为 JavaScript 的超集,具有泛型和 JS 特性来解决 JS 的复杂问题。 | JavaScript 是一种脚本语言,具有创建动态网页的一流功能。 |
| 类型 | 强类型。TypeScript 支持静态类型和动态类型。 | 弱类型 。JavaScript 仅支持动态类型。 |
| 生态 | TypeScript 更像是一种支持静态类型的强大而直观的语言。 | JavaScript 是一种简单的语言,它优化了代码的兼容性,易于阅读和编写。 |
| 编译 | TypeScript 需要编译。 | JavaScript 不需要编译。 |
| 数据绑定 | TypeScript 利用接口和类型等概念来定义所使用的数据。 | JavaScript 中没有这样的概念。 |
| 学习曲线 | TypeScript 有一条不友好的学习曲线。此外,它需要JavaScript知识。 | 它易于学习并且是一种用于编写 Web 脚本的灵活语言。 |
| Npm 包 | 使用Typescript,许多npm包要么有静态类型定义,要么有一个更容易安装的外部类型定义。 | JavaScript提供了不需要任何构建步骤就可以搜索和生成代码的替代方案。 |
| 客户端或服务器端 | TypeScript 专门用于客户端。 | JavaScript 用于服务器端和客户端。 |
| 文件扩展名 | .tsx 和 .ts | .js |
| 社区 | TypeScript 有一个较小的软件开发者社区。 | JavaScript 拥有庞大的软件开发人员社区。 |
| 原型设计 | 原型设计特性在 TypeScript 中可用。 | JS 不支持原型设计。 |
| 公司和网站 | Asana, Clever, Screen award | Airbnb、Codecademy、Instagram |
| 代码示例 | function multiply (a, b){ return a*b;}var result = multiply(a, b);console.log('答案是 - ' + result); | <script>function multiply (a, b){ return a\*b;}var result = multiply(a, b);document.write (‘The answer is – ’ + result);</script> |
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行
我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev
打印1:defsum(i)i=i+[2]end$x=[1]sum($x)print$x打印12:defsum(i)i.push(2)end$x=[1]sum($x)print$x后者是修改全局变量$x。为什么它在第二个例子中被修改而不是在第一个例子中?类Array的任何方法(不仅是push)都会发生这种情况吗? 最佳答案 变量范围在这里无关紧要。在第一段代码中,您仅使用赋值运算符=为变量i赋值,而在第二段代码中,您正在修改$x(也称为i)使用破坏性方法push。赋值从不修改任何对象。它只是提供一个名称来引用一个对象。方法要么是破坏性
使用rspec-rails3.0+,测试设置分为spec_helper和rails_helper我注意到生成的spec_helper不需要'rspec/rails'。这会导致zeus崩溃:spec_helper.rb:5:in`':undefinedmethod`configure'forRSpec:Module(NoMethodError)对thisissue最常见的回应是需要'rspec/rails'。但这是否会破坏仅使用spec_helper拆分rails规范和PORO规范的全部目的?或者这无关紧要,因为Zeus无论如何都会预加载Rails?我应该在我的spec_helper中做
Ruby中的Fixnum方法.next和.succ有什么区别?看起来它的工作原理是一样的:1.next=>21.succ=>2如果有什么不同,为什么有两种方法做同样的事情? 最佳答案 它们是等价的。Fixnum#succ只是Fixnum#next的同义词。他们甚至在thereferencemanual中共享同一block. 关于ruby-Ruby中.next和.succ的区别,我们在StackOverflow上找到一个类似的问题: https://stacko
我明白了defa(&block)block.call(self)end和defa()yieldselfend导致相同的结果,如果我假设有这样一个blocka{}。我的问题是-因为我偶然发现了一些这样的代码,它是否有任何区别或者是否有任何优势(如果我不使用变量/引用block):defa(&block)yieldselfend这是一个我不理解&block用法的具体案例:defrule(code,name,&block)@rules=[]if@rules.nil?@rules 最佳答案 我能想到的唯一优点就是自省(introspecti