JavaScript高级程序设计5--函数表达式

定义函数的方式有两种:一种是函数声明,另一种是函数表达式。

//函数声明
function functionName(arg0, arg1, arg2){
	//函数体
}
//函数表达式(匿名函数)
var functionName = function(arg0, arg1, arg2){
	//函数体
}
注意:函数声明有一个函数声明提升的特性,而函数表达式没有。
一、递归

我们知道对于一个递归阶乘函数,将函数名赋值给另一个变量时,此变量指向原始函数,如果我们将原始函数名值设为null,再访问此函数,就会导致错误,前面第3章说过,可以使用arguments.callee来解决,但在严格模式下,不能通过脚本访问它,此时我们可以使用命名函数表达式可解决。

var factorial = (function f(num){
	if (num <=1){
		return 1;
	} else{
		return num*f(num-1);
	}
});
二、闭包

闭包是指有权访问另一个函数作用域中的变量的函数

//function createComparisonFunction(propertyName){

	return function(object1, object2){
		var value1 = object1[propertyName];
		var value2 = object2[propertyName];
		if (value1 < value2){
			return -1;
		} else if (value1 > value2){
			return 1;
		} else {
			return 0;
		}
	};
}
例如以上函数中的匿名函数就是一个闭包,它可以访问包含它的函数createComparisonFunction作用域中的变量propertyName。
我们知道,通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。但是,当函数返回一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止。

例如:

//创建函数
var compareNames = createComparisonFunction("name");
//调用函数
var result = compareNames({ name: "Nicholas"}, { name: "Greg"});
//解除对匿名函数的引用(以便释放内存)
compareNames = null;

下图展示了调用compareNames()的过程中产生的作用域链之间的关系。


因此,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域

闭包的问题:

  • 闭包只能取得包含函数中任何变量的最后一个值,它所保存的是整个变量对象而不是某个特殊的变量。
  • 在闭包中使用this对象时,由于每个函数在被调用时都有this和arguments两个特殊变量,内部函数在搜索这两个变量时只会搜索到其活动对象为止,因此闭包永远不可能直接访问外部函数中的这两个变量。
  • 在IE9之前的版本中,如果闭包的作用域链中保存着一个HTML元素,那么该元素无法被销毁。
三、模仿块级作用域

使用闭包可以在JavaScript中模仿块级作用域(JavaScript本身没有块级作用域的概念)。这种方式可以减少闭包占用的内存问题。

(function (){
	//这里是块级作用域
})();
注意:函数声明function后面不能跟圆括号,而函数表达式的后面可以。
四、私有变量

私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。

通过闭包可以在对象中创建私有变量。这里,我们把有权访问私有变量和私有函数的公有方法称为特权方法

function MyObject(){

	//私有变量和私有函数
	var privateVariable = 10;

	function privateFunction(){
		return false;
	}

	//特权方法
	this.publicMethod = function (){
		privateVariable++;
		return privateFunction();
	};
}
但是,在构造函数中定义特权方法有一个缺点,就是针对每个实例都会创建同样一组新方法,而使用静态私有变量实现特权方法可以避免。

1.静态私有变量

(function(){

	//私有变量和私有函数
	var privateVariable = 10;

	function privateFunction(){
		return false;
	}
	//构造函数
	MyObject = function(){
	};

	//公有/特权方法
	MyObject.prototype.publicMethod = function (){
		privateVariable++;
		return privateFunction();
	};
})();
这个模式与在构造函数中定义特权方法的区别在于,私有变量和函数是由实例共享的。

2.模块模式

模块模式指的是为单例创建私有变量和特权方法,而单例指的是只有一个实例的对象。

var singleton = function(){
	//私有变量和私有函数
	var privateVariable = 10;
	function privateFunction(){
		return false;
	}

	//特权/公有方法和属性
	return {
		publicProperty: true,
		publicMethod: function(){
			privateVariable++;
			return privateFunction();
		}
	};
}();	
3.增强的模块模式

增强的模块模式适合那些必须是某种类型的实例,同时还必须添加某种属性和(或)方法对其加以增强的情况。

var singleton = function(){
	//私有变量和私有函数
	var privateVariable = 10;
	function privateFunction(){
		return false;
	}
	
	//创建对象
	var object = new CustomType();
	
	//添加特权/公有属性和方法
	object.publicProperty = true;
	object.publicMethod = function(){
		privateVariable++;
		return privateFunction();
	};

	//返回这个对象
	return object;
}();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值