# 参数相关

# 默认参数

// 只要当 参数的值为 undefined 时使用默认值
function makeRequest(url, timeout = 2000, callback) {
  
}

// 使用 timeout 的默认值
makeRequest('/foo', undefined, function(){}) 
makeRequest('/foo') 

// 不使用 timeout 的默认值。 null是一个合法值。 
makeRequest('/foo', null) 

# 默认参数在调用时求值

function getValue() {
  return 5;
}

// 传入的是 getValue(), 并且只在 add 调用时执行。
function add(first, second = getValue()) {
  return first + second;
}

add(1)

# 默认参数存在临时死区,即要先声明在使用

// second 未声明就使用,调用 add (undefined, 1)报错
function add(first = second, second) {
  return first + second;
}

// 调用 add (undefined,1)报错想当于
let first = second;
let second = 1;

# 不定参数

  1. 每个函数最多只有一个不定参数
  2. 不定参数放在所有参数末尾
  3. 不定参数为数组
function pick(object, ...rest) {
  
}

function checkArgs(...args) {
  
}

# 使用 展开运算符 传参, 可以简化使用数组给函数传参

不定参数可以让你指定多个独立的参数,并通过整合后的数组来访问;

而展开运算符可以让你指定一个数组,将它们打散后作为各自独立的参数传入函数。

// es5
let values = [25, 50, 75, 100]; 
Math.max.apply(Math, values);
// es6
let values = [25, 50, 75, 100]; 
Math.max(...values);

# 函数的 name 属性

  • 函数声明
  • 函数表达式 (变量名)
  • getter setter(get set 前缀 + 方法名)
  • bind函数 (bound 前缀 + 调用方法名)
  • New Function (anonymous)
function doSomething() {
  
}
console.log(doSomething.name) // "doSomething"

# 函数如何被调用

函数有两个不同的内部方法 [[Call]] , [[Construct]]

[[Construct]]负责

  1. 创建实例对象
  2. 执行函数体
  3. 绑定this为实例对象

[[Call]]负责

  1. 执行函数体

当通过new调用时,执行的是[[Construct]]方法。否则执行的是 [[Call]]

具有[[Construct]]方法的函数被称为构造函数。 箭头函数没有[[Construct]]方法。

使用 new.target是否被赋值 判断函数是否通过new调用

# 箭头函数

  1. 没有this,super,arguments,new.target

    这些值有外围最近一层的非箭头函数决定。

  2. 不能通过new调用

  3. 没有原型

  4. 不能改变this

  5. 不支持arguments对象

  6. 不知道重复的命名参数

# 尾调用优化