函数表达式
定义函数有两种方式:一是函数声明,二是函数表达式。函数声明有一个重要特征是函数声明提升。
匿名函数:function关键字后面没有标识符。
1 递归
非严格模式下:
function factorial(num){
if(num <= 1){
return 1;
}else{
return num * arguments.callee(num-1);
}
}
严格模式下:
var factorial = (function f(num){
if(num <= 1){
return 1;
}else{
return num * f(num-1);
}
}
2 闭包
闭包是指有权访问另一个函数作用域内的变量的函数。创建闭包的常用方式就是在一个函数内部创建另一个函数。
2.1 闭包与变量
闭包只能取得包含函数中任何变量的最后一个值。
function createFunctions(){
var results = [];
for(var i=0;i<10;i++){
results[i] = function(){
return i;
};
}
return results;
}
console.log(createFunctions().toString()); //10,10,10,...,10
2.2 this对象
匿名函数的执行环境具有全局性,因此其this对象通常指向window。
2.3 内存泄漏
(IE的某些版本中)如果闭包的作用域链中保存着一个HTML元素,那么意味着该元素将会无法被销毁。因为这些版本中对于JavaScript访问COM使用引用计数的垃圾收集机制。
/*
*匿名函数保存了一个对assignHandler()的活动对象的引用,因此就会导致无法减少element的引用计数,至少为1
*/
function assignHandler(){
var element = document.getElementById('ele');
element.onclick = function(){
alert(element.id);
}
}
/*
* 改进方法:
*/
function assignHandler(){
var element = document.getElementById('ele');
var id = element.id;
element.onclick = function(){
alert(id);
}
element = null;
}
3 模仿块级作用域
用作块级作用域的你ing函数与法如下:
(function(){
//这里是块级作用域
})();
无论在什么地方,只要临时需要一些变量,就可以使用私有作用域
function outputNumbers(count){
(function(){
for(var i=0;i<count;i++){
alert(i);
}
})();
alert(i); //error
}
4 私有变量
在JavaScript中没有私有成员的概念,所有对象属性都是公开的,但是有一个私有变量的概念:任何在函数中定义的变量都可以认为是私有变量,因为在函数外部无法访问这些变量。私有变量包括函数的参数,局部变量和在函数内部定义的其他函数。
我们把有权访问私有变量和私有方法的公有方法称为特权方法。有两种在对象上传建特权方法的方式:第一种是在构造函数内部创建特权方法。
function myObject(){
var privateVariable = 10;
funtion privateFunction(){
return false;
}
this.publicMethod = function(){
privateVariable++;
return privateFunction();
};
}
4.1 静态私有变量
通过在私有作用域中付那个意思有变量和函数,同样也可以创建特权方法。这个方法与在构造函数中定义特权方法的区别是:私有变量和函数是由实例共享的。
(function(){
var name = "";
Person = function(value){
name = value;
};
Person.prototype.getName = function(){
return name;
};
Person.prototype.setName = function(value){
name = value;
};
})();
var p1 = new Person('Nicholas');
console.log(p1.getName); //'Nicholas'
p1.setName('Gred');
console.log(p1.getName); //'Gred'
var p2 = new Person('Michael');
console.log(p1.getName); //'Michael'
console.log(p2.getName); //'Michael'
4.2 模块模式
模块模式是为单例创建私有变量和特权方法的。所谓单例,指的就是只有一个实例的对象。暗战管理,JavaScript是以对象字面量的方式来创建单例对象的。
var application = function(){
var components = new Array();
components.push(new BaseComponent());
return{
getComponentCount:function(){
return components.length;
},
registerComponent:function(component){
if(typeof component === 'oject'){
components,push(component);
}
}
};
}();
-----------------------------------------------拓展部分:--------------------------------------------------
单例模式:
1.模块模式:
function SingleWaiter(id,name,salary){
Staff.call(this,id,name,salary);
}
SingleWaiter.getInstance = function(id,name,salary){
var instance;
return function(id,name,salary){
if(!instance){
instance = new SingleWaiter(id,name,salary);
}
return instance;
}
}();
2.函数接口
function SingleWaiter(id,name,salary){
Staff.call(this,id,name,salary);
this.instance = null;
}
SingleWaiter.getInstance = function(id,name,salary){
if(!this.instance){
this.instance = new SingleWaiter(id,name,salary);
}
return this.instance;
}();
3.属性判断
function SingleWaiter(id,name,salary){
Staff.call(this,id,name,salary);
if(SingleWaiter.prototype.instance){
return SingleWaiter.prototype.instance;
}
SingleWaiter.prototype.instance = this;
}
-------------------------------------------------拓展结束---------------------------------------------------
4.3 增强的模块模式
在返回对象之前加入对其增强的代码。这种增强的模块模式适合那种单例必须是某种类型的实例,同时还必须添加某些属性和(或)方法对其加以增强的情况。
var application = function(){
var components = new Array();
components.push(new BaseComponent());
//要求application对象必须是BaseComponent类型的
var app = new BaseComponent();
app.getComponentCount = function(){
return components.length;
};
app.registerComponent = function(component){
if(typeof component === 'oject'){
components,push(component);
}
}
return app;
}();