9.js基础--函数重要概念
1.匿名函数
定义函数时,不使用任何变量引用的函数;
1.为何使用:使用匿名函数,可以节省内存空间,使用完毕以后立刻释放。
2.何时使用:如果一个函数只使用一次
3.如何使用:
1>自调: 创建完函数立刻执行
(function (){console.log("aaa")})() // aaa
(function(date){console.log(date.toGMTString())})(new Date())
//Wed, 15 Mar 2017 07:13:44 GMT
2>回调: 将函数传给另一个函数使用
arr.sort(function(a,b){return a-b});
2.函数重载
js中实际上不存在重载的概念,因为js中不支持同时包含多个同名函数,最后定义的同名函数会覆盖之前定义的。但一个函数可以通过不同的参数列表(类数组对象arguments)来实现各个功能,我们称之为函数重载。
传统方式1;
var overrideMethods = function(){
switch (arguments.length){
case 0 :
console.log("class no body");
break;
case 1:
console.log("class has one body");
break;
case 2:
console.log("class has two body");
break;
}
}
overrideMethods(); //class no body
overrideMethods("wu"); //class one body
overrideMethods("wu","li"); //class two body
3垃圾回收
清除不再使用的对象,释放存储空间。
垃圾回收进程器:是一个专门负责释放不再使用的对象的小程序。js引擎自带,自动执行,后台程序。
垃圾回收的原理:(对象的生命周期)
1.创建一个对象时,垃圾回收器会标记该对象的引用计数器为1;
2.使用对象的过程中,只要多一个变量引用该对象,计数器就+1;
3.主动为一个变量赋值为null时,就释放了该变量对对象的引用。计数器就-1;
4.如果一个对象不在被任何变量引用,计数器就变为0.垃圾回收就释放对象。
在使用完一个较大的对象后,都要主动用null释放对该对象的引用。
4.函数的生命周期
1.当程序开始执行时:创建一个 Execution Context Stack(ECS 执行环境栈),创建全局作用域对象 ,在ECS中压入第一个全局执行环境EC,全局EC引用window;
2.当定义函数时:(就是定义函数对象,封装函数定义)在函数对象中,设置scope属性,引用函数来自的作用域,通常scope都是window
3.创建一个活动的对象Actived Object(AO),向ECS中压入本次函数调用的执行环境EC,EC的scope chain引用AO。
4.当函数调用结束后,EC出栈,导致AO无EC引用,被释放。
1.ECS(执行环境栈):保存正在调用的函数的执行环境的栈结构
2.AO(活动对象):保存函数的局部变量的函数作用域对象。
结论:
1.单线程
2.同步执行,只有栈顶的上下文处于执行中,其他的上下文需要等待
3.全局上下文只有唯一的一个,他在浏览器关闭的时候出栈
4.执行上下文的个数没有限制
5.每次某个函数被调用,就会有新的执行上下文为其创建,即使调用的自身函数,也是如此。
5.作用域和作用域链
作用域:一个变量的使用范围
window是全局作用域,AO对象是函数作用域,AO对象引用着window对象
作用域链:由各级作用域对象,逐级引用形成的链式结构,就是作用域链,作用域链的末尾是window对象。
作用域链控制着变量的使用顺序:
1.优先使用AO中的局部变量;
2.如果AO中没有,就延作用域链向下找
3.如果到window对象仍然没找到,就报错。
6.闭包
重用变量,保护变量不受污染的机制。
如何使用:
1.用外层函数将受保护的变量和操作变量的函数封装在内部。
2.外层函数将内层函数返回
3.调用外层函数,获得返回的内层函数对象。
function f1(){
var n = 999;
function f2(){
alert(n); //内层函数操作受保护的变量
}
return f2;
}
var result = f1(); //result 为 f2()
result(); //999
函数执行时,首先创建一个ECS,全局作用域入栈,遇到可执行代码 var result = f1();
f1()的EC入栈,执行结束以后 return f2;并赋值给result,此时变量result 指向f2();f1()执行结束出栈,继续执行代码,result()的EC入栈,执行代码,结束后出栈。
注意:函数中,遇到return 能直接终止可执行代码的执行,因此会直接将当前EC弹出。