一. 函数的创建
1. 函数声明,使用函数语句定义函数,这种定义方式下,函数不属于任何对象,始终是默认的全局对象。
function outputHello(name){
return "Hello"+name;
}
console.log(outputHello("nana"); //Hello nana
javascript中任何一个函数都有返回值。如果不显式使用return关键字返回。或者只使用了return关键字,而没有返回值,函数实际的返回值为undeined。
变量提升:在程序执行之前,JavaScript解释器会将全局声明的变量,定义的函数等进行预处理,因此在代码层,函数的调用时在定义前还是定义后都无关紧要。(fun();函数可以先调用,因为在JS的最顶层有一个预编译处理机制。)
JS的运行机制:在JS中JS引擎会优先解析var变量function定义,在预解析完成后从上往下逐步进行。解析var变量时,会把值存储在“执行环境中”,不会去赋值,值是存储作用。alert(a); a=5; 返回undefind, 意思是被初始化而没有被赋值。(并不是没有被定义)。解析function时,会把函数整体定义。
2.使用函数表达式定义函数,即存储在变量值中。
//函数表达式
var myGoal = functiob(age){
console.log("My goal is"+age);
};
myGoal(17);
函数表达式和函数函数语句 最大的区别在于其可以忽略函数名,也可以理解为函数表达式创建了一个匿名函数。
函数表达式的函数名只能在函数内部使用,对于外部来说,起实质还是匿名函数。函数表达式定义的函数在函数定义之前是不能进行调用的,函数表达式的实质是将一个函数对象赋给了一个变量,javascript解释器只是预先定义好了变量符号,在表达式未执行之前,变量实际是undefind,函数并不存在。
3.构造函数
JS中一切都是对象,是对象就有属性和方法。
通过Function对象和New关键字来构造函数对象。
var R = new Function("name","console.log(name);");
R("GEGE"); //输出GEGE
Function构造函数的结构可以简化为Function(param,param,funbody). Function构造函数中的参数个数并不固定,最后一个参数为创建函数的函数体,前面所有的参数都将作为函数的形参。
二. JS函数中的this
this指代一个对象,指向调用函数的对象,并且拥有这个对象的值,只有某个对象调用了这个this函数的时候this才被赋值
1.函数直接调用,fun(); this指向全局对象,在浏览器中是window对象。
2.作为对象的方法调用,obj.fun(); this指向这个上级对象obj 。
3.作为构造函数调用,new fun(); this指向new fun()返回的对象。
4.apply调用,apply方法作用是改变函数的调用对象,这个方法的第一个参数为改变后调用这个函数的对象,this指代第一个参数,如果传入的第一个参数是null或者undefind, 则函数的this指向Global全局对象。
三.JS函数的参数
JS函数中的参数在内部是用一个数组来表示的,函数接收到的始终是这个数组,而不关心数组中包含哪些参数,通过arguments对象可以访问这个参数数组。(形参只是提供便利的,不是必须的。)
function myFunction(a,b,c){
console.log(arguments[0],arguments[1],arguments[2]) //1,2,3
return x+1;
}
myFunction(1,2,3);
arguments对象的length属性显示实参的个数,函数的length属性显示形参的个数。
function myFunction(a,b,c){
console.log(arguments.length) //3
return x+1;
}
myFunction(1,2,3);
console.log(myFunction.length) //2
四. 回调函数
回调函数就是一个参数,将这个函数b作为参数传到另一个函数a的参数里面,当那个函数a执行完以后,再执行传进去的那个函数b,这个过程就叫做回调,函数b就叫回调函数。
五. 闭包
变量作用域:全局变量和局部变量
函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。
注:在函数内部不声明变量的时候,如果没有用var 命令,实际上声明的是一个全局变量。
要想取到函数内部的局部变量,可以在函数内部再定义一个函数。
function f1(){
var n = 0;
function f2() {
n++;
console.log(n);
}
inc();
inc();
}
a(); //控制台输出1,再输出2
函数 f2 包含在函数 f1 中, f1 内部局部变量对 f2 都是可见的,但是f2 内的局部变量对 f1 是不可见的。
链式作用域结构: 子对象会一级一级向上 寻找父级对象的所有变量。
所以只要将 f2 作为 f1 的返回值,那么在 f1的外部级可以取到它的内部变量。
闭包:闭包就是能读取其他函数内部的函数,即定义在函数内部的一个函数。(f2)
闭包的用途:1.读取函数内的局部变量 。
2.让变量的值保存在内存中(全局变量始终在内存中),所以内存消耗大,不能滥用闭包。