函数的定义方式:1.函数声明;2.函数表达式 两种
函数生命提升 function declaration hoisting (执行代码之前会先读取函数声明)
匿名函数 anonymous[əˈnɑ:nɪməs] function
1.arguments.callee是一个指向正在执行的函数的指针,可以用在递归函数中。
命名函数表达式 var func=(functon f(num){…})
2.闭包:有权访问另一个函数作用域中的变量的函数。常见方式是在一个函数内部创建另一个函数。
在创建函数时会1.创建一个预先包含全局变量对象的作用域链(保存在内部的[[Scope]]属性中)——被调用时2.会创建一个执行环境(execute context)——3.及相应的作用域链()(复制函数的[[Scope]]属性中的对象构建起执行环境的作用域链)——4.然后使用arguments和其他命名参数的值来初始化函数的活动对象(activation object)(在此作为变量对象使用,会被推入执行环境作用域链的前端)。——在作用域中,外部函数的活动对象始终处于第二位。
后台的每个执行环境都有一个表示变量的对象——变量对象。全局的变量对象始终存在,而函数这样的局部环境的变量对象只在函数的执行过程中存在。一般讲,当函数执行完毕后局部活动对象就会被销毁。
由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,谨慎使用闭包。
2.1 闭包与变量
2.2 关于this对象
匿名函数的执行环境具有全局性
每个变量在被调用时都会自动取得两个特殊变量:this和arguments。
2.3 内存泄漏
function assignHandler(){
var element = document.getElementById("");
element.onclick = function(){
alert(element.id);
}
}
这个闭包创建了一个循环引用,由于匿名函数保存了一个对assignHandler()的活动对象的引用,因此就会导致无法减少element的引书。element占用的内存不会被收回。
function assignHandler(){
var element = document.getElementById("");
var id = element.id;
element.onclick = function(){
alert(id);
}
element = null;
}
闭包会引用包含函数的整个活动对象(包含作用域中的所有变量),而其中包含element。即使闭包不直接引用element,包含函数的活动对象中也仍然会保存一个引用,因此必须把element变量设置为null.
3.模仿块级作用域
(function(){
//这里是块级作用域
})()
4.私有变量(函数的参数、局部变量、函数内部定义的其他函数)
有权访问私有变量和私有函数的公有方法称特权方法(privileged method)
第一种创建特权方法的方式:在构造函数中定义特权方法。基本模式如下
function MyObject(){
//私有变量
var privateVariable = 10;
//私有函数
function privateFunction(){
return false;
}
//特权方法
this.publicMethod = function(){
privateVariable ++;
return privateFunction();
}
}
缺点:使用构造函数模式,针对每一个实例都会创建同样一组方法。
利用私有和特权函数,可以隐藏那些 不应该被直接修改的数据。
4.1静态私有变量
第二种创建特权方法的方:使用静态私有变量来实现特权方法。
(function (){
//私有变量
var privateVariable = 10;
//私有函数
function privateFunction(){
return false;
}
//构造函数
MyObject = function(){
}
//公有/特权方法
MyObject.prototype.publicMethod = function(){
privateVariable ++;
return privateFunction();
}
})();
缺点:私有变量在这种模式下变成了静态的、由所有实例共享的属性。
多查找作用域链中的一个层次,就会在一定程度上影响查询速度。这正是使用闭包和私有变量的明显不足之处。
4.2 模块模式
var singleton = function (){
//私有变量
var privateVariable = 10;
//私有函数
function privateFunction(){
return false;
}
return {
publicProperty : true;
publicMethod : function(){
privateVariable++;
return privateFunction();
}
}
}
如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有变量的方法,那么就可以使用模块模式。
4.3 增强的模块模式
var singleton = function (){
//私有变量
var privateVariable = 10;
//私有函数
function privateFunction(){
return false;
}
//添加特权/公有属性和方法
var object = new CustomType();
object .publicProperty : true;
object .publicMethod : function(){
privateVariable++;
return privateFunction();
}
return object
}