无论你承不认可,任何人在社会环境中都会被潜在的分为三六九等,而JavaScript中的函数就是一等公民。ajax
函数是以function关键字定义的一组用来执行特定功能的语句。定义函数有三种方式:函数声明,函数表达式和构造函数。编程
函数声明promise
function sum(num1,num2){ return num1+num2; }
函数表达式闭包
var sum=function(num1,num2){ return num1+num2; }
构造函数编程语言
var sum = new Function('num1', 'num2', 'console.log( num1 + num2)'); sum(2, 6);
构造函数的第三个参数是一个包括JavaScript语句的字符串。函数式编程
函数没有重载函数
function addNumber(num){ return num+10; } function addNumber(count){ return count+20; } addNumber(10);//30
上面两个函数名同样,可是参数及计算方式不同,结果倒是执行第二个函数,由于后面的函数覆盖了前面的函数。实际上与下面的代码没有区别:指针
var addNumber=function(num){ return num+10; }; addNumber=function(count){ return count+20; } addNumber(10);//30
能够把函数名理解为指针,同一个函数名指向同一个指针。code
函数声明与函数表达式的区别
一、函数声明是函数名跟在function后面,函数表达式是把一个函数赋值给一个变量;
二、函数声明能够在代码的任何位置,调用不受限制(可访问做用域),函数表达式必须在调用前定义。对象
console.log(addNumber(10));//20 function addNumber(num){ return num+10; }
console.log(addNumber(10));//Uncaught TypeError: addNumber is not a function var addNumber=function(num){ return num+10; };
再看一段代码
function addNumber(num){ return num+10; } var addAnotherNumber=function addNumber(count){ return count+20; } console.log(addAnotherNumber.name);//addNumber
函数表达式不必定是匿名函数,定之后函数表达式的函数名是function后面的函数名。
重点注意:全部函数的参数都是按值传递
也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另外一个变量同样。基本类型值的传递如同基本类型变量的复制同样,而引用类型值的传递,则如同引用类型变量的复制同样。
要理解上面这段话有点费劲。既然是复制,不是基本类型复制后互不影响,引用类型复制后会互相影响吗,为何是按值传递不是按引用传递?
在函数传递一个基本类型参数时,被传递的值会复制给函数内一个局部变量(arguments中的一个),传递一个引用类型的值时,会把该引用类型的指针地址复制给函数内一个局部变量,当局部变量发生变化时会反映在函数的外部。举个例子:
函数参数传递一个数字,函数内部修改后
function addNumber(num){ num=num+10; console.log(num);//20 } var num=10; addNumber(num); console.log(num);//10
若是传递的是一个object,在函数内部修改对象属性时,外部对象也发生变化了。
function setName(obj){ obj.name="李四" console.log(obj.name);//李四 } var obj={ name:"张三" }; setName(obj); console.log(obj);//obj.name="李四"
这不是与上面说的还值传递自相矛盾?咱们修改几行代码再看:
function setName(obj){ obj.name="李四" obj=new Object(); obj.name="王麻子"; console.log(obj.name);//王麻子 } var obj={ name:"张三" }; setName(obj); console.log(obj);//obj.name="李四"
这段代码与上面的区别是obj传递给函数后,其属性name被从新赋值,建立一个新对象赋值给obj,再修改obj.name。若是obj是按引用传递,那么修改obj后应该也反映到函数外部,但原始引用并无发生变化。缘由是在函数内部重写obj后实际上建立了一个新的对象引用,该变量引用是局部变量,函数执行完后即被销毁。
总之,函数参数都是局部变量。
回到主题,JavaScript函数为何是一等公民?
在编程语言中,一等公民有几个条件:能够做为函数参数,能够做为函数返回值,能够赋值给变量。
按照上面的条件,其实JavaScript中的数据均可以认为是一等公民~
不管是基础数据类型仍是引用类型都是知足上面条件的。通常说JavaScript函数是一等公民其实是相对其它编程语言而言,由于并非全部的编程语言中函数都能知足上述条件。
下面具体介绍下JavaScript中函数是如何知足上述三个条件的。
实际上就是咱们常常说的函数回调。举个例子:
element.addEventListener(event,eventHandler,useCapture)
其中eventHandler就是做为函数参数,元素监听到对应事件后进行调用。这种状况在JavaScript中很是常见。好比ajax,promise等等。
好比闭包:
function getName(){ var name="jack"; return function(){ return name; } } var getNameFun=getName(); var name=getNameFun(); console.log(name);//'jack'
正常状况下函数外部是没法访问函数内部变量的,可是经过返回一个引用函数内部变量的函数就能够实现,也就是咱们常说的闭包。
var getTime=function(){ console.log(new Date().getTime()); } setInterval(getTime,1000);
将函数做为变量赋值给变量getTime,而后做为参数传递给setTimeInterval。
函数做为一等公民是函数式编程的基础。高阶函数就是将函数做为参数的函数,React中的高阶组件也能够理解是高阶函数。