函数用来封装须要屡次使用的代码块数组
函数也是一个对象,所以能够给函数添加属性和方法,并做为数据值(利用函数的返回值)/参数(特定函数如setTimeout)/返回值使用app
把函数当参数传递时,函数名即为函数本体(里面的代码块),无需添加括号(添加括号即为执行函数)ide
当函数做为返回值时,为了调用返回的函数,须要在函数本体(函数名)后加()来执行函数
函数包括函数名、形式参数、实际参数、返回值this
函数名是指向函数在内存中位置的介质,可省略(此时叫匿名函数)spa
定义函数时函数名后的括号里即为形式参数(形参),不是必填,且形参和实参的数目没必要相等code
使用函数时实际传入的参数为实际参数(实参)对象
函数内部return后的语句即返回值blog
函数使得代码得以复用(不须要屡次Ctrl+C、Ctrl+V复制粘贴,只要调用函数便可使用相同的代码块执行特定功能)递归
便于代码的维护和修改(只需在函数中修改代码便可,调用函数的地方随之修改)
增长程序的可读性(把实现方法的细节封装在函数中,用函数名来表示实现的方法,更易理解)
包括function声明和var赋值表达式
1 function add(){ 2 console.log('I like swimming'); 3 }
1 var add = function(){ 2 console.log('I like swimming'); 3 }
function声明函数会预解析,执行函数放在函数定义前也能够顺利执行(声明提早)
var赋值表达式定义函数,在预解析时会将变量赋值为undefined,若是执行函数的操做在定义函数前,则报错
构建一个function对象的实例,其中形参和代码块都放在引号中
var add = new Function('num1','num2','return num1+num2;');
函数可定义在全局环境或局部环境(函数/对象内部)中
在全局中定义的函数,在全局内部任意位置均可以找到并调用这个函数
在局部中定义的函数,只可经过做用域链,向上一层找到该函数,若是找不到则报错
1.将其赋值给一个变量,用变量名()来实现调用
1 var add = function(){ 2 alert(1); 3 } 4 add();
2.直接用函数本体后加()的形式自我执行
这里的原理是:用function声明的函数会被识别并预解析,而在function前加合法的符号(+-!~等),不让函数以function打头,则函数不会被预解析,从而实现自执行
所以,在执行的()外/内加一组括号都是能够的
1 !+-~function(){ 2 alert(1); 3 }();
1 (function (){ 2 alert(1); 3 })();
可是要注意,自执行的函数也是有做用域的,执行完毕后,内部的做用域被销毁
在函数内部调用自身
注意调用次数不要超过最大的递归层数
1 function factorial(num){ 2 if(num == 1){ 3 return 1; 4 } 5 else{ 6 return num*factorial(num-1); 7 } 8 } 9 console.log(factorial(5));
不合法的方法名(属性名)须要用引号括起来(例如@),调用时用[](例如add['@'](1,2))
若是调用的方法名是一个字符串,则也使用[]
方法也能够链式调用,但该对象里的每一个方法须要返回当前对象(不然会形成undefined.方法的结果,出现报错)
不推荐过分使用链式调用
1 var operation = { 2 add:function(num1,num2){ 3 console.log(+num1+ +num2); 4 return this; 5 }, 6 subtract:function(num1,num2){ 7 console.log(num1-num2); 8 return this; 9 } 10 } 11 operation.add(1,2).subtract(3,2);
经过new 构造函数名()来调用(例如new Object())
调用完成后返回一个对象(该构造函数实例化的对象)
即不使用函数中的方法名()来调用方法,而是用函数名.方法名.apply()/call()来间接调用方法
注意此处函数名后不可跟()
call和apply方法的第一个参数都是用来改变方法中this的指向的,第二个参数apply可接收一个数组,把数组中每一个元素做为参数传入,而call只可接收一个个独立的参数
形式参数(形参):声明函数时的‘占位用’参数(在预解析时被当作函数的局部变量),可用函数名.length属性来访问到其个数
实际参数(实参):调用函数时传入的参数,可用arguments.length属性访问其个数
参数传递的本质:实参赋值给形参
1.实参数目=形参数目:按照定义函数时的顺序,把实参一一赋值给形参
2.实参数目<形参数目:未被赋值的形参为undefined
通常会在有可选参数时使用(若是不传递某个参数,给这个参数默认值)
1 function power(base,power){ 2 if(!power){ 3 power = 2; 4 } 5 return Math.pow(base,power); 6 } 7 console.log(power(3));//返回的是9
3.实参数目>形参数目:多余的实参不被归入函数的调用范围,会正常运行
arguments里保留了全部的实参(以键值对形式存储)、length属性、callee方法
建议不要在函数中对arguments对象进行修改操做
callee方法能够返回arguments对象的函数,防止函数名变化时,内部递归调用的函数名称也须要同时改变(严格模式下callee方法不可用)
1 function jiecheng(num){ 2 if(num == 1){ 3 return 1; 4 } 5 else{ 6 return num*arguments.callee(num-1); 7 } 8 } 9 console.log(jiecheng(5));
严格模式下,能够把命名函数赋值给经过var声明的变量,来达到相似callee的效果(变量名变化时,函数名以及函数内部自调用的名称都不要变,只要改变变量名)
1 var jiecheng = function f1(num){ 2 if(num == 1){ 3 return 1; 4 } 5 else{ 6 return num*f1(num-1); 7 } 8 } 9 console.log(jiecheng(5));
1.参数能够为空(声明函数时,括号中能够为空)
2.能够经过做用域链,用上一级的局部变量/全局变量来做为函数的参数
3.能够传递基本类型数据(数字、字符串、布尔值、undefined、null)或引用类型数据(数组、对象(参数三个以上时推荐使用)、函数)
其中传入对象能够解决了参数传递时必须按照形参顺序的问题
函数结束,将后续的内容返回(不然返回undefined)
1.返回值能够为空,即函数到此终止,返回undefined
2.返回值可为基本类型数据(数字、字符串(alert函数)、布尔值、undefined、null)、引用数据类型(数组、对象、函数)
document.write()方法指望返回的是字符串,若是不是,会调用toString方法将其返回为字符串