function基础知识
1. 函数的两部分
1.1 创建函数
- 语法:function函数名(形参){...}
- 过程:
- 创造值
- 开辟一个堆内存
- 把函数体中的代码当做字符串存在堆中
- 把对地址放到栈中
- 创造变量
- 让变量和地址关联
- 创造值
- 注意:只创造函数,其实就是创造了一个存储一堆字符串的堆而已,并没有实际作用
1.2 执行函数
- 语法:函数名(实参)
- 目的: 把创造的函数执行(把函数体中的代码执行)
- 依赖条件:
- 栈内存
- 供代码执行的上下文
- 过程:
-
函数每一次执行
-
- 创造一个全新的执行上下文,把执行上下文压缩到栈内存中去执行(进展执行)
-
- 在这个上下文中,也存一个AO(变量对象),用来存储当前上下文代码执行中所创建的变量
- 这些变量是“私有变量”
- 除当前上下文可以使用这些变量的值,上下文以外的环境不能直接使用私有变量的值
-
- 代码执行
-
- 当上下文中的代码都执行完后,如果该上下文中的信息没有被外界占用的情况,则执行完出栈(释放掉,减少栈内存中的空间)
-
2. 参数形式
2.1 形参与实参
-
形参:
- 创造函数的时候,我们并不清楚需要处理的数据是什么,只有当函数执行的时候,我们才会知道,此时我们需要定义相应的入口
- 入口在js函数中被称为形参,“用来存储执行函数时,传递进来的信息的”(所以形参是变量)
-
实参:
- 函数执行的时候,传递进来的值会复制给形参变量
- 传递的具体值在js函数中被称为实参,“实参就是具体传递的值”
-
形参与实参关系:
- 1.设定形参变量,但是执行的时候没有传递对应的值,则形参默认值是underfined
- 2.形参只有两个,实参有三个时,则第三个实参并没有对应的形参接受(但是传递给函数了)
-
注意:
- 形参是创造函数时候设定的变量
- 形参是变量
- 实参是执行函数时候给的形参传递的具体值
- 实参是值
- sum(1===1?“OK”:“NO”)
- 需要先把三元运算的结果作为实参传递给形参
- 形参是创造函数时候设定的变量
2.1 arguments
-
定义:
- 函数内置的实参集合
- 不管我们什么时候设置形参,或是否传递了实参,arguments始终都会存在
- 只能出现在函数中
-
形式:
- arguments是一个类数组集合
- 类似数组,但不是数组,和元素集和HTMLCollection类似
-
原理:
- 根据索引记录了每一个传递进来的实参信息
- arguments中包含了所有传递进来的实参信息
- length属性代表传递实参的个数
3.返回值return
-
定义:
- 如果,外面想用当前上下文中的一些私有信息,则需要函数提供对应的出口,把信息提供给外面使用,而这个出口在js函数中被称为“返回值return”
-
作用:
- 基于return把变量的值暴露给外面使用
- 在外边创建一个变量,用来接受函数执行返回的值(也就是return后面的值)
- 告知函数体重下面代码不再执行
- 基于return把变量的值暴露给外面使用
-
注意:
- return后面放的一定是变量
- 例如:
- console.og(sum)
- 这里输出的是sum函数本身
- sum=函数
- console.log(sum())
- 代表让函数执行
- 这里输出的是函数的返回值
- 如果函数中没有写return,默认返回值是underfined
- console.og(sum)
4. 函数表达式
-
实名函数:有函数名的
-
匿名函数:
-
- 函数表达式
- 把一个函数当做值赋值给变量
- 事件绑定
-
- 自执行函数
- 函数创建完后就立即执行了
- 语法规范
- (function(n){...})(实参)
- +function(n){...} (实参)
- -function(n){...} (实参)
- ~function(n){...} (实参)
- |function(n){...} (实参)
-
-
箭头函数
- let func=(x,y)=>{...}:
5.函数的作用域
5.1 全局作用域
- 全局作用域是最大的作用域,包含了局部作用域。在全局作用域中定义的变量可以在如何地方使用
- 全局作用域在页面打开的时候创建,页面关闭时才会销毁
- 编写在 script 标签中的变量和函数,作用域为全局,在页面的任意位置都可以访问到
- 在全局作用域中有全局对象window ,代表一个浏览器窗口,由浏览器创建,可以直接调用
- 全局作用域中声明的变量和函数会作为window对象的属性和方法保存
//下面两个变量都是存在全局作用域下面的,都是可以在任意地方使用的
var num1 = 100;
var num2 = 200;
console.log(window.num1) // 100
console.log(window.num2) // 200
5.2 局部作用域
- 局部作用域就是在全局作用域下面,开辟出来的一个相对小一些的作用域。在 js 中只有函数能生成一个局部作用域,别的不行, 在局部作用域中定义的变量只能在这个局部作用域内部使用
- 调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁
- 每调用一次函数就会创建一个新的函数作用域,他们之间是相互独立的
// 这个 num 是一个全局作用域下的变量 在任何地方都可以使用
var num = 100;
function fn(){
//下面这个变量就是一个 fn 局部作用域内部的变量
//只能在 fn 函数内部使用
var num2 = 200;
}
fn();
6. 作用域上下级
- 有了作用域以后,变量就有了使用范围,也就有了使用规则
6.1 变量定义机制
- 一个变量(函数)
- 定义在哪一个作用域里面
- 只能在当前作用域或下级作用域里使用
- 上一级作用域不能使用
// 全局作用域下的 a
var a = 100;
function fn(){
// 局部作用域下的 b
var b = 200;
}
fn();
console.log(a); // 100
console.log(b); // 报错:b is not defined
6.2 变量使用机制(作用域链)
- 当你需要使用一个变量(函数)
- 首先,在自己的作用域内部查找,如果有,就直接拿来使用
- 如果没有,就去上一级作用域查找,如果有,就拿来用
- 如果没有,就进行去上一级作用域查找,以此类推
- 如果一直到全局作用域 window 都没有这个变量,那么就会直接报错(该变量 is not defined)
var num = 100;
function fn(){
var num2 = 200;
function fun(){
var num3 = 300;
//自己fun函数作用域里面有,直接拿过来用
console.log(num3);
//自己作用域内没有,就去上一级,就是 fn 的作用域里面找,发现有,拿过来用
console.log(num2);
//自己这没有,去上一级 fn 那里也没有,再上一级到全局作用域,发现有,直接用
console.log(num);
// 自己没有,一级一级找上去到全局都没有,就会报错
console.log(a);
}
fun();
}
fn();
- 变量的使用机制也叫做作用域的查找机制
- 作用域的查找机制只能是向上找,不能向下找
6.3 变量赋值机制
- 当你想给一个变量赋值的时候,那么就先要找到这个变量,在给他赋值
- 变量赋值规则:
- 先在自己作用域内部查找,有就直接赋值
- 没有就去上一级作用域内部查找,有就直接赋值
- 在没有再去上一级作用域查找,有就直接赋值
- 如果一直找到全局作用域 window 都没有,那么就把这个变量定义为全局变量,在给他赋值(不会报错)
function fn(){
// 声明私有变量 num ,只能在 fun 内部使用,fun 外面不能用
var num1 = 100;
console.log(num1); // 100
}
fn();
console.log(num1); // 报错
function fun(){
// 声明私有变量 num ,只能在 fun 内部使用,fun 外面不能用
num2 = 200;
console.log(num2); // 200
}
fun();
console.log(num2); // 200
// 全局变量 num
var num;
function fn(){
var num;
function fun(){
// 不声明,只赋值
num = 100;
}
console.log(num); // undefined
fun(); // 这个函数执行完后,才给 fn 私有变量 num 赋值
console.log(num); // 100
}
/*fun 调用以后,要给 num 赋值
查看自己的作用域内部没有 num 变量
就会向上一级查找,上一级 fn 有 num 变量
那么就会把 num 赋值给 fn 下的 num 变量
赋值后的 num,由于是 fn 的私有变量,所以不会再给全局变量的 num 赋值了
*/
console.log(num); // undefined
fn();
console.log(num); // undefined
7. 作用域预解析
具体用法见预解析
7.1 全局预解析
- 会在页面打开的时候就进行了
- 只解析属于全局的内容
// 刚打开页面
var a = 100; // 会被解析
function fn(){ // 会被解析
var b = 200;// 不会被解析
}
7.2 局部预解析
- 当函数执行的时候进行预解析
- 函数内部的预解析,只属于函数内部
// 刚打开页面
var a = 100; // 会被解析
function fn(){ // 会被解析
var b = 200;// 等函数执行后,才会被解析
}
fn(); // 此时函数执行了,开始解析函数内部