画重点:js中函数是个对象;而函数名为栈中的指针指向堆中的函数对象

1:普通函数(函数声明):

函数声明总是以function关键词开始,反之为函数表达式

function obj(a,b){
    return a+b;
}
obj(1,2);//3

([3,4]).reduce(obj);//7
console.log(([1,2]).reduce(obj,10));//13

划重点: 

  1. 函数声明在当前作用域内创建了一个变量,其除了可以当做普通函数调用之外,还用于递归或者分离的事件监听。
  2. 函数表达式和箭头函数是无法创建并绑定函数名称作为函数变量。
  3. 函数提升仅适用于函数声明,而不适用于函数表达式.
  4. 函数声明可以被递归,就是说函数可以调用其本身。

reduce() :方法將一個累加器及陣列中每項元素(由左至右)傳入回调函数,將陣列化為單一值。

具体参考:Array.prototype.reduce()

递归小知识:

调用自身的函数我们称之为递归函数。在某种意义上说,递归近似于循环。两者都重复执行相同的代码,并且两者都需要一个终止条件(避免无限循环或者无限递归)。

一个函数可以指向并调用自身。有三种方法可以达到这个目的:

  1. 函数名
  2. arguments.callee
  3. 作用域下的一个指向该函数的变量名

小列子:

function obj(x) {
  if (x<=0) // "x<=0" 是退出条件(等同于 "!(x>0)")
    return;
  // 做些什么
  obj(x -1); // 递归调用
}
obj(10);

2:函数表达式

函数表达式:以var开始

var obj = function(o){
    alert(o);
}

函数表达式:map()的参数

var obj = ([1,2,3]).map(function(x){
	return x>1
})
console.log(obj);//(3) [false, true, true]

函数表达式:自执行函数

(function obj(mss){
	return console.log(mss*2)
})(5);//10

函数表达式:{}

var obj = {
	arr:[3,2,1],
	num:function(){
		return this.arr.map(function(x){
			return x>2
		})
	}
}
console.log(obj.num());//(3) [true, false, false]
  • num:function(){}:在num对象上创建一个方法
  • .map(function(x){}):当做一个方法函数

3:匿名函数

a:变量匿名函数:当函数中没有名称(名称和属性是一个空字符串)时,这个函数是一个匿名函数。

var obj = function(age){
	return age
}
obj.name//''

obj就是一个匿名函数,其obj.age的值为' '(空)。

b:命名函数表达式:当表达式中指定了一个名称时。

var getType = function funName(a) { 
	console.log(typeof funName === 'function'); //true
	return typeof a; 
} 
console.log(getType('1')); //  'string' 
console.log(getType); //  ƒ funName(variable) { 
	                  //console.log(typeof funName === 'function');
                      //return typeof variable; 
                      //}
console.log(typeof funName === 'function'); //false
console.log(getType('1')); //  'string' 
console.log(getType.name);//funName

function funName(a) { }为命名函数表达式。在函数作用域内存了一个funName变量。所以getType.name中的name属性就是函数的名称funName

4:嵌套函數

function addSquares(a, b) {
  function square(x) {
    return x * x;
  }
  return square(a) + square(b);
}
a = addSquares(2, 3); // returns 13
b = addSquares(3, 4); // returns 25
c = addSquares(4, 5); // returns 41

5:箭头函数

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++;
	  console.log(this.age);
  }, 1000);
}

var p = new Person();

结果为: 

6:方法定义可以在object literals和ES6 class时定义。

a:class定义

class Name {
			constructor(age){
				this.age = age;
			}
			nameObj(name){
				return `${name} is ${this.age}`
			}
		}
		var names = new Name('18'); 
		console.log(names.nameObj('Livia') );//Livia is 18

在构造器中填入Name函数传递过来的参数;实例化函数(new就是实例化函数)

b:object literals定义

var nameType ={
	arr:[],
	addName(...name){
		this.arr.push(...name);
	},
	getName(idx){
		return console.log(this.arr[idx],this.arr)//Nemo (3) ["Livia", "Tony", "Nemo"]
	}
}
nameType.addName('Livia','Tony','Nemo');
nameType.getName(2);

addName()和getName()方法在nameType对象使用方法定义。这些方法可以向这样调用nameType.addName()

传统方法定义和属性定义,是getName: function() {}这样定义的。

var getType = function(a) { 
			return  {
				getName: function() {
				  return a;
				}
			}
		}; 
		var getname = getType('1')
		console.log(getname.getName()); //1

参考:

声明JavaScript函数的六种方法

浅谈 JavaScript function 函数种类

总结一下js的函数类型