typescript[4] - function
2016-01-17 21:57
337 查看
// -------- Functions(函数) -------- // 函数是js程序的基本构件. // 函数包括如何建立抽象层,模拟类,信息屏蔽和模块 // 在typescript中,一旦涉及到类和模块,函数肯定在其中扮演重要角色 // typescript也加了一些新的功能到标准js函数中,来使得它更加方便使用 // -------- Functions(函数) -------- // 作为开始,如同在javascript中一样,typescript也可以建立有名字的函数和匿名函数 // 这使得你可以为你的程序选择合适的方式,不论你在创建一个api的函数列表,还是创建一次性的函数 // 来快速回顾下两种方式在javascript中的实现 /* //Named function function add(x, y) { return x+y; } //Anonymous function var 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 type var myAdd2 = function(x: number, y: number): number { return x + y; }; // The parameters 'x' and 'y' have the type number var 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 parameters var result2 = buildName("Bob", "Adams", "Sr."); //error, too many parameters var result3 = buildName("Bob", "Adams"); //ah, just right */ // 在javascript中,每个参数都被认为是可选的,用户觉得合适就可以把他们留空 // 当他们这么做的时候,这些被留空的参数的值就是undefined // 在typescript中,我们如果要让参数为可选参数,我们要用"?"跟在参数后面来修饰参数 // 举例,我们将"last name"设为可选 function buildName(firstName: string, lastName?: string) { if (lastName) return firstName + " " + lastName; else return firstName; } var result1 = buildName("Bob"); //works correctly now // var result2 = buildName("Bob", "Adams", "Sr."); //error, too many parameters var 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 parameters var result32 = buildName2("Bob", "Adams"); //ah, just right // 跟可选参数一样,默认值参数也必须跟在必须提供的参数后面 /* function buildName(firstName: string, lastName?: string) { and function 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'函数,输入其他类型参数,都会导致一个错误
相关文章推荐
- Leetcode 242 Valid Anagram 字符串处理
- codevs 1743 反转卡片
- PHP安装编译教程
- windows下Elasticsearch+Logstash+Kibana日志收集分析系统安装教程
- TCP/IP illustrated 阅读笔记(四) UDP协议和IP分段
- Codeforces 616D Longest k-Good Segment(双指针)
- challenge(二)闪屏和引导页
- mysql之函数【整理】
- HDOJ2454(Degree Sequence of Graph G)(Havel-Hakimi定理判断所给序列是否可化成简单图)
- Recognizing and Localizing Endangered Right Whales with Extremely Deep Neural Networks
- android 微信朋友圈效果(附完整注释)
- C++编程对缓冲区的理解
- python100例(一)
- 交换两个整型变量的值
- Hash桶实现hash表
- 【LeetCode-242】Valid Anagram(C++)
- 第二章:高性能Web宏观架构之代理服务器Nginx安装部署
- 1.View the Exhibit and examine the structure of the SALES, CUSTOMERS, PRODUCTS, and TIMES tables.
- vmware克隆出来的系统网卡无法启动问题
- 华为oj 字符串加解密