简介
1.1
定义函数的两种方式:
- 1、函数声明:函数声明提升,在执行代码之前会先读取函数声明,name属性值为function后的标识符(ie没有)
- 2、函数表达式:使用必须在定义之后,name属性值是空字符串
1.2 递归
function factorial(num){
if(num<=1){
return 1;
}else{
return num*factorial(num-1);
}
}
undefined
factorial(5);
//120
这是一个简单的递归表达式,此时,若是将函数引用替换将会发生错误
var newfunc = factorial;
factorial = null;
newfunc(5);//出现异常
解决方法有两种
- 1、使用arguments.callee,此指针会指向当前执行的函数
- 2、使用函数命名表达式
1.3 闭包
1.3.1 作用域链及其细节
当某个函数被调用时,会创建一个执行环境以及相应的作用域链。然后使用arguments和其它命名参数的值来初始化这个函数的活动对象。此时,作用域链的形式为参见下图
function compare(value1,value2){
if(value1 < value2){
return -1;
}else if(value1 > value2){
return 1;
}else{
return 0
}
}
var result = compare(5,10);
注意函数活动对象以及全局变量对象的的形式
1.3.2 变量对象
- 1、每个执行环境都有一个表示变量的对象(此对象包含此环境内的所有变量)—变量对象
- 2、全局环境的变量对象始终存在,函数的变量对象在函数接受后消失
- 3、创建函数 时,会创建一个预先包含全局环境的作用域链,被保存在内部属性[[Scope]]中
- 4、调用函数时,会创建一个执行环境,然后通过复制[[Scope]]属性值对象来构建作用域链,随后将活动对象(作为变量对象使用)推入执行环境作用域链的的前端
- 5、无论什么时候在函数中访问一个变量时,都会从作用域中搜索具有相同名字的变量。一般来讲,函数执行完毕后,局部的对象会被销毁,内存中仅保留全局执行环境变量对象
综述:函数在创建提供了作用域链的环境基础(函数的[[Scope]]属性),函数调用时利用变量对象构建起当前函数的作用域
1.3.3 闭包情形
- 当在一个函数A内部定义函数B时,会将A的活动对象添加到其作用域链
- 当A执行完之后,其活动对象不会被摧毁,而是一直保存在内存中,知道匿名函数被摧毁
闭包情形的作用域链如上图所示
1.3.4闭包与变量
- 闭包只能取得包含函数变量的最后一个值(显而易见,闭包是对外部变量对象的引用)
function createFunction(){
var result = new Array();
for(var i=0;i<10;i++){
result[i] = function(){return i}
}
return result;
}
var re = createFunction();
re[0]();
//10
上面是一个非常典型的例子。
- 1、外部函数 createFunction执行结束后,其内部变量(i)仍然存在于内存中。
- 2、闭包只取得了i的最后一个值 即 10.
要想返回正常的函数,只需要将i变为匿名函数的内部对象即可或者创建10个不同的变量
function createNiceFunction(){
var result = new Array();
for(var i=0;i<10;i++){
result[i] = (function(j){
//块级作用域
return function(){return j;};
})(i);
}
return result
};
var re = createNiceFunction();
re[1]();
//1
1.3.4 关于this对象
匿名函数的执行环境具有全局性,其this对象通常指向windows。这样理解 ,在函数里面定义变量时,如果不加上 var 那么这个变量为全局变量,这里的匿名函数也是如此。
若是想在闭包内使用当前的作用域,可以利用闭包的性质,外部定义this变量,然后在闭包内部引用
1.4 模仿块级作用域
javaScript中是没有块级作用域的
利用 匿名函数实现块级作用域 语法为 (function(){ 块级作用域在这里})();
这种写法就是一个直接执行函数;
使用:在需要使用临时变量或者私有作用域时,使用块级作用域
1.5 私有变量
任何函数中定义的变量都是私有变量
然后可以定义特权方法访问他们,类似java
function MyObject(){
var privateVariable = 10;//私有变量
function privateFunction(){//私有方法
return false;
}
this.publicMethod = function(){
privateVariable++;
return privateFunction();
};
}
var myobj = new MyObject();
myobj.publicMethod;
//ƒ (){
// privateVariable++;
// return privateFunction();
// }
var re = myobj.publicMethod();
re;
//false
1.5.1 单例(只有一个实例的对象)创建私有变量和特权方法
即创建对象时,将其放在块级作用域中 语法 var obj = function(){ 返回对象的代码,这里面为私有作用去 return onj}();