# 函数

## 函数

//Named functionfunction add(x, y) {    return x+y;}//Anonymous functionvar myAdd = function(x, y) { return x+y; };

var z = 100;function addToZ(x, y) {    return x+y+z;}

## 函数类型

### 给函数添加类型

function add(x: number, y: number): number {    return x+y;}var myAdd = function(x: number, y: number): number { return x+y; };

### 书写函数类型

var myAdd: (x:number, y:number)=>number =    function(x: number, y: number): number { return x+y; };

var myAdd: (baseValue:number, increment:number)=>number =    function(x: number, y: number): number { return x+y; };

### 推断类型

// myAdd has the full function typevar myAdd = function(x: number, y: number): number { return x+y; };// The parameters 'x' and 'y' have the type numbervar myAdd: (baseValue:number, increment:number)=>number =    function(x, y) { return x+y; };

## 可选参数和默认参数

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

function buildName(firstName: string, lastName?: string) {    if (lastName)        return firstName + " " + lastName;    else        return firstName;}var result1 = buildName("Bob");  //works correctly nowvar result2 = buildName("Bob", "Adams", "Sr.");  //error, too many parametersvar result3 = buildName("Bob", "Adams");  //ah, just right

function buildName(firstName: string, lastName = "Smith") {    return firstName + " " + lastName;}var result1 = buildName("Bob");  //works correctly now, alsovar result2 = buildName("Bob", "Adams", "Sr.");  //error, too many parametersvar result3 = buildName("Bob", "Adams");  //ah, just right

function buildName(firstName: string, lastName?: string) {

function buildName(firstName: string, lastName = "Smith") {

## 剩余参数

function buildName(firstName: string, ...restOfName: string[]) {  return firstName + " " + restOfName.join(" ");}var employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

function buildName(firstName: string, ...restOfName: string[]) {  return firstName + " " + restOfName.join(" ");}var buildNameFun: (fname: string, ...rest: string[])=>string = buildName;

## Lambdas和’this’的使用

JavaScript中的函数在被调用时会设置一个’this’变量。虽然这个特性强大而又灵活，但使用这个特性却需要我们时刻关注函数执行的环境。举例来说，当我们在回调函数上执行一个函数时，这个函数的上下文环境就会变得难以预料。

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);

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);

## 重载

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);

var suits = ["hearts", "spades", "clubs", "diamonds"];function pickCard(x: {suit: string; card: number; }[]): number;function pickCard(x: number): {suit: string; card: number; };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);