04 Function

Function类型:
每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法,由于函数是对象,因此函数名实际上是一个指向函数对象的指针。
函数的三种定义方式:

第一种:
	function sum(num1,num2){
		return num1+num2;
	}
第二种:
	var sum = function(num1,num2){
		return num1+num2;
	};
第三种:
	var sum = new Function("num1","num2","return num1+num2");

第二种方式function后面没有函数名,因为通过变量sum即可引用函数,另外函数末尾有分号,就像声明变量一样。
由于函数名是指向函数的指针,因此一个函数可以有多个名字
var anothersum = sum;
alert(anothersum(10,10));//20


没有重载:因为函数名是指针,因此可以理解javascript没有重载,因为在第二个同名函数被定义的时候,函数名指向了另一个函数对象。

函数声明和函数表达式:

函数声明:解析器会先读取函数声明,使其在执行任何代码之前可用
函数表达式:必须等到解析器执行到它所在的代码行,才会真正被解释执行。
Example 1:  正常运行;
alert(sum(10,10));
function sum(num1,num2){
	return num1+num2;
}

Example 2: 运行出错,函数位于一个初始化语句块中,而不是一个函数声明中
alert(sum(10,10));
var sum = function(num1 , num2){
	return num1+num2;
}


作为值的函数
因为ECMAScript中的函数名本身就是变量,所以函数本身也可以作为值来使用,也就是说可以像传递参数一样把一个参数传递给另一个参数,而且可以将一个函数作为另一个函数的结果返回。


函数的内部属性:
arguments和this
arguments主要是用来保存参数,这个对象还有一个属性叫callee,这是一个指针,指向拥有这个arguments对象的函数。
callee用法:在递归算法中消除耦合

this:函数执行时所处的作用域

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);
	}
}



函数的属性和方法
函数是对象,因此具有属性和方法
length属性:函数希望接受的命名参数的个数
prototype属性:是保存引用类型的所有实例方法的真正所在,在创建自定义类型和实现继承的时候,prototype属性的作用是极其重要的。
每个函数都有两个非继承而来的方法,call()和apply(),这两个方法用途都是在特定的域中调用函数,apply方法有两个参数,一个是在其中运行函数的作用域,另一个是参数数组,第二个参数可以是Array也可以是arguments
而是用call方法时,第二个参数必须一一列举出来。

Example 1:
function sum(num1,num2){
	return num1+num2;
}

function callSum1(num1,num2){
	return sum.apply(this,arguments);
}

function callSum2(num1,num2){
	return sum.apply(this,[num1,num2]);
}


Example 2:

function callSum3(num2,num1){
	return sum.call(this,num1,num2);
}

apply和sum真正的用处在于:能够扩充函数赖以运行的作用域
window.color= "red";
var o={color:"blue"};
function sayColor(){
	alert(this.color);
}
sayColor();//red
sayColor.call(this);//red
sayColor.call(window);//red
sayColor.call(o);//blue函数的执行环境不一样了,此时函数体内的this指向了o

函数的toString和toLocaleString方法都返回函数的代码。


<span style="font-size:18px;"><strong> 函数虽然是一个对象,但是却和对象有一些区别,对象是通过引用的指向完成对象的赋值的,而函数却是通过对象的拷贝来完成的所以fn1虽然变了,并不会影响fn2</strong></span>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>js01_hello</title>
	<meta name="author" content="Administrator" />
	<script type="text/javascript">
	//第一种定义方式
	function fn1() {
		alert("fn1");
	}
	//函数就是一个非常特殊的对象,是一个Function类的实例,其实在内存中存储的操作是通过一个键值对来存储的
	alert(typeof fn1);
	
	//由于函数是一个对象,所以可以通过如下方式定义
	//以下是通过函数的拷贝来完成赋值,两个引用并没有指向同一个对象
	var fn2 = fn1;
	fn2();
	fn1 = function() {
		alert("fnn1");
	}
	/**
	 * 函数虽然是一个对象,但是却和对象有一些区别,对象是通过引用的指向完成对象的赋值的,而函数却是通过对象的拷贝来完成的
	 * 所以fn1虽然变了,并不会影响fn2
	 */
	fn2();
	fn1();
	
	/**
	 * 对于对象而言,是通过引用的指向来完成赋值的,此时修改o1或者o2会将两个值都完成修改
	 */
	var o1 = new Object();
	var o2 = o1;
	o2.name = "Leon";
	alert(o1.name);
	</script>
</head>
<body>
</body>
</html>







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章