技术开发 频道

JavaScript大师谈TypeScript

        【IT168 技术】前段时间,微软发布了TypeScript语言,这个项目主要的负责人是 Anders Hejlsberg (C#、TurboPascal 之父)。TypeScript提供了类、模块和接口来帮助您构建健壮的组件,它可以帮助 JavaScript开发人员更容易地编写和维护应用程序。这似乎预示着微软正在试图使用TypeScript来替代JavaScript。

  在Web领域,几乎每周都会出现新的语言来试图取代JavaScript,比如谷歌推出的Dart就是想解决所有JavaScript不能修复的根本性问题;后来CoffeeScript的出现更煽动了这场取代JavaScript的战争。现在,微软也加入了,这不禁让我想知道为什么?

  个人偏见

  在具体讨论TypeScript之前,我先阐述一下个人感受,你可以在看完后对此进行评论。Web开发行业有个很现实的问题,该行业对JavaScript人才的需求一直在增长,过去10年中,虽然JavaScript的高手越来越多,但仍然是供不应求的。

  这种高需求低供给的现状也让优秀的JavaScript开发人员处于令人敬畏的位置,开发人员并不希望改变现状,因为这样他们的薪资就可以得到保障。当然,从个人角度考虑,谁都不愿意改变,但是从整个Web发展来看,肯定希望能有更多优秀人才加入进来,让Web开发行业不断成长,更加美好!

  我认为编译为JavaScript的语言很难达到这一目标。我们应该说服更多的人学习JavaScript,而不是提供更多的选择让他们放弃编写JavaScript。我常在想,如果所有的团队、公司都把时间和精力花在研究和探索JavaScript的替代者而非维护、传播它,那将会发生怎样的一番景象。

  需要澄清的是,JavaScript并非完美无瑕的语言。话说尺有所短,寸有所长,我使用过的所有语言都有利与弊,JavaScript也不例外。但我希望所有人都能齐心协力地研究一个项目,而不是分裂和互相替代。

  什么是TypeScript?

  首先,TypeScript是JavaScript的首要超集(TypeScript is first and foremost a superset of JavaScript),TypeScript完全兼容JavaScript语言。除此之外,它还添加了更多的功能,通过TypeScript编译,可以把代码进行转换,使之与ECMAScript 5兼容。这与其他编译为JavaScript的语言是不同的。TypeScript并没有创造新的语法,也就是说JavaScript开发人员很快就可以使用TypeScript开发更多的功能。值得一提的是,TypeScript允许加入注释,让编译器理解所支持的对象和函数,编译器会移除注释,不会增加开销;增加一个完整的类结构,使之更新是传统的面向对象语言。语法借用了原始的JavaScript 2/ECMAScript 4提案,同时也可以作为ActionScript 3实现。

var myName: string = "Nicholas";  

function add(num1: number, num2: number): number {  
    
return num1 + num2;  
}  

function capitalize(name:
string): string {  
    
return name.toUpperCase();  
}

  如果你使用过Pascal或者Delphi,肯定会对冒号式语法很熟悉,它们都是使用相同的语法来指明类型。JavaScript里面的strings、numbers和booleans在TypeScript里面所呈现的是string、number和bool(备注:都是小写)。这些注释会帮助TypeScript编译器判断所使用的值是否正确。例如下面的这个例子,在页面中会出现警告:

// warning: add() was defined to accept numbers  
var result = add("a", "b");

  由于add()方法是接受numbers类型的,所以在TypeScript编译器中会出现警告。

  TypeScript也非常智能,能够在声明时判断数据类型。例如,下面这些都是自动声明类型的:

var count = 10;           // assume ": number"  
var name = "Nicholas";    // assume ": string"  
var found = false;        // assume ": bool"

  所以你无需声明变量类型,编译器可以自己弄清楚类型信息。

  也许这些注释最酷的地方是能够正确注释回调函数。假设数组的每个item里面都会运行一个函数,与Array.prototype.forEach()相似。如果使用JavaScript,你通常会这样定义:

function doStuffOnItems(array, callback) {  
    var i
= 0,  
        
len = array.length;  

    
while (i < len) {  
        callback(
array[i], i, array);  
        i
++;  
    }  
}

  callback()函数接受3个参数:值、索引和数组本身。你很难在不阅读代码的情况下了解函数的具体信息。而在TypeScript里面,你可以通过注释使函数参数更加详细:

function doStuffOnItems(array: string[],  
        callback: (value:
string, i: number, array: string[]) => {}) {  
    var i
= 0,  
        len
= array.length;  

    
while (i < len) {  
        callback(array[i], i, array);  
        i
++;  
    }  
}

  上面这段代码,对doStuffOnItems()方法里面的参数进行了更加详细的注释。第一个参数是一个字符串类型的数组,第二个参数是一个接受3个参数的函数。备注:上面的双箭头是采用ECMAScript 6语法,编译器可以在执行之前自动验证函数参数匹配。

  类型注释算是TypeScript的核心。通过注释这些额外的信息,编辑器不仅可以在执行前对类型进行检查,还可以提供更好的智能支持。Visual Studio、Vim、Sublime Text 2和Emacs上都支持TypeScript插件,大家可以去尝试一下!

${PageNumber}

        附加功能

  TypeScript加入了静态类型语法,还支持ECMAScript 6的类和模块(正如目前所定义的),意味着你可以编写类似下面的代码:

class Rectangle {  
    constructor(length: number, width: number) {  
        
this.length = length;  
        
this.width = width;  
    }  

    area() {  
        
return this.length * this.width;  
    }  
}

  转换成TypeScript后:

var Rectangle = (function () {  
    
function Rectangle(length, width) {  
        this.length
= length;  
        this.width
= width;  
    }  
    Rectangle.prototype.area
= function () {  
        return this.length
* this.width;  
    };  
    return Rectangle;  
})();

  注意:上面构造函数没有问题,它是可以放在原型里的。

  除了模块和类,TypeScript还支持自定义接口,虽然接口没有按照ECMAScript 6标准去定义,但在涉及到类型检查时还是非常有用的。 由于JavaScript代码常常会定义大量的常量对象,所以,接口提供了一种非常简单的方式来验证对象类型使用的正确与否。例如:

interface Point {  
    x: number;  
    y: number;  
}  

function getDistance(pointA: Point, pointB: Point) {  
    
return Math.sqrt(  
               Math.pow(pointB.x
- pointA.x, 2) +  
               Math.pow(pointB.y
- pointA.y, 2)  
           );  
}  

var result
= getDistance({ x: -2, y: -3}, { x: -4, y: 4})

  在上述代码中,定义了一个Point接口,并且包含两个属性:x,y。getDistance()方法接受两个点:pointA和pointB,并且计算两点之间的距离。这两个参数可以是任何包含x,y属性的对象,这意味着TypeScript可以通过检查对象定义来保证对象包含的属性正确。

  接口和类都可以注入类型系统来提供更好的错误检查,模块只是把相关功能结合在一起。

  喜欢的地方

  首先,可以在TypeScript里面编写JavaScript代码,微软并没有完全创造一门新语言,他们试图以更有价值的方式来使用JavaScript语言。另外值得高兴的是把代码预编译成JavaScript,这很有实际意义。对TypeScript生成代码进行调试也不那么困难,因为它使用了大家非常熟悉的模式。

  另我印象最深的是TypeScript没有做什么——它没有把类型检查信息输入到JavaScript代码里面,所有的类型注释和错误检查都在开发时完成。除非你是手动使用JavaScript代码,否则最终的代码将不会做任何类型检查。类和模块会在转换成普通的JavaScript代码时完全消失,在最后的JavaScript代码里面是不会出现任何使用过的接口信息。

  编辑器集成也相当不错,你只需要在编辑器提示警告或错误时添加一些注释就可以了。能够明确定义回调函数也是令人印象深刻的,这样就可以检验是否有不正确的值传到函数里。

  另外值得高兴的是,TypeScript是开源的。微软致力于发展开放的TypeScript社区,持续运转这个开源社区还有待观察,但最起码已经采取措施,保证了这种可能性。

  不喜欢的地方

  当赞赏微软使用ECMAScript 6类时,我不禁担心它是否会毁掉这门语言。通过与TypeScript项目成员的交谈获知:在类和模块上,他们会保持与ECMAScript 6语法同步。理论上,这样的做法值得称赞,它鼓励人们学习未来会很有用的技术;但从现实角度出发,这样去定位还是比较困难的,因为ECMAScript 6标准还没完成,在规范没有发布之前更无法保证语法不会改变。这样开发TypeScript的团队会处于非常困难的境地:为了保持与时俱进,必须继续更新语法且要保持开发环境的稳定性。

  TypeScript小组希望将来的社区将同时围绕语言和工具发展,及时获知未来的走向。但这也是一把双刃剑,如果他们成功了,将会创建一个庞大的TypeScript社区,但也有可能会因为维护和更新的成本而偏离ECMAScript标准。

  我非常不喜欢原始类型布尔型命名为bool,我希望能改成boolean类型,以便映射typeof的返回值,还有string和number类型也一样。

  你应该使用它吗?

  我认为,TypeScript虽然很有保证,但请记住:目前提供的只是早期的预览版本,TypeScript并不像它的网站看起来那样精美,最终版本可能会在一年后ECMAScript 6发布会确定,现在的版本只是个开发之预览版。

  所以,现在真的就值得使用了吗?现在去体验并且把感受反馈给TypeScript团队是不错的做法。如果想把它作为日常工作来使用,这样会存在很大风险。我强烈建议你使用类型注释和接口,因为这些都是完全编译后的代码,并且与ECMAScript 6之间没有直接关系。但要注意避免使用目前ECMAScript 5尚不支持的任何东西。

  结论

  TypeScript提供了一些与其他编译成JavaScript语言不同的方案,并且添加了一些功能。我很高兴可以在TypeScript中编写JavaScript,并且可以从TypeScript中改善类型检查。这还意味着编写TypeScript代码能够帮助你学习JavaScript。毫无疑问,当编译器集成时,这些类型注释会创建更好的开发体验。一旦ECMAScript 6定案,肯定会有许多开发者开始使用TypeScript,也可以在并不原生支持它的浏览器中编写ECMAScript 6代码。TypeScript仍然有很长的路要走,但还是值得关注的。

0
相关文章