1. 函数的定义

函数体里面是普通的操作语句,不是对象的键值对。

1) 构造函数

(完整详细的写法,但很少用)

  1. sum = new Function('a', 'b', 'console.log(a); return a + b');

2) 具名函数

(有名字的函数)

  1. function sum(a,b){
  2. return a + b;
  3. }

3) 匿名函数

(没有名字的函数,也叫函数表达式)该方法创建的函数sum不会挂到window上

  1. let sum = function(a,b){
  2. return a + b;
  3. }
  4. let sum = function fn(a,b){
  5. return a + b;
  6. }
  7. fn(1,2) //语法错误,fn不存在,如果函数定义在等号右边则是以表达式的方式存在,其fn函数的作用域也
  8. 只在表达式右边,不是全局,出了表达式就不存在。

4) 箭头函数(没有this和arguments属性)

ES6函数定义新语法,sum不会挂到window上,且箭头函数没有this和arguments属性

  1. let sum = (a,b)=> a+b //函数体只有一个语句时,箭头左边是传入参数,右边是函数体
  2. //返回对象
  3. (错误) let fn = (x)=> {name: x} //若返回值为一个对象时,花括号默认是代码块标志,
  4. (正确) let fn = (x)=> ({name: x}) //给对象加个括号,标明里面是一个整体,即可正确返回对象
  5. let sum = (a,b)=> {
  6. return a + b;
  7. } //函数体有多个语句

每个函数都有返回值,若不写return,默认返回一个undefined,并且返回值是在函数执行时返回

任何函数的构造函数都是自己

箭头函数全都是匿名函数: 普通函数可以有匿名函数,也可以有具名函数

2. 函数自身属性

1) name

name这个属性值就是函数本身的名字

2) length

该属性是用来记录函数的形参个数,其属性值是number类型的数字,是形参个数。

3) arguments (箭头函数没有该属性)

在JS中,函数的定义中形参可以不写,在函数调用时可以直接传参,函数会接收传进来的参数,并且依次放进函数的arguments属性里,arguments属性值看似是个数组,但其实说对象更准确,里面数据是按照数组存储的方式存储的,所以arguments就是数组里提到的伪数组。当调用函数test(1,2)时,输出arguments组成如下所示:

  1. arguments(2){
  2. 0: 1
  3. 1: 2
  4. length: 2
  5. callee: ƒ test()
  6. Symbol(Symbol.iterator): ƒ values()
  7. __proto__: Object
  8. }

总结一句就是:arguments是包含了函数所有参数的伪数组

伪数组不具有数组的公共属性,如push、pop等,如想把伪数组变成数组,可通过Array.from实现。

4) caller

3. 函数公共属性

4. 闭包

4.1 什么是闭包

如果一个函数用到了外部的变量,那么这个函数加这个变量就叫做闭包

未完待续。。。。

5. 调用栈

5.1 什么是调用栈

JS引擎在执行一个函数前,需要把函数所在的环境push到一个数组里,这个数组叫做调用栈。等函数执行完了,就会把环境pop弹出来,然后return到之前的环境,继续执行后续代码

6. 立即执行函数

6.1 来源

在JS中,在函数外用var声明一个变量得到的是一个全局变量,那么如何得到一个局部变量呢?只用通过在函数内声明一个变量才能得到一个局部变量,如下所示:

  1. function fn(){
  2. var a;
  3. }
  4. fn();

那么a就是局部变量了,可是函数fn却是局部变量啊,为了得到一个局部变量,定义了一个全局函数变量,得不偿失,因此,就想到声明一个匿名函数如下:

  1. function(){
  2. var a;
  3. }

那么问题来了,匿名函数咋执行啊,没有名字怎么执行函数得到局部变量啊,因此就将函数的声明和执行统一在一起了,形成:

  1. function(){
  2. var a;
  3. }();

但是这样一来,JS认为该语法是错误的,是不对的,经过实验发现,如果在该函数面前加一个操作符,如+、-等就可成功运行了,也可以用括号将其括起来,如下:

  1. (function(){
  2. var a;
  3. }());
  4. !function(){
  5. var a;
  6. }();

6.2 结论

但经过测试,最保险的方法有如下两种:

  1. 在前面加感叹号
  2. 用括号将其包起来,但是要保证前一个语句后有分号隔开。

这样的函数就是立即执行函数。