这两天看这个理论知识,看的有点小恶心了。。现在稍微总结一下,大体知道的,然后不全的再随着自己的理解往上加。
函数表达式
-
什么是函数表达式?
定义函数有两种方式,一个是函数声明,另一个是函数表达式。函数声明最重要的一个特征是函数声明提升。
函数声明:function functionName(arg0, arg1, arg2){ //函数体 }
函数表达式:
var functionName = function(arg0, arg1, arg2) {
//函数体
}
-
为啥会出现函数表达式?
既然函数声明比较好理解,同时还具有函数声明提升的特征,为啥要出现函数表达式??
原因一:if(condition) { function sayHi( ){ alert(" Hi ! "); } }else{ function sayHi( ){ alert(" Yo ! "); } }
其实上面代码的本意是很清楚的,希望能根据不同的condition可以执行不同的部分。但是,函数声明提升会导致语法错误,而各个浏览器修复错误的方式是不同的,所以执行结果也会不同。这个时候,函数表达式可以解决这个问题。
if(condition) {
sayHi = function ( ){
alert(" Hi ! ");
}
}else{
sayHi function ( ){
alert(" Yo ! ");
}
}
原因二:
javascript中没有块级作用域的概念,可以使用函数表达式、匿名函数来模拟实现这个功能。
var someFunction = function( ) {
//这里是块级作用域
};
someFunction( );
同时在这里说一下“立即执行函数表达式”,常见的几种方式包括
(1)
( function ( ){
console.log(" test ! ");
})( );
(2)
( function ( ){
console.log(" test ! ");
}( ));
以上是正确的“立即执行函数表达式”的正确写法。可能很多人会有疑问,为什么要这样子写??
function ( ){ }( ); //出错
当像上面这样写的时候,会出现语法错误,因为javascript当遇到function关键字时,会当作函数声明的开始,而函数声明后面跟的应该是函数名,而不能是圆括号,所以会出现语法错误。那为啥上面两种方法就可以实现“立即执行”的功能,不报错呢。因为javascipt中语法中,()里面会自动解析成表达式,而不是语句。比如:
/ / 如果传入字面量(literal),则返回表达式(expression)
(1) // 1
(function(){console.log("f");}) // function () {console.log("f")}
通过上面的描述应该大概懂了一些,那如何实现模拟块级作用域的呢。
//a.js
var num = 1;
// code....
//b.js
var num = 2;
// code....
当同时引入a.js、b.js时,一定会造成num变量的覆盖,为了解决这个问题,我们的“立即执行函数表达式”就发挥作用了呢。
a.js
(function(){
var num = 1;
// code....
})();
b.js
(function(){
var num = 1;
// code....
})();
经过改造之后,现在两个库成为完全独立的了,就可以放心大胆的使用了。
匿名函数:顾名思义,就是没有名字的函数。
匿名函数的用途之一就是把函数当成值来使用。
闭包
啥是闭包?
闭包就是能够读取其它函数内部变量的函数。是将函数内部和函数外部连接起来的一座桥梁。闭包的用处??
为啥会出现闭包呢,因为javascript作用域链的作用,函数内部可以访问函数外部的作用域,但是外部想访问内部的变量就不可以了。闭包的最大用处有2个,一个是可以读取函数内部的变量,另一个就是可以让这些变量的值始终保持在内存中。-
闭包经常出现的问题
function createFunctions(){ var result = new Array(); for(var i = 0; i < 10; i++){ result[i] = function(){ return i; }; } return result; }
上面代码返回的数组,每个函数都返回的是10。因为每个函数的作用域链中都保存着createFunctions()函数的活动对象,所以它们引用都是同一个变量i。我们可以通过创建另一个匿名函数强制让闭包的行为符合预期。
function createFunctions(){
var result = new Array();
for(var i = 0; i < 10; i++){
result[i] = function(num){
return function(){
return num;
};
}(i);
}
return result;
}
-
闭包用来模拟单例
var counter = (function(){ var i = 0; return { get: function(){ return i; }, set: function( val ){ i = val; }, increment: function() { return ++i; } }; }()); counter.get(); // 0 counter.set( 3 ); counter.increment(); // 4 counter.increment(); // 5