一、创建函数的几种方式
1、声明函数
最普通最标准的声明函数方法,包括函数名及函数体。
function fn1(){}
2、创建匿名函数表达式
创建一个变量,这个变量的内容为一个函数
var fn1 = function(){}
注意采用这种方法创建的函数为匿名函数,即没有函数name
var fn1 = function (){};
3、创建具名函数表达式
创建一个变量,内容为一个带有名称的函数
var fn1 = function frankName(){};
注意:具名函数表达式的函数名只能在创建函数内部使用
即采用此种方法创建的函数在函数外层只能使用fn1不能使用frankName的函数名。frankName的命名只能在创建的函数内部使用测试:
varfn1=function frankName(){
console.log("in:fn1<",typeoffn1,">frankName:<",typeof frankName,">");
};
console.log("out:fn1<",typeoffn1,">frankName:<",typeof frankName,">");
fn1();
//out:fn1< function >frankName:<undefined>//in:fn1< function >frankName:< function >
可以看到在函数外部(out)无法使用frankName的函数名,为undefined。
注意:在对象内定义函数如var o={ fn : function (){…} },也属于函数表达式
4、Function构造函数
可以给Function构造函数传一个函数字符串,返回包含这个字符串命令的函数,此种方法创建的是匿名函数。
5、自执行函数
(function(){alert(1);})();
(functionfn1(){alert(1);})();
自执行函数属于上述的“函数表达式”,规则相同
6、其他创建函数的方法
当然还有其他创建函数或执行函数的方法,这里不再多说,比如采用eval,setTimeout,setInterval等非常用方法,这里不做过多介绍,属于非标准方法,这里不做过多展开
二、函数作用域链的问题
问题:在函数表达式内部能不能访问存放当前函数的变量?
测试1,对象内部的函数表达式:
var o = {
fn:function(){
console.log(fn);
}
};
o.fn();//ERROR报错
测试2,非对象内部的函数表达式:
var fn = function(){ console.log(fn);};
fn();
//function (){console.log(fn);};正确
总结:使用var或是非对象内部的函数表达式内,可以访问到存放当前函数的变量;在对象内部的不能访问到。
原因也非常简单,因为函数作用域链的问题,采用var的是在外部创建了一个fn变量,函数内部当然可以在内部寻找不到fn后向上册作用域查找fn,而在创建对象内部时,因为没有在函数作用域内创建fn,所以无法访问。
三、简单的几个代码片段
代码片段一:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
// The Window
代码片段二:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());
//My Object
ps:匿名函数的执行环境是window
代码片段三:
代码片段四:
四、闭包的注意事项
由于闭包会常驻内存,使用不当会导致内存溢出。