# JavaScript/子程序和对象

## 無參數的函數

```<script language="javascript">
function helloworld()
{
}
</script>
```

```helloworld();
```

```<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<TITLE>Some Page</TITLE>

<script language="javascript">
function helloworld()
{
}
</script>

<BODY>

<script lang="javascript">
helloworld();
</script>

</BODY>
</HTML>
```

## 帶參數的函數

```function addsubtract(thenumber)
{
if(thenumber>5){
thenumber--;
}
if(thenumber<5){
thenumber++;
}
return thenumber;
}
```

```function addsubtract(thenumber){......}
```

```if(thenumber>5){......}
```

```X>Y（如果X大於Y）
X<Y（如果X小於Y）
X>=Y（如果X大於或等於Y）
X<=Y（如果X小於或等於Y）
X==Y（如果X等於Y）
```

`thenumber--;`

`thenumber++;`

`return thenumber;`

```<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<TITLE>Some Page</TITLE>

<script language="javascript">
{
if(thenumber>5){
thenumber--;
}
if(thenumber<5){
thenumber++;
}
return thenumber;
}
</script>

<BODY>

<script language="javascript">
</script>

</BODY>
</HTML>
```

```var number = addsubtract(6);
```

## 函数概论

```// define a function
function <function_name> (<parameters>) {
<function_body>
}

// call a function
<variable> = <function_name> (<arguments>);
```

JavaScript支持函数式编程。函数派生自Object的一种数据类型。是头等公民。

## 函数声明

```"use strict";

// conventional declaration (or 'definition')
function duplication(p) {
return p + "! " + p + "!";
}

// call the function
const ret = duplication("Go");
```

Construction via a variable and an expression:

```"use strict";

// assign the function to a variable
let duplication = function (p) {
return p + "! " + p + "!";
};

const ret = duplication("Go");
```

```"use strict";

// using the 'new' constructor
let duplication = new Function ("p",
"return p + '! ' + p + '!'");

const ret = duplication("Go");
```

## 调用

```"use strict";

function duplication(p) {
return p + "! " + p + "!";
}

// the conventional invocation method
const ret = duplication("Go");
```

```"use strict";

function duplication(p) {
return p + "! " + p + "!";
}

// via 'call'
let ret = duplication.call(window, "Go");

// via 'apply'
ret = duplication.apply(window, ["Go"]);
```

```"use strict";

function duplication(p) {
return p + "! " + p + "!";
}

alert(duplication); // 'function duplication (p) { ... }'
```

### 提升

```"use strict";

// use a function above (in source code) its declaration
const ret = duplication("Go");

function duplication(p) {
return p + "! " + p + "!";
}
```

## 立即被调函数

```"use strict";

// declaration plus invocation
(function (p) {
return p + "! " + p + "!";
})("Go")   // ("Go"): invocation with the argument "Go"
);

// the same with 'arrow' syntax
((p) => {
return p + "! " + p + "!";
})("Gooo")
);
```

## 实参

### 传值调用

```"use strict";

// there is one parameter 'p'
function duplication(p) {
// In this example, we change the parameter's value
p = "NoGo";
return p + "! " + p + "!";
};

let x = "Go";
const ret = duplication(x);

// is the modification of the argument done in the function visible here? No.
alert("Return value: " + ret + " Variable: " + x);
```

```"use strict";

function duplication(p) {
p.a = 2;       // change the property's value
p.b = 'xyz';   // add a property
return JSON.stringify(p) + "! " + JSON.stringify(p) + "!";
};

let x = {a: 1};
const ret = duplication(x);

// is the modification of the argument done in the function visible here? Yes.
alert("Return value: " + ret + " Object: " + JSON.stringify(x));
```

```"use strict";

function duplication(p) {

// modify the reference by creating a new object
p = {};

p.a = 2;       // change the property's value
p.b = 'xyz';   // add a property
return JSON.stringify(p) + "! " + JSON.stringify(p) + "!";
};

let x = {a: 1};
const ret = duplication(x);

// is the modification of the argument done in the function visible here? No.
alert("Return value: " + ret + " Object: " + JSON.stringify(x));
```

### 缺省值

```"use strict";

// two nearly identical functions; only the signature is slightly different
function f1(a, b) {
alert("The second parameter is: " + b)
};

function f2(a, b = 10) {
alert("The second parameter is: " + b)
};

// identical invocations; different results
f1(5);        //   undefined
f1(5, 100);   //   100

f2(5);        //   10
f2(5, 100);   //   100
```

### 可变数量的实参

#### 单独检查

```"use strict";

function showName(firstName, familyName, academicTitle, titleOfNobility) {
"use strict";

// handle required parameters
let ret = "";
if (!firstName || !familyName) {
return "first name and family name must be specified";
}
ret = firstName + ", " + familyName;

// handle optional parameters
ret = ret + ", " + academicTitle;
}
if (titleOfNobility) {
ret = ret + ", " + titleOfNobility;
}

return ret;
}

```

#### “其余”参数

```"use strict";

// the three dots (...) introduces the 'rest syntax'
function showName(firstName, familyName, ...titles) {

// handle required parameters
let ret = "";
if (!firstName || !familyName) {
return "first name and family name must be specified";
}
ret = firstName + ", " + familyName;

// handle optional parameters
for (const title of titles) {
ret = ret + ", " + title;
}

return ret;
}

```

#### 'arguments'关键字

```"use strict";

function showName(firstName, familyName, academicTitles, titlesOfNobility) {

// handle ALL parameters with a single keyword
for (const arg of arguments) {
}
}

showName("Mike", "Spencer", "Ph.D.", "Duke");
```

## Return

```"use strict";

function duplication(p) {
if (typeof p === 'object') {
return;  // return value: 'undefined'
}
else if (typeof p === 'string') {
return p + "! " + p + "!";
}
// implicit return with 'undefined'
}

let arg = ["Go", 4, {a: 1}];
for (let i = 0; i < arg.length; i++) {
const ret = duplication(arg[i]);
}
```

## 箭头函数(=>)

```"use strict";

// original conventional syntax
function duplication(p) {
return p + "! " + p + "!";
}

// 1. remove keyword 'function' and function name
// 3. remove 'return'; the last value is automatically returned
(p) => {
p + "! " + p + "!"
}

// remove { }, if only one statement
(p) =>  p + "! " + p + "!"

// Remove parameter parentheses if it is only one parameter
// -----------------------------
p => p + "! " + p + "!"     // that's all!
// -----------------------------

(p => p + "! " + p + "!")("Go")
);
```

```"use strict";

const myArray = ['a', 'b', 'c'];

myArray.forEach(e => alert("The element of the array is: " + e));
```

## 递归调用

```"use strict";

function factorial(n) {
if (n > 0) {
const ret = n * factorial(n-1);
return ret;
} else {
// n = 0;  0! is 1
return 1;
}
}

const n = 4;