从C#到TypeScript - function

从C#到TypeScript - function

虽然TypeScript里有了类,但JavaScript的function也还在,这也是和C#的不同所在。 C#里函数不能脱离类工作,但TypeScript的function和JavaScript一样,可以单独工作。

函数类型

函数和C#一样可以有名字,也可以是匿名函数,匿名函数有两种写法:

function checkLogin(name: string, pwd: string): boolean{
    return true;
}

let checkLogin = (name: string, pwd: string) => {
    return false;
}

let checkLogin = function(name: string, pwd: string){
    return true;
}

前面文章写变量声明时有写变量类型let str: string,但上面其实都没有把函数的类型真正写出来,比如最后一个let checkLogin里并没有标明返回的类型。 如果要把函数做为参数或返回值的话如果没有明确类型的话使用会很不方便,没有智能提示,重构也不方便。 函数的返回类型其实就是由参数+返回类型构成,下面代码的(name: string, pwd: string) => boolean就是checkLogin的返回类型。

let checkLogin: (name: string, pwd: string) => boolean = function(name: string, pwd: string){
    return true;
}

返回类型里的参数名不需要与真正的参数名一致,只需要类型一致即可。 当然,大部分情况下是不用写这么复杂的返回类型的,前面文章有说过类型推论,TypeScript会根据上下文推论出返回值的类型。

函数参数

TypeScript的参数和JavaScript的参数不太一样,调用JavaScript函数的参数可以多或少都可以,但TypeScript里函数需要确保传入参数的个数和定义的一致。 同C#里的函数参数可以有默认值一样,TypeScript也支持,并且还支持可空参数。 默认值只需要在参数后面写上=某值就可以,默认值参数可以在任意位置,不过在必须参数前面时,想用默认值的话需要传undefined。 可空参数和前面说的可空属性一样,参数名后加?号,可空参数必须是在最后面。

function checkLogin(name: string, pwd: string, isAdmin: boolean = false, email?: string){
    console.info(isAdmin);
}

checkLogin('brook'); // 编译不了
checkLogin('brook', '123456'); // false
checkLogin('brook', '123456', undefined); // false
checkLogin('brook', '123456', false); // false
checkLogin('brook', '123456', true, 'brook@email.com'); // true

剩余参数

JavaScript里的参数本身是个数组,可以是任意个数且都可以在函数体内用arguments来访问。 TypeScript同样可以通过剩余参数来支持,形式上类似于C#的param。 剩余参数的格式是...restParam: string[]

function checkLogin(name: string, pwd: string, ...others: string[]){
    console.info(others.join(' '));
}

checkLogin('brook', '123456', 'brook@email.com', `12800`); // brook@email.com 12800

this

this在JavaScript里总是指向调用者,这点经常容易导致被坑,在ES6之前经常需要类似var self = this来把this保存下来。 ES6和TypeScript针对这点做了改进,使用箭头函数可以把创建函数时的this自动保存下来。

let permission = {
    name: 'brook',

    checkLogin: function() {
        return function() {
            console.info(this.name === 'brook');
        }
    }
};

permission.checkLogin()(); // 出错, this为undefined

let permission = {
    name: 'brook',

    checkLogin: function() {
        return () => {
            console.info(this.name === 'brook');
        }
    }
};

permission.checkLogin()(); // 通过,因为用了箭头函数

不过上面的this还是有个缺点,得到的thisany类型,这样重构起来会不方便,这时可以用this参数来改进: this参数只是一种定义,使用时是不需要传的。

interface Permission{
    name: string;
    checkLogin(this: Permission): ()=>void;
}

let permission: Permission = {
    name: 'brook',

    checkLogin: function(this: Permission) {
        return () => {
            console.info(this.name === 'brook'); //这里的this不是any,而是Permission
        }
    }
};

permission.checkLogin()();

这样也倒逼着定义好类型,发挥TypeScript强类型的优势。

泛型函数

同C#一样支持泛型函数,写法也差不多。

function deserialize<T>(content: string): T { }

function addItem<TKey, TValue>(key: TKey, value: TValue) { }

也支持泛型约束,C#用的是where T: object,而TypeScript用的是extends Object

function deserialize<T extends Object>(content: string): T { }

泛型函数类型比普通函数类型在前面多了个<T>,比如上面deserialize

let deserialize: <T>(content: string) => T;

但这样如果做为参数就略显复杂,可以用接口重构下:

function deserialize<T extends Object>(content: string): T { }

interface serializable<T> {
    (content: string): T;
}

function parse<T>(s: serializable<T>){ }

parse(deserialize);

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏debugeeker的专栏

《coredump问题原理探究》Linux x86版3.8节栈布局之栈溢出coredump例子

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

742
来自专栏梦里茶室

一个由proguard与fastJson引起的血案

更新微信sdk导致ComposeData中的内部类ComposeDataSender方法被混淆 根本原因,fastjson使用姿势不对。 问题描述: 一个发件人...

1887
来自专栏河湾欢儿的专栏

数组

631
来自专栏编码小白

ofbiz实体引擎(四) ModelReader的作用

public class ModelReader implements Serializable { public static final Stri...

2718
来自专栏平凡文摘

面试问烂的 Spring AOP 原理、SpringMVC 过程

Spring AOP ,SpringMVC ,这两个应该是国内面试必问题,网上有很多答案,其实背背就可以。但今天笔者带大家一起深入浅出源码,看看他的原理。以期让...

772
来自专栏函数式编程语言及工具

Scalaz(47)- scalaz-stream: 深入了解-Source

   scalaz-stream库的主要设计目标是实现函数式的I/O编程(functional I/O)。这样用户就能使用功能单一的基础I/O函数组合成为功能完...

2655
来自专栏JAVA后端开发

xml与java对象的快速互转

做流程图的项目时,新的流程定义为xml的,需要对xml与java对象进行互转 查了一下activiti的转换xml方式,发现转换太麻烦了,需要一步步的解析xm...

2072
来自专栏androidBlog

Android 代码混淆语法讲解及常用模板

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/de...

1132
来自专栏跟着阿笨一起玩NET

事件(Event)

事件是对象发送的消息,以发信号通知操作的发生。操作可能是由用户交互(例如鼠标单击)引起的,也可能是由某些其他的程序逻辑触发的。引发事件的对象称为事件发送方。捕获...

532
来自专栏一个会写诗的程序员的博客

第9章 文件IO操作、正则表达式与多线程第9章 文件IO操作、正则表达式与多线程

我们在《第6章 扩展函数与属性》中已经介绍过Kotlin中的类扩展的特性。使用Kotlin的扩展函数功能,我们可以直接为 String 类实现一个 inc() ...

813

扫码关注云+社区