JavaScript之函数为何是一等公民

无论你承不认可,任何人在社会环境中都会被潜在的分为三六九等,而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中的高阶组件也能够理解是高阶函数。

相关文章
相关标签/搜索