函数
创建函数
ECStack:(执行函数栈) 浏览器打开后只有一个栈内存
EC(G): 全局执行上下文
VO(G): 全局变量对象
函数和对象都是引用数据类型,创建函数的经历的三个步骤如下:
- 创建一个函数类型的值(引用数据类型)
- 开辟一个16进制的堆内存
- 把函数体中的代码当作”字符串“存储近去
- 把地址存放在栈内存中
- 创建变量(函数名)
- 关联
在VO(G)中进行,但是VO(G)在EC(G)里, EC(G)在ECStack里
为什么要执行函数
常见函数只是按照普通存储对象的方法,把函数体存储在堆内存中,如果不调用,它就是一对没有任何意义的字符
console.log(func)//这里输出的是函数体字符串
执行函数
EC(FUNC): func函数的执行上下文
AO(FUNC): 当前上下文中的变量对象
函数每一次执行:
- 创建一个全新的执行上下文EC(FUNC),把执行上下文压到栈内存中执行
- 在这个执行上下问中,也存在变量对象AO(FUNC),用来存储当前上下文中代码执行所创建的变量
… - 代码执行
… - 当上下文中的代码执行完后,如果该上下文中的信息没有被外边占用,则出栈(以此机制减少栈内存的占用)
ARGUMENTS
- arguments是一个类数组集合,和元素集合HTMLCollection类似
- 根据索引记录了每一个传递进来的实参信息(和是否定义形参没有关系。arguments中包含了所有传递进来的实参信息)
- length属性代表了实参的个数
- 箭头函数没有
练习题:任意数求和,不论个数和数的形式
// Solution1
function sum() {
let total = 0;
for (let i = 0; i < arguments.length;i++) {
let item = Number(arguments[i]);
if (!isNaN(item)) {
total += item;
}
}
console.log(total);
}
// Solution 2
function sum(...args) {
let total = 0;
for (let i = 0; i < args.length; i++) {
let item = Number(args[i]);
if (!isNaN(item)) {
total += item;
}
}
console.log(total);
}
sum(0);
sum(0, 2);
sum(0, 2, "a");
sum(0, 2, "a", '4');
RETURN
- 如果一个函数没有返回值,输出就是undefined(显而易见🤷♂️)
- return;经常用这个终止函数执行
匿名函数
函数表达式
把一个函数当作值赋值给变量或事件绑定
// 事件绑定
document.body.click = function () {};
// 赋值 fun和function fn类似,但是有区别
let fn = function () {};
自执行函数
函数创建完就立即执行
(function(n){})(100);//n会被赋值为100
箭头函数
箭头函数的简化
function func(x) {
return function (y) {
return x + y;
}
}
// 使用箭头函数简化
let func = x => y => x + y;