目录
函数
定义
组成形式
递归
立即执行函数
作用域
变量作用域
函数作用域[[scope]]
作用域链
预编译
JS运行分三步:
预编译执行分五步:
函数
原则:高内聚弱耦合(重复)
函数声明(用function声明函数)
函数表达式
三种定义方式:
function test(){
document.write('abc');
}
test();//定义完函数,调用才能执行。
// 命名函数表达式,忽略名字,没什么用。
var test = function abc() {
document.write('123');
}
test();
// 匿名函数表达式,最常用。
var test = function() {
document.write('123');
}
test();
函数名称
多个单词拼接单词,小驼峰规则,第一个单词小写,后面单词第一个字母大写。
参数
形参(函数定义时的参数)
实参(调用的时候实际传的参数)
不用声明参数数据类型,实参形参数量不对应也不会报错,有几个用几个。不定参(不给定形参数量)用的最多。
返回值
return ;终止函数(后面的语句不执行),返回值。
特别复杂的程序别用递归,程序执行很慢,比for循环唯一的好处只是代码简洁一点。
1.找规律
2.找出口
//n的阶乘
function mul(n) {
if (n == 1) {
return 1;
}//递归的出口,一个递归到最后的已知子单元。
return n * mul(n - 1);
}
mul(3);
立即执行函数
很多函数只会用一次,之后一直在等待执行浪费内存空间,而立即执行函数执行完就会把函数立即删除,之后调用也找不到。
主要用于初始化功能的函数。
基本形式:(function (){}())
其它方面与普通函数无任何区别,有执行期上下文,要预编译等等。
var mum=(function (a,b,c){
var d=a+b+c;
console.log(d);
}(1,2,3));
结果为6。
作用域
变量和函数生效的区域
全局变量:函数外面的变量是全局变量,函数里函数外都能访问
局部变量:函数里面的变量是局部变量,函数外无法调用,相对而言的,函数里面的函数可以访问外层函数的局部变量。
作用域的访问顺序:简而言之就是,里面的可以访问外面的,外面的不能访问里面的,平级的局部变量不能相互访问。
全局函数,局部函数同理,写在函数里面还是函数外面的函数。
全局对象和全局变量的关系
1.任何变量未经声明就赋值,则此变量为全局对象(window)所有。a = 10;
2.一切声明的全局变量,全是window的属性,window就是全局的域。
var a = 123;
window.a=123;
每个javascript函数都是一个对象,对象中有的属性可以访问,有的不能,这些属性仅供javascript引擎存取,如[[scope]]。
[[scope]]就是函数的作用域,其中存储了执行期上下文的集合。
执行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象(AO)。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行期上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行期上下文,当函数执行完毕,它所产生的执行上下文被销毁。
[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们称这种链式链接为作用域链。查找变量时,要从作用域链的顶部开始查找。Activation Object(AO)到Global Object(GO)。
原理图解:
例子:
由上到下时间执行过程:
预编译
语法分析(通篇扫描是否有语法错误),预编译(发生在函数执行的前一刻),解释执行(一行行执行)。
一、创建AO对象(Activation Object 执行期上下文)
二、找形参和变量声明,将变量和形参名作为AO属性名,值为undefined.
变量声明提升(变量放到后面也不会报错,只是未定义类型)如:console.log(a);var a=10;结果undenfined;
三、将实参值和形参统一(传参)
四、在函数体里面找到函数声明{函数声明整体提升(相当于放到程序最前面)}
五、值赋予函数体,执行(声明函数和变量的部分直接不看了)
了解编译步骤后,当函数名,变量名等同名的时候,也可以不混淆。