javascript--函数(递归、闭包)

一、函数声明与函数表达式

定义函数的方式有两种:函数声明和函数表达式

函数声明:
function functionName()
{
}
  • 函数声明提升:执行代码前会先读取函数声明。可以把函数声明放在调用它的语句后面。
  • 两个同名函数声明,后出现的生效
函数表达式
var functionName = function()
{

}
  • 因为function关键字后没有函数名,所以创建的函数叫匿名函数(或拉姆达函数
  • 函数表达式在使用前必须赋值,和其他表达式一样
var sayHi;

if(condition)
{
	sayHi = function(){alert("Hi");};
}
else
{
	sayHi = function(){alert("Yo");};
}
//只能用函数表达式实现,不能用函数声明
二、函数递归
function factorial(num)
{
	if(num<=1)
	{
		return 1;
	}
	else
	{
	 	return num*arguments.callee(num-1);
	}
}
  • arguments.callee指向正在执行的函数的指针
  • 在严格模式下访问arguments.callee属性会导致错误
var factorial =  function f(num)//命名函数表达式
{
	if(num<=1)
	{
		return 1;
	}
	else
	{
		return num*f(num-1);
	}
}
  • 严格模式下用命名函数表达式实现递归
三、闭包
  • 在一个函数内部创建的另一个函数,会将包含函数的活动对象添加到它的作用域中,因此有权访问包含函数中的变量和方法。
  • 外部函数在执行完毕后,其作用域链会被销毁,但其活动对象也不会销毁,因为内部函数的作用域链仍在引用这个活动对象。

  • 闭包会比其他函数占用更多的内存,只在绝对必要时在考虑使用闭包

  • 闭包保存的是整个活动对象,而不是某个时刻的变量值,它只能取得包含函数的变量的最后一个值。
function createFunctions()//每个函数返回自己在数组中的索引值
{
	var result = new Array();
	for(var i=0; i<10; i++)
	{
		result[i]= (function(num)
		{
			return function()
			{
				return num;
			}
		})(i);//函数参数是按值传递的,会将变量i的瞬时值赋给num
	}
	return result;
}
this对象
  • 在全局函数中this = window
  • 函数被作为某个对象的方法调用时,this = 那个对象
  • call() , apply() 改变函数执行环境时,this指向指定的对象

  • 每个函数在调用时都会自动取得两个变量:this和arguments。内部函数在搜索这两个变量时,只会搜索到其自己的活动对象为止,因此不能直接访问其外部函数的这两个变量。可以将外部函数的这两个变量保存在其他变量里,内部函数利用闭包来访问。
var name = "the window";
var object = {
	name : "My object",
	getNameFunc : function(){
		return function()//匿名函数执行环境具有全局性,其this对象通常指向window
		{
			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

  • 特殊情况
var name = "the window";
var object = {
	name : "my object",
	getName:function()
	{
		return this.name;
	}
};

(object.getName = object.getName)();//the window
  • 先赋值,再调用赋值后的结果。因为赋值表达式的值是函数本身,this的值不能得到维持。(???)
内存泄露
  • IE9之前对JScript和COM对象使用不同的垃圾收集例程,COM对象使用引用计数方式。如果闭包的作用域链中保存着一个HTML元素,该元素将无法被销毁。
  • 解决方法如下:
function assignHandler()
{
	var element = document.getElementById("someElement");
	var id = element.id;
	element.onclick = function(){alert(id);};
	
	element = null;//有必要解除对DOM对象的引用
}
模仿块级作用域
  • 匿名函数模仿块级作用域
(function(){
	//块级作用域
})();
  • 函数声明后不能加(),函数表达式后可以加()
  • 这种技术经常在全局作用域中被用在函数的外部,限制向全局作用域中添加过多的变量和函数。
私有变量
  • javascript中所有对象属性都是公有的
  • 函数中定义的变量和方法、函数的参数可以认为是私有的
  • 用闭包创建访问私有变量和方法的公有方法:特权方法
  • 创建特权方法:
  1. 在构造函数中定义特权方法
    但是每个实例都会创建同样的方法,不能复用方法
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是全局变量
   //但严格模式下给未经声明的变量赋值会导致错误
   MyObject = function(){};
   //特权方法
   MyObject.prototype.publicMethod = function(){
   	privateVariable++;
   	return privateFunction();
   };
})();
  • 这里的私有变量和函数变成了静态的,是由实例共享的
  1. 模块模式为单例创建特权方法
  • 单例:只有一个实例的对象
  • javascript以对象字面量来创建单例对象
var singleton = function()
{
   var privateVariable = 10;
   function privateFunction(){return false;}

   return { 
   	publicProperty : true,
   	publicMethod : function(){
   		privateVariable++;
   		return privateFunction();
   	};
}();
  1. 增强的模块模式
  • 单例必须是某种类型的实例,同时还必须添加某些属性和方法对其加以增强的情况。
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;
}();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值