[TOC]
## 函數的形參與實參
### arguments是一個類數組
類數組的**類**意味著什么呢?
這意味著他們都有長度,都能夠被遍歷,它們是長成如下樣子的**對象**而不是數組
```
{
'0':'a'
,'1':'b'
,length:2
,? ifn(a,b,c)
,Symbol(Symbol.iterator):? values()
,__proto__:Object
}
```
但,畢竟只是相似,具有一些數組的特征,不是真正的數組,So他們**不在Array的原型鏈上**,不具有Array原型上的方法,也就是說所有數組獨有的方法這些類數組都不能夠使用。
#### 轉真·數組
- Array.prototype.slice.call(arguments);
- Array.from(arguments)
### 兩種獲取參數長度的方式
`fn.length` 和 `arguments.length`都能獲得一個函數的參數的長度,
但!`fn.length`拿到的是**形參**的長度,而`arguments.length`拿到的是所傳**實參**的長度,這兩個值不總是相等的,因為實際傳入的參數的個數可以大于或小于形參的個數。
```
function ifn(a,b,c){
console.log(arguments.length);
console.log(ifn.length);
}
ifn();
<<<
0
3
```
### 形參和arguments都指向實際的參數
下例中,實際傳入的第一個參數的值將會被修改,并且在arguments中得到顯示
```
function ifn(a,b,c){
console.log(arguments[0]);
a = 'x'; //實際傳入的第一個參數的值將會被修改,并且在arguments中得到顯示
console.log(arguments);
}
ifn(1,2,3)
<<<
1
{ '0': 'x', '1': 2, '2': 3 }
```
## 函數、剩余運算符與解構運算
### 函數與剩余
注意,若使用剩余運算符必須在形參的末尾處使用
```
function sum(zero,...args){
return currency+eval(args.join('+'));
}
sum (0,1,2,3,4,5,6)
```
### 函數與解構
對象作為實參可在形參處被解構
```
function ajax({url=new Error('url不能為空'),method='get'}){
...
}
ajax({url:'/test',method:'get'});
```
但并不支持解構數組
```
let fn1 = function(...args){
console.log(args)
};
fn1([1,2,3])
<<<
[ [ 1, 2, 3 ] ]
//--- --- ---
let fn1 = function(a,b,c){
console.log(a)
};
fn1([1,2,3])
<<<
[1,2,3]
```
## Function
### 用字符串創建一個函數
此種創建函數的方式常常和模板拼接一起配套使用,讓我們能夠更自由的創建函數
```
let strFnBody = `if(arg1)console.log('參數存在')`;
let fn = Function('arg1','arg2',...,strFnBody);
fn(); //執行函數
```
### 所有函數們的粑粑
所有函數都是Function函數的實例
```
let fn1 = function(){};
console.log(fn1.__proto__ === Function.prototype)
<<<
true
```
## 箭頭函數
### 箭頭函數木有arguments
替代方案是利用剩余運算符,嘿,我們得到了還是一個真·數組
```
(...args)=>{
console.log(args);
}
<<<
[ 1, 2, 3 ]
```
其次雖然沒有arguments,我們仍然能通過`fn.length`來拿到形參的個數
```
let arrow = (a,b,c)=>{
console.log(arrow.length)
}
arrow(1,2,3);
<<<
3
```
### 箭頭函數木有this
```
let obj = {
fn:function(){
console.log(this);
}
}
let fn = obj.fn;
fn(); //global||window
obj.fn(); //obj
//--- --- ---
let obj = {
fn:()=>{
console.log(this);
}
}
let fn = obj.fn;
fn(); //本模塊的最頂層的this window||{}
obj.fn(); //因為箭頭函數不再有this會往上找,如果是nodejs會找到{},如果是瀏覽器會找到window
```
當一個函數本身沒有this時(箭頭函數),那么**誰調用的函數this就指向誰這句話就不再適用**,它會查找上級作用域的this是指向誰。而又因為Node.js中,最頂層的作用域(模塊作用域)的this指向的是`{}`(空對象),故上栗中會指向{}。(注意Node.js中文件模塊的this并不指向全局對象global,而瀏覽器是指向window全局對象的)
## 函數作用域鏈的查找
函數作用域鏈的查找 是順著【函數定義時】所處的作用域來查找的
```
let b = '123'
function bbb(){
console.log(b)
}
(function(){
let b = 'bbb';
bbb(); //123
})();
```