定义
定义函数的 方式有两种:一种是函数声明,另一种就是函数表达式
关于函数声明,它的一个重要特征就是函数声明提升
执行以下代码的结果可 能会让人意想不到
if(condition){
function sayHi(){
alert("Hi!");
}
} else {
function sayHi(){
alert("Yo!");
}
}
这在 ECMAScript 中属于无效语法,JavaScript 引擎会尝试修正错误,将其转换为合 理的状态。大多数浏览器会返回第二个声明。
修改
var sayHi;
if(condition){
sayHi = function(){
alert("Hi!");
};
} else {
sayHi = function(){
alert("Yo!");
};
}
递归
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * factorial(num-1);
}
}
减小耦合,但增大了内存开销。
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * arguments.callee(num-1);
}
}
闭包
闭包是指有权访问另一个 函数作用域中的变量的函数。
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
以它们引用的都是同一个变量 i 。 当 createFunctions()函数返回后,变量 i 的值是 10
修改
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(num){
return function(){
return num;
};
}(i);
}
return result;
}
在这个 匿名函数内部,又创建并返回了一个访问 num 的闭包
this对象
匿名函数的执行环境具有全局性,因此其 this 对象通常指向 window
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //"The Window"
每个函数在被调用时都会自动取得两个特殊变量:this 和 arguments。内部函 数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量
var name = "The Window";
var object = {
name : "My Object",
getName: function(){
return this.name;
}
};
object.getName(); //"My Object"
(object.getName)(); //"My Object"
(object.getName = object.getName)(); //"The Window",
第二行代码在调用这个方法前先给它加上了括号。虽然加上括号之后,就好像只 是在引用一个函数,但 this 的值得到了维持,因为 object.getName 和(object.getName)的定义 是相同的。
第三行代码先执行了一条赋值语句,然后再调用赋值后的结果。因为这个赋值表达式的值是 函数本身,所以 this 的值不能得到维持,结果就返回了"The Window"。
内存泄漏
如果闭包的作用域链中保存着一个 HTML 元素,那么就意味着该元素将无法被销毁
function assignHandler(){
var element = document.getElementById("someElement");
element.onclick = function(){
alert(element.id);
};
}
由于匿名函数保存了一个对 assignHandler()的活动对象的引用,因此 就会导致无法减少 element 的引用数
修改
function assignHandler(){
var element = document.getElementById("someElement");
var id = element.id;
element.onclick = function(){
alert(id);
};
element = null;
}
通过把 element.id 的一个副本保存在一个变量中,并且在闭包中引用该变量消 除了循环引用
模仿块级作用域
语法
(function(){
//这里是块级作用域
})();
以上代码定义并立即调用了一个匿名函数,可以避免命名的变量被其他地方调用
私有变量
(function(){
//私有变量
var a
//私有函数
function b(){
...
}
(function(){
//这里可以去调用
})();
})();