TypeScript面向对象开发

发布:elantion 日期:2018-07-11 阅读:1495 评论:0

JavaScript是基于原型链方式开发的语言,如果要想面向对象开发,需要把大脑中的对象转变为原型链转或者借助ES6的class语法,对于想习惯了面向对象开发的人来说很不友好。很多经验丰富的前端工程认为基于原型链开发的方式并不差,没必要学习面向对象开发,可是面向原型链开发并不是传统的开发思维方式,很多写Java、C++、PHP等语言的工程表示无法理解原型链的逻辑,特别是大学只教面向对象开发的,学习基于原型链开发敢直就是恶梦。所以,JavaScript也意识到这种非主流的思想会影响到自已的发展,于是ES6(JavaScript的新版本语法)推出来许多面向对象的语法,例如class、getter/setter等等。但TypeScript做得更加彻底,不仅可以满足面向对象的需求,也满足执着于强类型语法的开发者。看不懂这段话?不要紧,让贫僧一点一点地指导大家。

什么是TypeScript

TypeScript是JavaScript的超集,所有TypeScript都必须编译成JavaScript才能运行,如果了解前端语言的同学,还会听说过CoffeeScript、Dart之类的语言,基实跟TypeScript一样,也需要编译成JavaScript才能运行,这些泛JavaScript语言(请允许我这么称呼他们)其最终目的只是为了让开发者更好地实现产品和交互的需求。

面向对象开发

面向对象开发并不是一门语言的功能或者特性,而是一种思维想法,即使像C语言这种函数式语言,你也能写面向对象的代码,相反,也能把Java写出函数式的代码。面向对象开发的优势最显著的就是容易维护、容易扩展,在大型项目和可持续发展的项目中,这是必要的开发要求。当然,函数式编程也不是不好,在某些场景,函数式语言有无以伦比的优越性。这是后话了,以后再聊,先来写个对象练练手。

创建一个简单的对象

TypeScript拥有完整的面向对象开发的能力,下面展示了如何创建一个对象并且实例化。

class Index{
    construtor(){
        // init
    }
    greeting(){
        console.log('Hello world');
    }
}
let index = new Index();
index.gretting();

这是一个很简单的对象,类实例化之后,执行对象的方法greeting,控制台就可以输出hello world。但如果你想用原生的JavaScript要怎么写呢?请看下面:

let Index = (function(){
    function Index(){
        //construtor
    };
    Index.prototype.greeting = function(){
        console.log('hello world');
    };
    return Index;
})();
let index = new Index();
index.greeting();

除了代码量的增加之外,也不太好理解,prototype是什么鬼?为什么要用function来包裹Index?如果你不理解原型链的原理,也不理解JavaScript变态的作用域,确实是会让人懵逼,但幸运的是,有了TypeScript,你可以任性地抛弃JavaScript了,而且不会对你实现产品交互需求有什么影响,上个楼梯也倍儿有劲。

创建一个带有变量修饰符的类

如果说面向对象开发最让人激动的部分,那就是类的变量修饰符了,有了它,妈妈再也不用担心我的变量名重复了。现在你用上了TypeScript之后,你也可以深沉地向TypeScript说句我爱你。

class Index{
    constructor(){
        //constructor
    }
    private _threeWords = 'I love you';
    greeting(){
        console.log(this._threeWords);
    }
}
let index = new Index();
index.greeting();

因为TypeScript最终会编译成JavaScript,所以你总会在JavaScript找到另一种爱,一种复杂的爱。

var Index = (function () {
    function Index() {
        this._threeWords = 'I love you';
        //constructor
    }
    Index.prototype.greeting = function () {
        console.log(this._threeWords);
    };
    return Index;
}());
var index = new Index();
index.greeting();

虽然结果都一样,但为什么不用TypeScript来让你的生活变得更美好呢?

对象的继承

如果某天警察找你说你一个远远远房亲戚去世了,与他有关系的只剩下你,他有一百万的家产要你继承,你惊不惊喜,意不意外?你从此可以少奋斗十年了,四十多岁就可以跟领导说:世界很大,我想去走走。
同理,作为面向对象编程的一个重要概念,继承是非常重要的功能,它虽然不能让你少奋斗十年,但至少可以让你少写许多代码,少许头白头发。下面我来看看一个经典的动物对象例子:

class Animal{
    constructor(args){
        //constructor
        this._name = args.name;
    }
    protected _name;
    protected food = 100;
    speak(){
        console.log(this._name + 'say: Hello, mate.');
    }
    eat(){
        this.food--;
        console.log('food left: ' + this.food);
    }
}
class Dog extends Animal{
    constructor(args){
        super(args);
    }
    getName(){
        console.log('My name is: ' + this._name);
    }
}
let animal = new Animal({name: 'AA'});
animal.speak();
animal.eat();
let dog = new Dog({name: 'BB'});
dog.speak();
dog.eat();
dog.getName();

控制台会打印出以下内容:

AA say: Hello, mate.
food left: 99
BB say: Hello, mate.
food left: 99
My name is: BB

『继承』非常适合那些具有通用性的功能开发,例如数据的存储、数据计算等等,但在前端却用得很少,一个很重要的原因是通用性不强。例如你开发一个评论列表,想在A网站和B网站中用,理论上来说,两边都继承同一个对象,然后改一些参数就可以了。但事际上,你图样图森破了,设计师和交互师会把A网和B网的需求搞得完全不一样,即使都是评论功能,例如A网站把头像放到左边,B网站放到右边,A网站登录后才会显示评论框,B网站点击发布评论时才要求登录,等等。与其写一个通用的组件,还不如把代码拷贝两份,不仅性能更好、灵活性更强,而且还可以解耦,更方便维护。所以并不是说『继承』用上了就好,还得看实际需求。

强类型变量开发

很多人认为强类型语言的性能会更好,因为在内存管理方面会有更好的预判性,理论上来说是会好一些,在极端情况下也确实如此。但在实际项目中,常被Node.js这种优化得不要不要的语言把脸打得啪啪响。所以,性能并不能作为选择强类型语言的第一要素,我认为最重要的功能是对开发者的自我约束。

弱类型语言带来的麻烦

有句话说,自由是在法律的约束下才会拥有。开发也一样,如果你是资深的前端工程师,一定知道JavaScript各种数据类型的转换带来的麻烦,因为JavaScript遇到类型转换时是不会报错的,这就在代码里埋了个定时炸弹,幸运时测试同学帮你找出来了,但如果是由用户发现的,那就很尴尬了。
TypeScript的强类型变量可以帮助你解决这个问题,只要你定义了一个变量,并且声明了变量的类型,任何时候你都不能再改变其类型,否则编辑器会警告你(但不会编译失败)。

let hello: string = 'Hello';
hello = 123; //error

更好的代码补全功能

虽然很多JavaScript编辑器都自带代码补全功能,但也只限于语言本身的代码补全,例如你输入『fun』,编辑器就会提示你补全『function』。我认为代码补全功能是很重要的功能,因为就算是经验丰富的大牛也会出现写错参数名的尴尬情况。但如果有了TypeScript,你可以定义interface,限制参数名称和类型,这样就能把这种低级错误降到最低。

interface ARGS {
    id: string;
    title: string;
    content: string;
    author?: string;
}
function showComment(args:ARGS){
    // args会有参数补全功能
};
showComment({
    id: 1, //类型错误
    title: 'this is a title of comment',
    content: 'this is a awsome comment. '
});

总结

我认为TypeScript是一种非常好的语言,因为它使用了很多写代码时需要的特性,例如对象、接口、修饰符等,都是广泛使用的特性。不需要特殊的理解就能轻松掌握,而且这些特性对于保证程序的稳定性,提高开发的效率都有很好的帮助。
因为这不是教学课程,所以具体怎么使用TypeScript就不展开说了,官网文档就非常完整。我也不想强制大家转用TypeScript,因为每个人写代码的风格差异很大,有些人喜欢松散的风格,跟JavaScript的设计之初就很吻合,并不是什么坏事。这里只是介绍一种希望使用严格风格的语言,用不用,怎么用,还得看自已的风格和实际项目性况。