JS函数知识点总结

  • JS函数知识点总结已关闭评论
  • 9 次浏览
  • A+
所属分类:Web前端
摘要

在JS中,函数实际上是对象,是Function类型的实例。语法:语法:因为函数本质上是对象,所以可以直接赋值给一个变量。这个变量将指向这个函数,调用函数时直接使用变量名即可。


函数

基本概念

  • 在JS中,函数实际上是对象,是Function类型的实例。

  • 函数名是指向函数对象的指针。
function sum(num1, num2){     return num1 + num2; } // 检查sum是否是Function类型的实例 console.log(sum instanceof Function); // true  let anotherSum = sum; // 指向同一个函数  console.log(anotherSum(1,2));   // 3 
  • 函数将若干条语句封装起来,可以提高代码的可复用性。

创建函数

函数声明

语法

function funcName(params){     // do something...     return something; } 

函数表达式

语法

let funcName = function(params){     // do something...     return something; } 

因为函数本质上是对象,所以可以直接赋值给一个变量。这个变量将指向这个函数,调用函数时直接使用变量名即可。

箭头函数

语法

let funcName = (params)=>{     // do something...     return something; } 

:箭头函数是ES6新加入的语法。

构造函数

语法

let funcName = new Function("param1","param2",...,"body"); 

构造函数接收任意多个字符串参数,最后一个是函数体,前面的是函数参数。

:这种写法不推荐,因为作为JS语句,它首先会被当做常规代码解析,然后再通过Function构造函数解析形成函数对象,性能较差。


箭头函数

箭头函数是ES6新增的语法。任何可以使用函数表达式的地方,都可以使用箭头函数。

语法格式

  1. 如果没有参数,要写括号:
let getRandom = () => {return Math.random();}; 
  1. 如果参数只有一个,可以不写括号:
let double = x => {return x*2; }; 
  1. 如果有多个参数,要写括号:
let sum = (x, y) => {return x + y; }; 
  1. 如果函数体有多条语句,则需要大括号:
let division = (a, b)=>{     if(b === 0){         console.error("除数不能为零");     }else{         return a/b;     } } 
  1. 如果函数体只有一条语句,可以不写大括号,此时会隐式返回这行代码的值:
let double = x => x*2; 

特点

  • 箭头函数语法简洁。

  • 箭头函数不能使用argumentssuper,也不能用作构造函数,且箭头函数没有prototype属性。


参数列表

JS的函数参数和大多数其他语言不同,JS中的函数参数定义是无关紧要的。

假如定义函数时预设有两个参数,而调用时传入了0个、1个或者3个参数,解释器都不会报错。

原因是使用function关键字定义的函数,可以在函数内部访问arguments对象,从中获取传入的参数。

function testArgs(){     console.log(arguments); }  testArgs(1,2,3,4,5,6);  testArgs(1,"Hello",true); 

arguments是一个类数组对象,它并不是Array的实例对象,并不是真正的数组,但是它具有类似数组的一些操作,比如可以像数组一样通过[]访问元素的值,可以通过length获取元素个数。

可以通过arguments[0]访问到传入的第一个参数,通过arguments.length获取传入多少个参数。

箭头函数的参数

:箭头函数不能使用arguments,所以箭头函数需要多少参数需要在定义函数时就写明。

不存在函数重载

在其他语言比如C++Java中,存在函数重载,即可以存在多个函数名相同的函数,只要它们的参数个数、参数类型不一样。在调用函数的时候,会根据传入的参数数据类型,匹配上对应的函数。

显然,在JS中,函数的参数列表是随意的(参数个数与参数数据类型都是随意的),也就不存在函数重载了。

:在JS中,如果有多个函数名相同的函数定义,只有最后一个是有效的,前面的定义都将被覆盖。

默认参数值

// 返回一个由随机数组成的数组,默认长度为5 function getRandomArray(length = 5){     const arr = new Array();     for(let i=0;i<length;i++){         arr.push(Math.floor(Math.random()*100));     }     return arr; }  const arr1 = getRandomArray(); console.log(arr1); //[76, 86, 60, 21, 37]  const arr2 = getRandomArray(10); console.log(arr2); //[18, 98, 76, 43, 77, 24, 44, 74, 58, 3] 
  • 在函数参数后面使用=就可以为其设置默认值。

函数声明和函数表达式

  • 函数声明指通过function functionName(){}来得到一个函数.

  • 函数表达式是指通过function(){}创建一个匿名函数,再讲这个匿名函数赋值给一个变量functionName.

区别

函数声明提升

所有函数声明在JS引擎执行代码之前会被提升到代码顶部,即以下两段代码是等价的。

console.log(sum(1,2));    // 不会报错,因为sum会被提升到顶部 function sum(x,y){     return x+y; } 
function sum(x,y){     return x+y; } console.log(sum(1,2)); 

而函数表达式不会被提升:

console.log(sum(1,2));    // 报错 let sum = function(x,y){     return x+y; } 

sum作为一个变量:

  • 如果使用var声明会被提升,但是定义不会被提升,undefined无法被调用;

  • 如果使用let则声明和定义都不会被提升,一个未声明的变量显然无法被调用。


函数作为值

函数名是一个变量,因此函数可以作为函数参数传递给另一个函数,并且函数也可以作为一个函数的返回值

回调函数

如果当前无法决定调用哪个函数,可以先把函数作为参数传递,等到可以做出明确的选择时,再回过头来调用这个函数。这种情况下作为参数传递的函数就被叫做回调函数(callback).

典型应用

向后端接口发送网络请求时,一般会附带上两个回调函数,一个success函数,一个error函数。在发送网络请求时,是无法确定请求是否发送成功的。只有拿到了返回结果,才能确定执行success函数或error函数。


闭包

闭包是指引用了另一个函数作用域中变量的函数。通常在嵌套函数中实现。

// 获取累加器 function getAccumulator(){     let num = 0;    // 内部属性     return function(){    // 返回一个函数         return num++;     } }  // 调用函数获取累加器 let add = getAccumulator(); console.log(add());    // 0 console.log(add());    // 1 console.log(add());    // 2     console.log(add());    // 3 console.log(add());    // 4 

在函数getAccumulator的作用域中,有一个num属性,而返回的函数中,引用了这个num. 即返回的这个函数引用了另一个函数作用域中的变量.

num这个变量和add函数绑定在了一起,当getAccumulator执行结束后也不会被回收,并且无法被直接访问。


立即调用的函数

立即调用的函数表达式(IIFE, Immediately Invoked Function Expression)

ES5没有块级作用域,可以使用立即调用的函数表达式来模拟块级作用域。

var funcName = function(){...}; funcName(); 

使用立即调用的函数表达式可以省略一个不必要的函数名。

(function(){ ... })(); 

ES6之后,IIFE就没有那么必要了,因为可以很方便地使用块级作用域。