1.7JavaScript语言的函数(Function)

1.函数声明

函数声明是 Function 类型的实例,函数名相当于存储这个实例的变量或常量。

//函数声明定义方式
function 函数名(值形参名, 默认值形参名 = 默认值, ...剩余形参名) {
  //函数体
}
//函数表达式定义方式
//命名函数
const Rectangle = function Rectangle2(值形参名, 默认值形参名 = 默认值, ...剩余形参名) {
  //函数体
};
console.log(Rectangle.name);  // 输出函数名:Rectangle2

//未命名/匿名函数
const Rectangle = function (值形参名, 默认值形参名 = 默认值, ...剩余形参名) {
  //函数体
};
console.log(Rectangle.name);  // 输出函数名:Rectangle

2.函数分类

2.1全局函数

名称修饰符
全局函数——————

2.2成员方法

名称修饰符
静态方法(类)static
实例方法(类)——————
静态访问器属性(类)static
实例访问器属性(类)——————
方法(对象字面量)——————
访问器属性(对象字面量)——————

2.3局部函数

名称修饰符
嵌套函数——————

3.函数名

既然函数声明是 Function 类型的实例,则函数名就是存储这个实例的变量。

既然函数名就是变量,则函数名就可以用在任何可以使用变量的地方。

function sum(num1, num2) {
  return num1 + num2;
}

//等同于
let sum = new Function("num1", "num2", "return num1 + num2");

3.1赋值场景

就跟变量一样,作为变量的函数也可以赋值给另外一个变量,此时这两个变量都指向同一个函数。

注意:等号右边是函数声明,而不是函数调用,所以函数名后面没有圆括号 ()

function sum(num1, num2) {
  return num1 + num2;
}

console.log(sum(10, 10));  // 20

let anotherSum = sum;
console.log(anotherSum(10, 10));  // 20

3.2回调函数场景

就跟变量一样,不仅可以把一个函数作为参数传递给另外一个函数,而且还可以在一个函数中将另外一个函数作为返回值返回给调用者。

只要满足其一,我们就可以将这种编程风格称为高阶函数风格(Higher Order Function Style),函数A称为高阶函数(Higher Order Function),函数B称为回调函数(Callback Function)。

注意:传递或返回的是函数声明,而不是函数调用,所以函数名后面没有圆括号 ()

//作为参数
function A(someFunction, someArgument) {
  return someFunction(someArgument);
}

function B(num) {
  return num + 10;
}

console.log(A(B, 10));  // 20
//作为返回值
function A() {
  return function (num) {
    return num + 10;
  };
}

let B = A();
console.log(B(10));  // 20

4.形参分类

注意:调用剩余形参时,剩余形参名的前面无 ...

名称修饰符
值形参——————
默认值形参——————
剩余形参...

5.函数签名

在很多其它编程语言里,函数签名(由函数名、形参类型、形参个数组成)就好比是函数的身份证一样,可以通过比较函数签名来判断是否是同一个函数。

JavaScript 语言的函数隐式地只有一个形参,arguments 就是这个形参。arguments 为一个类似于数组的对象,为了易于理解,我们可以暂且称为 arguments 数组。arguments 数组内的元素为所有传递给函数的实参,函数只有验证传递过来的是不是 arguments 数组的机制,并没有验证 arguments 数组内元素的类型和个数的机制。

函数的显式的形参只是为了方便调用才写出来的,并不是必须写出来的,可以使用类似数组中变量名后跟方括号 [] 包含索引来访问 arguments 数组中索引对应的实参。第一个实参是 arguments[0],第二个实参是 arguments[1],以此类推。

所以,JavaScript 语言的函数没有函数签名,或者说 JavaScript 语言的函数的函数签名只是函数名。

6.实参传递方式

实参的类型无需与默认值形参的类型兼容。

实参的个数可以小于、等于、大于形参的个数,甚至可以没有实参。

实参的传递只支持按位置从左往右依次传递方式,不支持按命名传递方式。

实参的传递只支持按值传递方式,不支持按引用传递方式。

注意:不给值形参传递值,相当于给值形参传递了 undefined 值。不给剩余形参传递值,相当于给剩余形参传递了空数组。这就类似于变量已声明未初始化。

注意:给默认值形参不传递或传递 undefined 值,都会触发默认值形参的默认值。给默认值形参传递 null 值,不会触发默认值形参的默认值。

7.函数返回方式

按值返回。

8.函数返回值

参见 return 语句。

9.调用函数

//无实参
函数名();

//有实参
函数名(实参);

10.箭头(Arrow)函数

零个或多个形参时必须使用圆括号 () ,只有一个值形参时可以省略圆括号 (),只有一个默认值形参或者只有一个剩余形参时不可以省略圆括号 ()

如果有花括号 {},则花括号 {} 内就跟普通函数一样。

如果没有花括号 {},则胖箭头 => 后面就只可以有单条语句,比如一个赋值操作语句,或者一个表达式。因为 return 关键字只可以在函数体内使用,此时不可以使用 return 关键字。而且,此箭头函数会隐式地返回此单条语句的返回值。

const 函数名 = (值形参名, 默认值形参名 = 默认值, ...剩余形参名) => { 
  //函数体
};
//赋值操作语句
let person = {};
let setName = (p) => p.name = "张三";
setName(person);
console.log(person);  // { name: "张三" }

11.立即调用的函数表达式

立即调用的函数表达式(Immediately Invoked Function Expression,IIFE),又被称为立即调用的匿名函数。在第一组圆括号内的是匿名函数或箭头函数的声明,而不是函数调用。紧跟在第一组圆括号后的第二组圆括号会立即调用前面的函数表达式。

//未命名/匿名函数形式
(function(形参) {
  //函数体
})(实参);

//箭头函数形式
((形参) => {
  //函数体
})(实参);

12.函数递归(Recursive)

一个函数声明的函数体内有此函数的函数调用,此时便形成了函数递归(Recursive)。

function factorial(n) {
  if (n === 0 || n === 1) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

13.闭包(Closure)

闭包是 JavaScript 最强大的特性之一。JavaScript 允许函数嵌套,并且内部函数具有对外部函数内定义的所有变量和函数(以及外部函数有权访问的所有其它变量和函数)的完全访问权。

但是,外部函数不能访问内部函数中定义的变量和函数。这为内部函数的变量提供了一种封装。

此外,由于内部函数可以访问外部函数的作用域,因此,如果内部函数生命周期大于外部函数时,那么在外部函数中定义的变量和函数将比外部函数执行的持续时间更长。当内部函数以某种方式可用于外部函数之外的任何作用域时,此时就创建了闭包。

//外部函数定义了一个名称为name的变量
const pet = function (name) {
  const getName = function () {
    //内部函数可以访问外部函数名称为name的变量
    return name;
  };
  return getName;  //返回内部函数,从而将其暴露给外部作用域
};
const myPet = pet("Vivie");

console.log(myPet());  // "Vivie"

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/javascript/javascriptlang/4731.html

(0)
huoxiaoqiang的头像huoxiaoqiang
上一篇 2020年8月6日
下一篇 2020年8月8日

相关推荐

  • 2.8JavaScript语言的Iterable和Iterator接口

    1.Iterable接口 方法 返回值 @@iterator 返回一个实现了Iterator接口的对象。 2.Iterator接口 方法 是否必须实现 返回值 next() 必须 返回一个实现了IteratorResult接口的对象。 return() 非必须 返回一个实现了IteratorResult接口的对象。 t…

  • 2.10JavaScript引用类型之期约(Promise)

    Promise 对象用来表示异步操作的结果。 1.Thenable接口 方法 描述 then(onFulfilled, onRejected) 接收两个函数作为参数:一个用于处理承诺(promise)兑现时(fulfilled),一个用于处理承诺(promise)拒绝时(rejected)。 2.Promise类 Pr…

  • 2.11JavaScript语言的异步函数

    1.异步函数声明 如果您想声明一个异步函数,只需要首先在普通函数前添加一个 async 关键字,然后在函数体内至少包含一个 await 关键字即可。普通函数支持函数声明、函数表达式、箭头函数、立即调用的函数表达式和实例方法。 2.await表达式 await 关键字后的表达式可以是 实现了 Thenable 接口的对象…

发表回复

登录后才能评论