函数

81 阅读4分钟

在js中,每一个函数都是Function类型的实例,都是对象

定义函数

以函数声明的方式定义

function sum(a,b){
  return a + b
}

以函数表达式定义

let sum = function(a,b){
  return a + b
}

JavaScript引擎在任何代码执行之前,会先读取函数声明,并在执行上下文中生成函数定义。而函数表达式必须等到代码执行到它那一行,才会在执行上下文中生成函数定义

    console.log(sum(1,2)) // 正常执行
    function sum(a,b){
      return a + b
    }
    console.log(sum(1,2)) // 报错
    let sum = function(a,b){
      return a + b
    }

1732932694829.jpg

以箭头函数的方式定义

let sum = (a,b) => a + b

箭头函数

箭头函数是ES6新增的一种定义函数的方式。箭头函数在很大程度上与使用函数表达式定义的函数是相同的,但也有一些不同之处

如果只有一个参数时,可以不使用括号

let sum = x =>{ return 3*x }

箭头函数也可以不使用大括号,此时箭头后面只能包含一行代码,同时隐式的会返回这行代码的值

let sum = (x)=> 3*x

箭头函数不能使用arguments、super和new.target,不能用作构造函数,不包含prototype属性

函数参数

在js中,函数并不关心参数的个数,也不关心参数的类型。之所以会这样,是因为在编译时函数参数在内部表现为一个数组。函数被调用时总会接收一个数组,但函数并不关心这个数组中包含什么

在使用function定义的(非箭头)函数时,可以在函数内部可以访问到一个arguments对象,从中取出传入的参数

function test(a,b){
  console.log(arguments)
}

1732867234880.jpg

箭头函数没有arguments

arguments不反应默认参数,arguments只和调用函数时相关

function sum(a = 1,b = 2){
  console.log(arguments)
}

1732868108386.jpg

1732868077404.jpg

默认参数作用域与暂时性死区

给多个参数设置默认值就和使用let按顺序定义变量一样。因此:

  1. 后定义的参数可以使用先定义的
function sum(a= 1, b = a){
  return a+b
}

1732868593991.jpg

  1. 先定义的不能使用后定义的
function sum(a= b, b = 1){
  return a+b
}

1732868673762.jpg

  1. 不能使用函数体中定义的变量
function sum(a= 1, b = c){
  let c = 2
  return a+b
}

1732868824868.jpg

扩展参数

let values = [1,2,3,4]
function sum(){
  let sum = 0
  for(let i = 0;i<arguments.length;++i){
    sum += arguments[i]
  }
  return sum
}

sum(...values) // 将传入的参数扩展

参数收集

function sum(...data){
  console.log(data)
}

sum(1,2,3) // [1,2,3] // 将入参收集在一个数组里

function sum1(a,...data){
  console.log(a)
  console.log(data)
}

sum1(1,2,3,4) // 1 [2,3,4]

this

this是函数内部一个重要的对象,箭头函数和普通函数的this指向是有所不同的

window.color = 'red'
const o = {
  color:'blue'
}
function sayColor(){
  console.log(this.color)
}
sayColor()   // red
o.sayColor = sayColor
o.sayColor() // blue

在普通函数中,this指向的是把函数当做方法调用时的上下文对象

window.color = 'red'
const o = {
  color:'blue'
}
let sayColor = ()=> console.log(this.color)

sayColor()   // red
o.sayColor = sayColor
o.sayColor() // red

在箭头函数中,this指向的是定义函数时的上下文对象

new.target

函数既可以作为普通函数调用,也可以作为一个构造函数用于创建新对象。当使用new调用时,new.target指向被调用的构造函数;当作为普通函数调用时,为undefined

函数的属性和方法

length

定义函数时声明的参数个数

function sum(a,b){
}

console.log(sum.length) // 2

prototype

prototype是保存引用类型所有实例方法的地方,这意味着toString()等方法全都在这上面,进而由所有实例共享

prototype是不可枚举的,所以不能使用for-in循环出这个属性

apply()、call()和bind()

在一般情况下,标准函数的this是由函数被调用时决定的,但js中也有显式的控制this的方法:apply()、call()、bind()

apply()

apply接收一个参数数组

function greet(address,school){
  console.log(this.name,this.age,address,school)
}

const stu = {
   name:'momo',
   age:18
}

greet.apply(stu,['beijing','xtu']) // momo 18 beijing xtu

call()

call与apply类似,区别在于传参的时候只能一个一个传

function greet(address,school){
  console.log(this.name,this.age,address,school)
}

const stu = {
   name:'momo',
   age:18
}

greet.call(stu,'beijing','xtu') // momo 18 beijing xtu

bind()

bind会返回一个新函数,这个新函数永久的指向被传入的第一个参数

function greet(address,school){
  console.log(this.name,this.age,address,school)
}

const stu = {
   name:'momo',
   age:18
}

const _greet = greet.bind(stu)
_greet('beijing','xtu') // momo 18 beijing xtu