1,函数是什么
①,函数的数据类型是Object,函数是对象。
②,函数的原型链中肯定会有Function.prototype对象,并继承其属性和方法。
③,函数是可以反复调用的代码块。
2,函数的声明
①,用function命令声明一个具名函数。
function fun(x,y){function body}
②,用function命令声明一个匿名函数,并赋值给变量。(也可是具名函数)
var fun = function(x,y){function body}//匿名函数
var fun = function haha(x,y){function body}//具名函数
③,Function构造函数生成一个实例,但需要注意,你可以传递任意数量的参数给Function构造函数,只有最后一个参数会被当做函数体,如果只有一个参数,该参数就是函数体。
var fun = new Function('x','y','functionbody')
④,箭头函数(ES6)
var fun = (x,y)=>{functionbody}
也可以这样
var fun = (x,y) => x+y
var fun = x => x*x
3,函数的调用方法
声明函数一个函数:function fun(x,y){console.log(x+y)}
①,直接函数名加括号,括号内写入参数:fun(1,2)。
②,call方法调用:f.call(undefined,1,2)
PS:接受n个参数,第一个是函数fun内this的指向,接下来就是传入的参数。
③,JS把函数名视同变量名和var声明变量一样,function命令声明的函数存在函数提升。
③,函数不调用不执行,在什么位置调用,就在什么地方执行。什么时候执行函数,才会什么时候解析函数体里面的代码。
4,arguments对象与参数
①,调用函数时,传入的参数会组成一个类似数组的对象,这个对象就是arguments。
②,类似数组,但不是数组,原型链中并没有Array.prototype。
③,函数的参数可以省略一部分或全部,但不能省略前参数而直接传入后参数,如果要省略前参数,请传参时传入undefined。
④,如果函数内部给arguments对象的属性赋值,将忽略你调用函数时传入的参数(参数顺序与arguments下标匹配)。
⑤,同名参数以后面的为准,就算你没给后面的赋值,也一样,如下:
function f(a, a)
{console.log(a);}
f(1)// undefined
5,函数的调用栈call stack
6,作用域
①,作用域(scope)指的是变量存在的范围。在 ES5 的规范中,JavaScript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。(ES6 新增了块级作用域)
②,对于顶层函数来说,函数外部声明的变量就是全局变量,它可以在函数内部读取。
③,在函数内部定义的变量,外部无法读取,称为“局部变量”。函数内部定义的变量,会在该作用域内覆盖同名全局变量。
④,与全局变量一样,用var命令声明的变量在函数内部也存在变量提升。
⑤,函数本身也是一个值,也有自己所存在的作用域。与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。
⑥,全局变量与局部变量同名是互不影响的,即便将全局变量当做参数赋值给同名的局部变量也是互不影响的。但对象是特例,因为传址传递的缘故,内外指向的都是同一个对象,如果你在函数作用域修改对象的属性,那么在函数外部该属性也是被修改了的。如下例:
varobj = {p:1};
function f(o)
{ o.p =2;}
f(obj);
obj.p// 2
⑦,JavaScript 语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
7,闭包
①,英文是closure。
②,闭包就是:函数套函数,内函数存在外函数的变量,内函数与该变量的总合就是闭包。
③,详见:闭包
网友评论