下载APP
登录
关闭
讲堂
算法训练营
Python 进阶训练营
企业服务
极客商城
客户端下载
兑换中心
渠道合作
推荐作者
当前播放: 09 | 函数相关知识点梳理
00:00 / 00:00
标清
  • 标清
1.0x
  • 2.0x
  • 1.5x
  • 1.25x
  • 1.0x
  • 0.5x
网页全屏
全屏
00:00
付费课程,可试看

TypeScript开发实战

共47讲 · 约450分钟
3008
免费
01 | 重塑“类型思维”
免费
02 | 类型基础(1):强类型与...
免费
03 | 类型基础(2):动态类型...
免费
04 | 编写你的第一个TypeScrip...
免费
05 | 基本类型
06 | 枚举类型
07 | 接口(1):对象类型接口
08 | 接口(2):函数类型接口
09 | 函数相关知识点梳理
10 | 类(1):继承和成员修饰...
11 | 类(2):抽象类与多态
12 | 类与接口的关系
13 | 泛型(1):泛型函数与泛...
14 | 泛型(2):泛型类与泛型...
15 | 类型检查机制(1):类型...
16 | 类型检查机制(2):类型...
17 | 类型检查机制(3):类型...
18 | 高级类型(1):交叉类型...
19 | 高级类型(2):索引类型
20 | 高级类型(3):映射类型
21 | 高级类型(4):条件类型
22 | ES6与CommonJS的模块系统
23 | 使用命名空间
24 | 理解声明合并
25 | 如何编写声明文件
26 | 配置tsconfig.json(1)...
27 | 配置tsconfig.json(2)...
28 | 配置tsconfig.json(3)...
29 | 编译工具:从ts-loader到...
30 | 代码检查工具:从TSLint到...
31 | 使用Jest进行单元测试
32 | 创建项目
33 | 组件与类型(1):函数组...
34 | 组件与类型(2):高阶组...
35 | 事件处理与数据请求
36 | 列表渲染与路由
37 | Redux与类型
38 | 搭建服务端开发环境
39 | 列表的CRUD
40 | 导出Excel
41 | 搭建Vue开发环境
42 | 组件封装
43 | 组件发布
44 | 共存策略
45 | 宽松策略
46 | 严格策略
47 | 结束语
本节摘要

精选留言(13)

  • 2019-07-22
    主要讲了定义函数类型的三种方式
    1、使用变量的方式
    2、使用type(类型别名)
    3、使用inerface (接口)

    使用interface还可以定义混合类型,俗称类库,这个类型的变量既可以当做函数使用,并且其本身还有一些属性或者方法,类似jquery的$使用方式。
    但是使用interface定义混合类型(类库):
    需要注意,其第一个行或者第一个属性必须是一个匿名函数。

    形式如下:
    interface App{
        ():void,
        dosomething():void,
        version:string
    }

    后面如果使用这个类型定义变量的话,一般需要类型断言,使用as。

    使用如下:

    let app:App = (()=>{}) as App;
    app.version = 1.0;
    app.dosomething = ()=>{};

    这个过程可以封装成一个工厂函数:

    function getapp(){
    let app:App = (()=>{}) as App;
    app.version = 1.0;
    app.dosomething = ()=>{};
    return app
    }
    let app = getapp()

    这里有个疑问:我看文档type是类型别名的意思,type和interface在使用场景上有啥区别呢?
    展开

    作者回复: type:不创建新的类型,只是给一个类型起一个名字,比如联合类型,写起来不方便,用type定义后就很简洁,你可以把type当做一种快捷访问方式;

    interface:创建新的类型,接口之间还可以继承(type不可以)。如果可能,建议优先使用 interface。

    另外纠正你的一个理解,接口中的属性没有顺序之分,混合接口不需要第一个属性是匿名函数。

    4
  • 2019-09-12
    function func6(x:number,y=1,z:number,q=1){
        return x+y+z+q;
    }
    console.log(func6(1,undefined,3)); //6 第二个参数undefined的时候3这个参数没有传给y,而是传给了z,y使用了默认值
    3
  • 2019-07-24
    在C++或者java等静态语言中,两个函数名称相同,但是参数类型不同或者参数个数不同,实现了函数重载。
    函数重载的好处是:不需要为功能相似的函数起不同的名称。

    ts实现函数重载的时候,要求定义一系列的函数声明,在类型最宽泛的版本中实现重载,最宽泛的版本个人理解应该是,参数是any类型 返回值是any类型,如下

    ```
    function add8(...rest: any[]): any {
        let first = rest[0];
        if(typeof first === 'string') {
            return rest.join('')
        }
        if(typeof first === 'number') {
            return rest.reduce((pre, cur) => pre + cur)
        }
    }
    ```

    这里有个疑问? 如果这样调用会报错吗 add8(),不传递任何参数
    如果不报错,为什么呢?

    add8(...rest: any[]) 这样定义函数是否包含了未传参数的情况呢?
    展开

    作者回复: 剩余参数表示参数个数不确定,不传是可以的,函数返回的是 undefined。可以加入判断 undefined 的逻辑:
    if (typeof first === 'undefined') {
            throw new Error('No param')
    }

    3
  • 2019-08-13
    function add8(...rest: number[]): number;
    function add8(...rest: string[]): string;
    function add8(...rest: number[] | string[]): number | string {
      let first = rest[0]
      if (typeof first === 'string') {
        return rest.join('')
      }
      if (typeof first === 'number') {
        return rest.reduce((pre, cur) => pre + cur)
      }
    }
    console.log(add8(1,2,3))
    为啥会报错
    展开

    作者回复: 函数重载一般在实现时用any类型,如果一定要这么些,有两个报错要处理:
    1)返回值类型加上undefined
    2)第二个分支,给rest加上类型断言 (rest as number[]),ts只推断了first,rest类型还是 number[]|string[],不符合reduce的接口声明

    1
    2
  • 2019-07-23
    四种声明方式:
        1. 通过function
        2. 通过变量
        3. 通过接口
        4. 通过类型别名

    可选参数:
    通过 ? 来声明。
    ```typescript
    function add5(x: number, y?: number) {
        return y? x + y : x;
    }
    ```

    剩余参数
    ```typescript
    function add6(x: number, ... rest: number[]) {
        return x + rest.reduce((pre, cur) => pre + cur)
    }
    ```
    参数默认值:
    ```typescript
    function add7(x: number, y = 0, z: number, q =1) {
        return x + y + z + q;
    }
    add6(1, undefined, 3)
    ```
    注意:
    必选参数前面的默认参数是不可省略的,需传入 undefined 来获取它的默认值;
    必选参数后面的默认参数是可以省略的。

    函数重载
    ```typescript
    function add8(...rest: number[]): number;
    function add8(...rest: string[]): string;
    function add8(...rest: any[]): any {
        let first = rest[0];
        if(typeof first === 'string') {
            return rest.join('')
        }
        if(typeof first === 'number') {
            return rest.reduce((pre, cur) => pre + cur)
        }
    }
    ```

    ps: 极客时间留言板不支持md是有些难受的😣
    展开
    2
  • 2019-08-25
    请教下老师:

    let addFun:(a:number,b:number)=>number

    这种函数定义的方式,在实际调用的时候该怎么使用?

    作者回复: 这是函数类型的定义,调用前还需要有实现,比如:addFun = (a, b) => a + b;
    然后再调用:addFun(1, 2)

    1
  • 2019-08-14
    听到函数重载时,也遇到参数为空时的困惑,当时是这样处理的:
    ```typescript
    function MySum(...rest: number[]): number;
    function MySum(...rest: string[]): string;
    function MySum(...rest: any[]): any {
        return typeof rest[0] === 'number' ? rest.reduce((pre, cur) => (pre + cur)) :
                typeof rest[0] === 'string' ? rest.join("") : undefined;
    }
    console.log( MySum(1, 2, 3, 4, 5) ); // 15
    console.log( MySum('1', '2', '3', 'a', 'b') ); // 123ab
    console.log( `MySum() = ${MySum()}` ); // MySum() = undefined
    ```
    另外想请教老师,TypeScript 中是否不要求使用分号结尾?视频中好像都没作特别要求?
    展开

    作者回复: 视频中没有处理参数未定义的情况,你这样处理可以。
    ts中对分号结尾没有要求,这个全看个人风格。

    1
  • 2019-08-03
    3被赋值给z,不是y

    function add6(x: number, y = 0, z: number, q = 1) {
      return x + y - z + q
    }
    console.log(add6(1, undefined, 3))
    -1
    展开
    1
  • 2019-11-13
    function sum6(a:number, b=2, c:number, d=4) {
        return a+b+c+d
    }
    console.log(sum6(undefined, undefined, 3), 'sum6(1, undefined, 3)') // 10 1 + 3 + 4

    第一个参数为undefined,不报错,这是因为之前说的,undefined是所有类型的子集的原因吗?
    展开

    作者回复: 第一个参数是undefined应该报错,仔细看一下,或重启一下VSCode

  • 2019-08-28
    老师,函数的重载部分我有一些疑问
    为什么要多余的定义两个函数呢
    function add8(...rest: number[]): number
    function add8(...rest: string[]): string
    直接定义一个
    function add8(...rest: any[]): any
    不是就可以实现函数的重载了吗
    而且我从TypeScript的官网编译结果来看,没有丝毫差别呀
    编译结果如下:
    function F4() {
        var rest = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            rest[_i] = arguments[_i];
        }
        var first = rest[0];
        if (typeof first === 'number') {
            return rest.reduce(function (pre, cur) { return pre + cur; });
        }
        if (typeof first === 'string') {
            return rest.join(',');
        }
    }
    展开

    作者回复: 为啥用函数重载,请见本节我对 火云邪神0007 的回复。
    因为不是很方便,函数重载在实际应用中使用的比较少,一般会用联合类型或泛型代替。
    另外,函数重载的声明只用于类型检查阶段,在编译后会被删除。

  • 2019-08-21
    // function add3(...rest: number[]): number
    // function add3(...rest: string[]): string
    function add3(...rest: any[]): any {
      if(typeof rest[0] === 'number') return rest.reduce((pre, cur) => pre + cur)
      if(typeof rest[0] === 'string') return rest.join('')
    }
    document.getElementById('app').innerHTML = add3(1, 2, 3, 4, 5).toString()

    老师,这样也跑的通,是不是没必要写前面的number和string的定义啊
    展开

    作者回复: 我们的目的不是为了跑通,而要理解函数重载的意义,前两条声明是重载,目的是将参数类型约束为 number 或 string;最后的实现不是重载,要遵循前面的声明,比如传 boolean 就不可以了。

  • 2019-08-18
    有一个小点, arr.reduce() 方法视频里并没有传入初始值, 这样在空数组的时候会报错. 传入初始值 0 就好了.

    作者回复: if (typeof first === 'number') 已经保证了rest 不会是空数组

  • 2019-07-25
    let Add1: (x: number, y: number) => number

    这个能干啥?好像也不能实现函数。

    作者回复: 这是定义一个函数类型,函数实现可基于此类型。

    3