js 函数
一、 函数的定义
JavaScript 函数有 属性 和 方法。
JavaScript 使用关键字 function 定义函数。
函数可以通过声明定义,也可以是一个表达式。
1. 函数声明
function a() {
console.log(1);
}
a();
2. 函数表达式
var b = function() {
console.log(2);
};
b();
3. 自调用函数
(function() {
console.log(3);
})();
二、 return 语句
return 关键字的意义: 结束一个函数;返回数据
return
语句只能在函数体内出现,如果不是的话会报语法错误。当执行到 return
语句 的时候, 函数终止执行, 并返回 return
的值给调用程序。
三、 函数参数
1. 显式参数(Parameters)
形参, 形式参数 ,默认是 undefined
函数显式参数在函数定义时列出。 (parameter:参数)
functionName(parameter1, parameter2, parameter3) {
// 要执行的代码……
}
2. 隐式参数(Arguments)
Arguments 对象
函数隐式参数在函数调用时传递给函数真正的值。
JavaScript 函数有个内置的对象 arguments 对象。
argument 对象包含了函数调用的参数数组。
实例
x = findMax(1, 123, 500, 115, 44, 88);
function findMax() {
var i,
max = arguments[0];
if (arguments.length < 2) return max;
for (i = 0; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
四、 函数的调用方式
作为普通函数
作为对象中的方法
作为对象的构造函数
通过对象的
call()
和apply()
方法间接调用
五、 变量的作用域
变量在哪里声明,则那里就是它的有效区域
var scope = "global"; //定义全局变量,如果不赋值,默认undefined;
x = 1; //没有声明的默认挂载的window,为全局变量
function checkscope() {
var scope = "local"; //定义局部变量
y = 2; //没有声明的默认挂载的window,为全局变量
return scope;
}
checkscope(); //=>'local' 改变的只是局部变量scope
scope; //=>'global' 全局变量scope并没有改变
!>在函数体内的参数和使用var
定义的变量都是属于局部变量,一定要善于使用局部变量,防止污染全局变量
六、 变量的声明提前
用了 var 定义的变量或函数的参数,都会被提前到函数体的顶部进行声明(但不涉及赋值,具体赋值还是需要运行到对应行数)
var scope = "global";
function f() {
console.log(scope); // =>undefined 输出"undefined",而不是"global"
var scope = "local"; // 变量 在这里 赋 初始 值, 但 变量 本身 在函数体内任何地方均是有定义的
console.log(scope); // =>"local"
}
这个特性跟**全局变量的声明提前(变量提升)**其实是一致的,所以编程时,要有个好习惯,尽量把函数所需要用到的变量在函数顶部声明好,这样可以使源代码非常真实的反映函数的变量作用域
七、 js 闭包
1. 闭包的概念
能读取其他函数内部变量的函数
2.闭包的由来
由于作用域链和垃圾回收机制的关系,函数内部能访问到函数外部的变量, 函数外部并不能访问到函数内部的变量。除非函数自己return
出来,这时候就需要闭包了!
普及一下:
作用域链:内部环境可以通过作用域链访问所在的外部环境,但是外部环境不能访问内部环境的任何变量和函数。
3. 闭包的作用
当我们想要访问函数A里面的变量时,我们就在函数A内部定义函数B,并且函数B调用了函数A的变量,且函数A返回函数B,此时函数B就称为闭包。 因为此时函数A在执行完后,并不会被释放,因为里面的变量仍然有被B调用,且函数A主动return函数B,这样我们就能从函数A外面调用函数A的变量了
!> 关键点:让A不会被回收,且主动return
function a() {
var test = "函数内的变量"; // name 是一个被 init 创建的局部变量
function b() {
// displayName() 是内部函数,一个闭包
alert(test); // 使用了a函数中声明的变量
}
b();
}
a();
闭包问题
首先:函数a()
可以访问外部的变量,但是外部不能访问a()
的变量
创建闭包后:当函数a()
的内部函数b()
被函数a()
外的一个变量 c引用的时候,就创建了一个闭包。
作用:函数b()
作为函数a()
的返回值,在外部通过变量 c 调用b()
可以引用a()
内的变量.
4. 闭包的实例
var test = 10;
function a() {
var test = "100";
console.log(test); //结果为'aa 100' //作用域 : a --> window
//返回一个函数(带参数)
return function b(num) {
test += num; //作用域 : b --> a --> window
console.log("b", test);
};
}
a();//执行函数a(),返回的是b函数,还没打印出test,test是b()执行的结果
var c = a(); //变量c = a()执行后的返回值,也就是b()
c(1); //结果为 1001
c(2); //结果为 10012
5. 闭包的弊端及解决方法
由于函数A会一直不被释放,一直占用着内存,会容易造成内存泄露。
解决方法:在函数执行完后,将变量=null
!> 函数可以嵌套函数,同时函数也可以被当做值返回或传递
八、 回调函数
定义主函数的时候,让代码先去执行callback()回调函数,但是结果却先输出主函数在输出回调函数。这就说明了主函数不用等待回调函数执行完,可以接着执行自己的代码。所以一般回调函数都用在耗时操作上面。比如ajax请求,比如处理文件等。
//定义主函数,回调函数作为参数
function A(callback) {
callback();
console.log('我是主函数');
}
//定义回调函数
function B(){
setTimeout("console.log('我是回调函数')", 3000);//模仿耗时操作
}
//调用主函数,将函数B传进去
A(B);
// 输出结果:
// 我是主函数
// 我是回调函数