函数种类

名称 写法 解释
普通函数 function foo(){}
箭头函数 const foo = ()=>{}
generator function* foo(){} ES6的一种异步编程解决方案
constructor函数 class Foo{ constructor(){…} } 类的构造函数
async函数 async function foo(){} Generator 函数的语法糖

立即执行函数

通过立即执行函数(IIFE)可以实现块级作用域

  1. (function(){ var a = 1;
  2. //这里是块级作用域,里面定义的变量外部无法访问(除非return出去)
  3. })();
  4. console.log(a); // Uncaught ReferenceError: a is not defined

ES6以后已经有了块级作用域的概念了,因此IIFE已经逐渐退出历史舞台了。

闭包

闭包是指有权访问另一个函数作用域中的变量的函数。常见方式,就是在一个函数内部创建另一个函数

  1. var closure = function(){
  2. var count = 0;
  3. return function(){ return count ++; }}
  4. const fn = closure();
  5. console.log(fn()); // 0
  6. console.log(fn()); // 1
  7. console.log(fn()); // 2

fn = closure() 相当于 fn = function(){ return count ++; } , fn一直保持着对这个匿名函数的引用,而这个匿名函数又引用着count变量。因此count变量一直存在于执行上下文中,不会消失。
闭包通常用来创建内部变量,使得这些变量不能被外部随意修改,同时又可以通过指定的函数接口来操作

  1. var closure = (function(){ var foo = "foo";
  2. return { getFoo: function() { return foo },
  3. setFoo: function(newFoo){ return foo = newFoo } }
  4. })();
  5. console.log(closure.getFoo()); // foo
  6. console.log(closure.setFoo("newFoo")); // newFoo
  7. console.log(closure.foo); // 获取不到

纯函数

不会产生副作用的函数。
相同的输入,永远会得到相同的输出

  1. //这是个纯函数,满足上面两点条件
  2. const pureFn = function(a,b){ return a + b }
  3. //这个不是存函数,它的副作用就是修改了外部作用域的变量。
  4. let sum = 0;
  5. const plus = (a,b)=>{ sum = a + b;
  6. return sum;
  7. }

函数参数是对象

  1. function test(person) {
  2. person.age = 26
  3. person = { name: 'yyy',
  4. age: 30 }
  5. return person
  6. }
  7. const p1 = { name: 'yck',
  8. age: 25 }
  9. const p2 = test(p1)
  10. console.log(p1) // -> 26 'yck'
  11. console.log(p2) // -> 30 'yyy'

代码解释:
函数传参是传递对象指针的副本,因此函数里面如果修改了对象副本的话,原对象也会跟着修改的
函数里面的person属性被重新赋值一个新对象,因此p2就等于新对象。

箭头函数和普通函数的区别