1. 参数默认值
- ES6新特性,老版本浏览器(IE8)不支持
- 参数的默认值,未设置时,为undefined
- 形参默认值设置
function(a = 1, b = 2) {};
参数值的映射:
- 对于某一个参数,若默认值和传入的实参值都为undifined,才为undefined
- 若其中一个不是undefined,则使用该值
- 若两个都不为undefined,则使用实参值
function test (a = 1, b) {
//...
}
// 要求:a保持默认值,b=2
test(undefined, 2);
// ES5
function test(a, b) {
// var a = arguments[0] || 1;
// var b = arguments[1] || 2;
var a = typeof(arguments[0]) === 'undefined' ? 1 : arguments[0];
var b = typeof(arguments[1]) === 'undefined' ? 2 : arguments[1];
console.log(a, b)
}
2. 递归
函数自己调用自己
- 两大要素
- 规律
- 出口
案例1. 求n的阶乘
function factorial(n, f) {
if(n < 0) throw new Error("参数必须大于或等于0")
if(n === 1 || n === 0) return 1;
return n * factorial(n - 1);
}
案例2. 求第n位斐波那契数列的值
function fibonacci(n) {
if(n < 0) throw new Error("参数必须大于或等于0")
if(n === 0) return 0;
if(n === 1) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
3. 预编译
3.1 预编译在JS引擎工作流程中的位置
- 先通篇检查语法错误 SyntaxError
- 预编译
- 解释一行,执行一行
3.2 函数 vs 变量
- 函数声明赋值整体提升
- 变量只有声明提升,赋值不提升
3.3 暗示全局变量 imply global
在全局,无论是否使用var声明,变量都定义在window对象上 var a; // a = window.a
function test() {
var a = b = 1;
}
test();
console.log(b); // -> 1; b 并没有在test()内部声明
console.log(a); // -> ReferenceError
3.4 函数预编译 与 执行期上下文-AO
函数预编译步骤:
- 创建AO对象 (activation object ,执行期上下文/函数上下文)
AO = {}
- 寻找函数的形参和变量声明
- 把实参值赋给形参
- 寻找函数声明,赋值函数体
- 逐行执行函数代码,预编译执行过的代码行直接跳过
例1:
```javascript function test(a) { console.log(a); // -> function a(){} var a = 1; console.log(a); // -> 1 function a(){}; // skip console.log(a); // -> 1 console.log(b); // -> undefined var b = function(){}; console.log(b); // -> function(){} function d(){}; // skip }
test(2);
AO = { a: undefined -> 2 -> function a(){} -> 1, b: undefined -> function(){}, d: function d(){}, }
<a name="HbJDZ"></a>
#### 例2:
```javascript
function test(a, b) {
console.log(a); // -> 1
c = 0;
var c;
a = 5;
b = 6;
console.log(b); // -> 6
function b(){};
function d(){};
console.log(b); // -> 6
}
test(1);
console.log(a, b, c);
AO = {
a: undefined -> 1 -> 5,
b: undefined -> function b(){} -> 6,
c: undefined -> 0,
d: function d(){}
}
3.4 全局预编译 与 全局上下文-GO
全局预编译的步骤:
- 创建GO对象 (global object ,全局上下文/函数上下文)
GO = {}
- 寻找变量声明 var
- 寻找函数声明 function
- 逐行执行代码,预编译执行过的代码行直接跳过
例1:
var a = 1;
function a() {
console.log(2);
}
console.log(a); // -> 1
GO = {
a: undefined -> function a(){} -> 1
}
3.5 综合 GO & AO
例1:
function test() {
var a = b = 1;
}
test()
GO = {
b: 1
}
AO = {
a: undefined -> 1
}
例2:
var b = 3;
console.log(a); // -> function a(a){...}
function a(a) {
console.log(a); // -> function a() {}
var a = 2;
console.log(a); // -> 2
function a() {}
var b = 5;
console.log(b) // -> 5
}
a(1);
GO = {
b: undefined -> 3;
a: function a(a){...}
}
AO = {
a: undefined -> 1 -> function a() {} -> 2,
b: undefined -> 5
}
例3:
a = 1;
function test(){
console.log(a); // undefined
a = 2;
console.log(a); // 2
var a = 3;
console.log(a); // 3
}
test();
var a;
GO = {
a: undefined -> 1,
test: function test(){...}
};
AO = {
a: undefined -> ,
}
例4:
function test() {
console.log(b); // -> undefined
if(a) {
var b = 2;
}
c = 3;
console.log(c); // -> 3
}
var a;
test();
a = 1;
console.log(a); // -> 1
GO = {
a: undefined -> 1,
test: function test() {},
c: 3
}
AO = {
b: undefined,
}
例5:
function test() {
return a;
a = 1;
function a(){};
var a = 2;
}
console.log(test());
AO = {
a: undefined -> function a() {},
}
GO = {
test: function test() {},
}
例6:
function test() {
a = 1;
function a() {};
var a = 2;
return a;
}
console.log(test());
GO = {
a: 1,
}
AO = {
a: undefined -> function a() {} -> 1 > 2
}
例7:
a = 1;
function test(e) {
function e() {}
arguments[0] = 2;
console.log(e); // -> 2
if(a) {
var b = 3;
}
var c;
a = 4;
var a;
console.log(b); // -> undefined
f = 5;
console.log(c); // -> undefined
console.log(a); // -> 4
}
var a;
test(1);
console.log(a); // -> 1
console.log(f); // -> 5
GO = {
a: undefined -> 1,
test: function test() {},
f: 5
}
AO = {
e: undefined -> 1 -> function e() {} -> 2,
b: undefined,
c: undefined,
a: undefined -> 4,
}