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;
}

四、 函数的调用方式

  1. 作为普通函数

  2. 作为对象中的方法

  3. 作为对象的构造函数

  4. 通过对象的 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);

// 输出结果: 
// 我是主函数
// 我是回调函数
Last Updated:
Contributors: zerojs