typescript[4] - function

来源:互联网 发布:迅龙数据恢复 注册码 编辑:程序博客网 时间:2024/05/21 09:18
// -------- Functions(函数) --------// 函数是js程序的基本构件.// 函数包括如何建立抽象层,模拟类,信息屏蔽和模块// 在typescript中,一旦涉及到类和模块,函数肯定在其中扮演重要角色// typescript也加了一些新的功能到标准js函数中,来使得它更加方便使用// -------- Functions(函数) --------// 作为开始,如同在javascript中一样,typescript也可以建立有名字的函数和匿名函数// 这使得你可以为你的程序选择合适的方式,不论你在创建一个api的函数列表,还是创建一次性的函数// 来快速回顾下两种方式在javascript中的实现/*//Named functionfunction add(x, y) {    return x+y;}//Anonymous functionvar myAdd = function(x, y) { return x+y; };*/// 如同在javascript中,函数在return中可以使用函数体外的变量// 当他们这么做,他们被称为,他们捕获到了这些变量/*var z = 100;function addToZ(x, y) {    return x+y+z;}*///  -------- Function Types(函数类型) -------- // 让我们从早些的一个简单例子来增加类型function add(x: number, y: number): number {return x + y;}var myAdd = function(x: number, y: number): number { return x + y; };// 我们给函数的每个参数加了类型,也给函数的返回值加了类型// typescript可以从return代码段中识别出return的类型,所以我们可以在很多情况下省略它//Writing the function type// 现在我们已经给函数确定了类型,让我们通过观察函数各个部分的类型,来写出函数的完整类型var myAdd2: (x: number, y: number) => number =function(x: number, y: number): number {return x + y;}// 函数类型分为2个部分,参数的类型和返回值的类型那个// 当写完整的函数类型,这2个部分都是需要的// 我们写出参数类型就像参数列表,给与每个参数名字和类型// 参数名字只是为了让我们更好的阅读,我们可以替换它们如下/*var myAdd: (baseValue:number, increment:number)=>number =     function(x: number, y: number): number { return x+y; };*/// 只要你排列出参数类型,它就被认为是函数的合法类型,不要在意你给出的参数的名字// 第二个部分是返回值类型.我们可以在参数列表和返回值类型之间使用"=>",这样返回类型会很清楚// 如前面提到的,这个是函数类型的一个必要部分// 所以如果函数没有返回值,那么你应该用"void",而不是留空// 提醒,只有参数和返回类型定义了函数的类型// 捕获的变量是不影响函数类型的// 在影响上,这些捕获变量是函数的"隐藏部分",虽然不是api的组成部分// -------- Inferring the types(类型推断) --------// 在例子里,你可能意识到了,typescript编译器可以识别出类型,即便你在"="的两边,一边写了类型,而一边没有// myAdd has the full function typevar myAdd2 = function(x: number, y: number): number { return x + y; };// The parameters 'x' and 'y' have the type numbervar myAdd3: (baseValue: number, increment: number) => number =    function(x, y) { return x + y; };// 这个被称为"上下文类型",一种类型推断的形式// 这有效降低你的代码量,并且保证了你程序的类型安全//  -------- Optional and Default Parameters(可选参数和默认参数) -------- // 跟javascript不一样,在typescript中,每个函数中的参数都是被函数所需要的// 这不意味没有null值,而是,当函数被编译器调用,编译器会检测用户是否给每个参数提供了值// 编译器也会检测提供的参数是不是函数所要的参数(参数不能多)// 简单的说,传递给函数的参数要跟函数所要求的参数个数一致/*function buildName(firstName: string, lastName: string) {    return firstName + " " + lastName;}var result1 = buildName("Bob");  //error, too few parametersvar result2 = buildName("Bob", "Adams", "Sr.");  //error, too many parametersvar result3 = buildName("Bob", "Adams");  //ah, just right*/// 在javascript中,每个参数都被认为是可选的,用户觉得合适就可以把他们留空// 当他们这么做的时候,这些被留空的参数的值就是undefined// 在typescript中,我们如果要让参数为可选参数,我们要用"?"跟在参数后面来修饰参数// 举例,我们将"last name"设为可选function buildName(firstName: string, lastName?: string) {if (lastName)return firstName + " " + lastName;elsereturn firstName;}var result1 = buildName("Bob");  //works correctly now// var result2 = buildName("Bob", "Adams", "Sr.");  //error, too many parametersvar result3 = buildName("Bob", "Adams");  //ah, just right// 可选参数必须在必须提供的参数之后// 如果我们要让firstName可选,而不是lastName,我们需要改变参数在函数中的位置,把firstName放在列表的最后// 在typescript中,我们也可以给与可选参数一个默认值,如果玩家没有提供值// 这个被称为默认值// 让我们把上面的例子中的lastName赋予一个默认值"Smith"function buildName2(firstName: string, lastName = "Smith") {    return firstName + " " + lastName;}var result12 = buildName2("Bob");  //works correctly now// var result22 = buildName2("Bob", "Adams", "Sr.");  //error, too many parametersvar result32 = buildName2("Bob", "Adams");  //ah, just right// 跟可选参数一样,默认值参数也必须跟在必须提供的参数后面/*function buildName(firstName: string, lastName?: string) {andfunction buildName(firstName: string, lastName = "Smith") {*/// 他们共享一个类型"(firstName: string, lastName?: string)=>string"// 默认值参数没有了默认值,那么就是一个可选参数// -------- Rest Parameters(不定参数) --------// 必须参数,可选参数和默认参数有个共同点,他们都是某一时间一个确定的参数// 有时候,你想把参数作为一个组来使用,或则你可能不知道最终函数会使用多少个参数// 在javascript中,你可以使用"arguments"变量来访问所有的参数,这个在每个函数体内部都可以访问到的变量// 在typescript中,你可以把这些参数们放在一个变量里function buildName3(firstName: string, ...restOfName: string[]) {return firstName + " " + restOfName.join(" ");}var employeeName = buildName3("Joseph", "Samuel", "Lucas", "MacKinzie");// 不定参数被当作一捆可选参数来对待.// 你可以把他们留空,也可以任意数量的使用// 编译器会建立一个参数数组,数组名字是用...前缀来修饰的参数变量,你可以在你的函数中使用这个数组// ...也用在定义函数类型var buildNameFun: (fname: string, ...rest: string[]) => string = buildName;// -------- Lambdas and using 'this'(lambdas表达式中使用'this') --------// 对于来到javascript的程序员来说,'this'在javascript的函数中是怎么工作的,是个很常见的主题// 事实上,要灵活使用javascript,那么学好javascript中的this很重要// 因为typescript是javascript的一个超集,所以typescript开发者有必要去学习如何使用'this'和关注当它没有被正确使用的时候// 如何在javascript中使用'this'可以写一大篇文章,甚至更多// 这里,我们只关注一些基本的东西// 在javascript中,'this'变量在函数被调用的时候才被确定.这使得它非常强大和具有定制的特性.// 但是它带来的成本是,得知道函数运行的上下文// 这让人非常的疑惑,举例来说,当函数被用做callback(回调函数)的时候/*var deck = {    suits: ["hearts", "spades", "clubs", "diamonds"],    cards: Array(52),    createCardPicker: function() {        return function() {            var pickedCard = Math.floor(Math.random() * 52);            var pickedSuit = Math.floor(pickedCard / 13);            return {suit: this.suits[pickedSuit], card: pickedCard % 13};        }    }}var cardPicker = deck.createCardPicker();var pickedCard = cardPicker();alert("card: " + pickedCard.card + " of " + pickedCard.suit);*/// 如果我们试着去运行这个例子,我们会得到一个错误,而不是期待的提醒盒子.// 这是因为'this'在由'createCardPicker'所生成的函数中,已经指向了window,而不是deck这个object// 这个错就是因为调用'cardPicker()'而来的// 这里没有动态绑定,所以就this就指向了window(注意,在严格模式下,这样的情况下,this会是undefined而不是window)// 我们可以修正这个,通过把这个返回的函数绑定一个正确的this// 这样,不论他以后怎么用,他都会被正确指向初始的'deck'对象// 为了修复this,我们使用lambdas表达式(()=>{}),而不是javascript里的表达式// 这样就可以自动在创建函数的时候就捕获'this'变量,而不是在以后使用的时候才捕获var deck = {    suits: ["hearts", "spades", "clubs", "diamonds"],    cards: Array(52),    createCardPicker: function() {        // Notice: the line below is now a lambda, allowing us to capture 'this' earlier        return () => {            var pickedCard = Math.floor(Math.random() * 52);            var pickedSuit = Math.floor(pickedCard / 13);            return { suit: this.suits[pickedSuit], card: pickedCard % 13 };        }    }}var cardPicker = deck.createCardPicker();var pickedCard = cardPicker();alert("card: " + pickedCard.card + " of " + pickedCard.suit);// -------- Overloads(重载) --------// javascript天生就是非常动态的语言// 一点都奇怪,一个javascript函数就可以通过输入的参数的不同,从而返回不同类型的对象var suits = ["hearts", "spades", "clubs", "diamonds"];function pickCard(x): any {    // Check to see if we're working with an object/array    // if so, they gave us the deck and we'll pick the card    if (typeof x == "object") {        var pickedCard = Math.floor(Math.random() * x.length);        return pickedCard;    }    // Otherwise just let them pick the card    else if (typeof x == "number") {        var pickedSuit = Math.floor(x / 13);        return { suit: suits[pickedSuit], card: x % 13 };    }}var myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];var pickedCard1 = myDeck[pickCard(myDeck)];alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);var pickedCard2 = pickCard(15);alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);// 'pickCard'函数会基于用户不同的输入而返回两个不同的值// 如果用户输入一个deck,函数会选择一个卡片// 如果用户选择一个卡片,我们会告诉他什么卡片被选择了// 但是我们如何把这个描述到类型系统里呢// 答案是为一个函数提供多个函数类型来完成一个重载列表// 编译器会使用这个列表来完成函数调用// 让我们来创建重载列表,来描述我们的'pickCard'函数接受什么,返回什么var suits = ["hearts", "spades", "clubs", "diamonds"];function pickCard2(x: {suit: string; card: number; }[]): number;function pickCard2(x: number): {suit: string; card: number; };function pickCard2(x): any {    // Check to see if we're working with an object/array    // if so, they gave us the deck and we'll pick the card    if (typeof x == "object") {        var pickedCard = Math.floor(Math.random() * x.length);        return pickedCard;    }    // Otherwise just let them pick the card    else if (typeof x == "number") {        var pickedSuit = Math.floor(x / 13);        return { suit: suits[pickedSuit], card: x % 13 };    }}var myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];var pickedCard1 = myDeck[pickCard2(myDeck)];alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);var pickedCard3 = pickCard2(15);alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);// 通过这些该表,重载给与我们的'pickCard'函数以类型检测通过// 未来让编译器获取正确的类型检测,它跟随javascript// 它遍历重载表,从第一个重载开始通过提供的参数适配// 如果找到适配的,就选择这个重载作为正确的重载// 由于这个原因,你需要组织重载函数从最可能的到最不可能的排列顺序// 请注意'function pickCard2(x): any'不是重载列表的某一项,所以重载列表只有2项:// 输入一个object 和 输入一个数字// 调用'pickCard'函数,输入其他类型参数,都会导致一个错误

0 0
原创粉丝点击