【JavaScript】深度理解js的函数(function、Function)

简言

学了这么久的JavaScript,函数在JavaScript中最常用之一,如果你不会函数,你就不会JavaScript。
函数就是Function对象,一个函数是可以通过外部代码调用的一个“子程序”,它是头等(first-class)对象,因为它们可以像任何其他对象一样具有属性和方法。瞧瞧它的定义,注定它能做很多事情。
**函数是函数名、参数和函数体组成,然后由function声明。**我们一般说函数是指普通函数,还有另一种函数叫做生成器函数,这个生成器比较比较高级,生成器函数在执行时能暂停,后面又能从暂停处继续执行,这里不展开描述。

函数

在 JavaScript 中,每个函数其实都是一个Function对象。函数默认返回undefined

定义函数

声明一个函数(Function对象)有很多种方式。如果一个函数中没有使用 return 语句,则它默认返回undefined。要想返回一个特定的值,可以使用return 返回。

function声明

由function声明的函数,函数名会提升这个作用域的顶部,即在函数定义前也能使用。

function name([param[, param[, ... param]]]) { statements }
  • name 函数名。
  • param 传递给函数的参数的名称。
  • statements 组成函数体的声明语句。

函数表达式

由函数表达式创建的函数,函数名不会会提升,即必须在创建之后使用。

var myFunction = function name([param[, param[, ... param]]]) { statements }
  • name 函数名,可以省略,省略了后是匿名函数。
  • param 传递给函数的参数的名称。
  • statements 组成函数体的声明语句。

立即调用函数(IIFE)

当函数只使用一次时,通常使用IIFE (Immediately Invokable Function Expressions)。意思是当这个js文件被执行时调用一次。

(function () {
  statements;
})();
  • statements 组成函数体的声明语句。

箭头函数表达式(=>)

箭头函数是函数

var fn = ([param] [, param]) => { statements } param => expression
  • param 参数名称。
    零参数需要用 () 表示。只有一个参数时不需要括号。(例如 foo => 1)
  • statements or expression
    多个声明 statements 需要用大括号括起来,而单个表达式时则不需要。表达式 expression 也是该函数的隐式返回值。

Function构造函数 (不推荐)

函数(Function对象)可以用 new 操作符创建。
把 Function 的构造函数当作函数一样调用 (不使用 new 操作符) 的效果与作为 Function 的构造函数调用一样。

new Function (arg1, arg2, ... argN, functionBody)
  • arg1, arg2, … argN
    函数使用零个或多个名称作为正式的参数名称。每一个必须是一个符合有效的 JavaScript 标识符规则的字符串或用逗号分隔的字符串列表,例如“x”,“theValue”或“a,b”。

  • functionBody
    一个构成的函数定义的,包含 JavaScript 声明语句的字符串。

函数参数

函数参数(形参)一个重要的概念,它是函数体与外面作用域交互的媒介或桥梁。普通的参数由js各种类型定义,除此之外,它还有this、剩余参数和arguments对象。

形参

普通的参数由js各种类型定义,定义的参数可以在函数内使用,想传啥就传啥。
调用传参时,则按你定义参数的顺序传。

function fnParams(
  name,
  age = 18,
  object = {
    label: 'object形参',
  },
  fn = () => {},
  date = new Date(),
  arr = []
) {
  console.log(name, age, object, fn, date, arr)
}
fnParams()

调用时不传参数,参数为undefined,有默认值则值为默认值。
【JavaScript】深度理解js的函数(function、Function)_第1张图片

arguments对象

arguments 是一个对应于传递给函数的参数的类数组对象。
arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。
箭头函数使用arguments在浏览器环境下会报错。

function fnParams(
  name,
  age = 18,
  object = {
    label: 'object形参',
  },
  fn = () => {},
  date = new Date(),
  arr = []
) {
  console.log(name, age, object, fn, date, arr)
  console.log(arguments)
}
fnParams('zsk', () => {})

const fn = (name) => {
  console.log(name, arguments)
}
fn('zsk')

【JavaScript】深度理解js的函数(function、Function)_第2张图片

剩余参数

剩余参数是es6的,剩余参数语法允许我们将一个不定数量的参数表示为一个数组。
如果函数的最后一个命名参数以…为前缀,则它将成为一个由剩余参数组成的真数组,其中从0(包括)到theArgs.length(排除)的元素由传递给函数的实际参数提供。

function(a, b, ...theArgs) {
  // ...
}

如上,theArgs就是剩余参数,它是一个数组,包含那些没有对应形参的实参,默认值[],不能更改默认值。

let fn = function (a, ...args) {
  console.log(a, args)
}
fn(1, 2, 3)

在这里插入图片描述

this

在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)。this 不能在执行期间被赋值,并且在每次函数被调用时 this 的值也可能会不同。可以使用 bind 方法来设置函数的 this 值,而不用考虑函数如何被调用的。箭头函数本身没有this,值为创建时外层上下文对象。

function fn2() {
  console.log('fn2::', this)
  const arrowFn = (a = 1) => {
    console.log('()=>{} ::', this)
  }
  const fn = function (a = 1) {
    console.log('fn::', this)
  }
  arrowFn()
  fn()
  let o = {
    fn: fn,
  }
  o.fn()
}
fn2()

【JavaScript】深度理解js的函数(function、Function)_第3张图片
bind()、call() 和 apply()方法可以改变this值。

a = 1
const obj = {
  a: 2,
}
function fn3() {
  // 'use strict'
  console.log(this.a)
  return this
}
fn3()

fn3.bind(obj)()
fn3()
fn3.bind()()
fn3.call(obj, 1, 2)
fn3()
fn3.call()

fn3.apply(obj, [1, 2])
fn3()
fn3.apply()

【JavaScript】深度理解js的函数(function、Function)_第4张图片

函数体

函数体没啥说的,什么都可以写。自己都可以调用。。。,递归就是这么来的。
如果有return 的话,可以返回函数,例如实现闭包、函数柯里化、高阶函数等。

函数属性

另外,函数本身还有一些属性和方法:

  • name 返回函数定义的名称。
  • length 只读属性,表示函数形参的个数
  • prototype 函数的原型对象
  • toString() 返回函数完整的源代码字符串

结语

有了函数,js就算玩出花来,也可以有条理性。

你可能感兴趣的:(JavaScript,javascript,开发语言,ecmascript)