1.函数其实是对象。每一个函数都是 Function 类型的实例,并且都与其余引用类型同样具备属性和方法数组
2.因为函数名仅仅是指向函数的指针,所以函数名与包含对象指针的其余变量没有什么不一样app
function sum(num1, num2){ return num1 + num2; } alert(sum(10,10)); //20 var anotherSum = sum; alert(anotherSum(10,10)); //20 sum = null; alert(anotherSum(10,10)); //20
3.ECMAScript中函数没有重载函数
4.函数声明和函数表达式的区别:解析器会率先读取函数声明,并使其在执行任何代码以前可用(能够访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行this
alert(sum(10,10)); function sum(num1, num2){ return num1 + num2; } //函数声明提高,正常执行 alert(sum(10,10)); var sum = function(num1, num2){ return num1 + num2; }; //报错
5.做为值得函数:不只能够像传递参数同样把一个函数传递给另外一个函数,并且能够将一个函数做为另外一个函数的结果返回;仅使用函数名能够访问函数的指针而不执行函数。prototype
function add10(num){ return num + 10; } var result1 = callSomeFunction(add10, 10); alert(result1); //20
6.函数内部属性arguments指针
arguments它是一个类数组对象,包含着传入函数中的全部参数,它还包含一个属性交callee,该属性是一个指针,指向拥有这个 arguments 对象的函数。callee属性能够用来解耦合。code
function factorial(num){ if (num <=1) { return 1; } else { return num * factorial(num-1) //利用factorial函数名回调递归 } }
这样作法若是以后factorial赋值给别的变量,而后又从新赋值一个函数给factorial。那么别的变量并不会调用到本来的递归函数,而是调用到factorial新赋值的函数。因此须要消除这种紧耦合。对象
function factorial(num){ if (num <=1) { return 1; } else { return num * arguments.callee(num-1) } } var trueFactorial = factorial; factorial = function(){ return 0; }; alert(trueFactorial(5)); //120 alert(factorial(5)); //0
7.函数内部属性this
this引用的是函数据以执行的环境对象——或者也能够说是 this 值继承
window.color = "red"; var o = { color: "blue" }; function sayColor(){ alert(this.color); } sayColor(); //"red" o.sayColor = sayColor; o.sayColor(); //"blue"
ps:函数的名字仅仅是一个包含指针的变量而已。所以,即便是在不一样的环境中执行,全局的sayColor()函数与o.sayColor()函数指向的仍然是同一个函数。递归
8.函数都包含的属性与length和protoType。
length是函数接收的命名参数个数;
protoType是保存他们全部实例方法的真正所在,例如valueOf(),toString(),只不过是经过各自对象的实例访问。另外,prototype 属性是不可枚举的,所以使用 for-in 没法发现。
9.每一个函数都包含两个非继承而来的方法:apply()和 call()。这两个方法的用途都是在特定的做用域中调用函数
apply()方法接收两个参数:一个是在其中运行函数的做用域,另外一个是参数数组
function sum(num1, num2){ return num1 + num2; } function callSum1(num1, num2){ return sum.apply(this, arguments); // 传入 arguments 对象 } function callSum2(num1, num2){ return sum.apply(this, [num1, num2]); // 传入数组 } alert(callSum1(10,10)); //20 alert(callSum2(10,10)); //20
call()方法与 apply()方法的做用相同,它们的区别仅在于接收参数的方式不一样。传递给函数的参数必须逐个列举出来。
function sum(num1, num2){ return num1 + num2; } function callSum(num1, num2){ return sum.call(this, num1, num2); } alert(callSum(10,10)); //20
10.传递参数并不是 apply()和 call()真正的用武之地;它们真正强大的地方是可以扩充函数赖以运行的做用域
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
使用 call()(或 apply())来扩充做用域的最大好处,就是对象不须要与方法有任何耦合关系。