函数(回顾)

文章详细介绍了JavaScript中的函数,包括函数的作用、创建方式(声明、表达式、构造器)、参数形式、返回值、以及ES6的新特性如剩余参数。还讨论了函数的执行上下文,如arguments对象、函数命名规则、立即执行函数(IIFE)及其变种。此外,重点讲解了高阶函数的概念和柯里化技术,展示了如何实现柯里化函数。

函数

定义

一个处理事情的方法

作用

函数的意义在于封装
减少页面中冗余代码,提高代码重复利用率 ==》 '低耦合,高内聚'

函数的两部分

  1. 创建函数 function 函数名 (形参) {…}
    过程:开辟一个堆内存,把函数体的代码当做字符串存在堆中,把堆地址和变量相关联
    注意:只创建函数,其实就是创建了存储一个字符串的堆,并没有实际作用
  2. 执行函数 函数名(实参)
    依赖条件:栈内存,供代码执行的上下文
    作用:把创建的函数执行
    注意:函数内部执行该函数会无限递归
var test = function abc() { abc() }
test(); // 进入递归,造成栈溢出

参数形式

形参:入口在JS函数中被称为形参,用来’存储执行函数时传递进来的信息’ ==》变量
实参:传递的具体值在JS函数中被称为实参 ==》具体传递的值

返回值

定义:JS函数的出口
作用:
1.基于 return 把变量的值暴露给外面使用
2.终止函数
注意:如果函数没有写 return,默认返回 undefined

创建函数的3种方式

  1. 函数声明

注意:if 括号中一定不能声明函数,会独自创建一个作用域

function test () { ... }
  1. 函数表达式
  • 命名函数表达式
var test = function abc () { ... }
  • 匿名函数表达式
var test = function () { ... }
  • 箭头函数
let test = () => { ... }
  1. 函数构造器Function

注意:此方法不支持闭包,只能访问自身参数列表中的变量和全局变量

var test1 = new Function('a,b','console.log(a + b)')
//相当于 function test (a,b) { console.log(a + b) }
var test2 = new Function('console.log(a + b)')
//相当于 function test () { console.log(a + b) }

函数声明

函数命名规则

和变量的命名规则,基本一样

(1)不能以数字开头
(2)可以以字母, _ , $ 开头
(3)要有语义化:
==>指命名需要有意义
需要考虑到要结构化
并且,必须是英文,不能用中文(例: J_header)
(4)变量命名遵循:
==>小驼峰,首个字母小写,后面单词字母大写
    例: function myFirstName(){}
(5)下划线命名法
function my_first_name(){}
(6)总之按所在公司开发规定来
(7)不能使用关键字,保留字(例:float 就是保留字)

命名函数表达式

函数作用域外部自动忽略函数名
会创建一个特定的辅助对象,将函数名作为属性存储,内部可以访问,并且是只读的

  1. name属性
var test = function abc() { ... }
console.log(test.name); // 'abc'
adc();// adc is not defined
  1. 函数内部可以调用
var test = function abc() { abc() }
test();// Maximum call stack size exceeded  无限递归,造成栈溢出
  1. 特殊立即执行函数也是命名函数表达式
    相关题目链接
var a = 1;
;(function a () {
  a = 2;
  console.log(a);//f a(){}  函数名是只读的,无法修改
  delete a;
  console.log(a);//f a(){}  函数名是只读的,无法删除
})

函数参数

形参与实参的映射关系

1.设定形参变量,但执行没有传递对应的值,则形参默认值为 undefined
2.形参只有两个,实参有三个,第三个并没有对应的形参接受(但是传递给函数了)

arguments

定义:函数内置实参集合 ==》 类数组
作用:包含了所有传递进来的实参信息,与是否定义形参无关
注意:ES6的箭头函数中没有arguments

function test() { console.log(arguments) }
test(1,2,3);//Arguments [1, 2, 3] 类数组

argument.length 传递实参的个数

function sum(a,b,c,d){
  if(sum.length > arguments.length){
    console.log('形参多了');
    //sum.length  形参列表
  }else if(sum.length < arguments.length){
    console.log('实参多了');
  }else{
    console.log('相等');
  }
}

argument.callee 参数所属的当前执行的函数作用域

function test(){ console.log(arguments.callee == test); } 
test();//true

ES6的剩余运算符 …

定义:把传递进来的实参信息,都以数组的形式保存在args变量中

function test(...args) { console.log(args) }
test(1,2,3);// [1, 2, 3] 

组合常规参数和剩余参数
一个常规参数,获取一个参数的值,剩余的参数由…argus接受

function test(a, ...args) { console.log(args) }
test(1,2,3);// [2, 3]

剩余参数和arguments的区别

1.剩余参数只包含没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参
2.arguments对象是一个类数组,而剩余参数是数组

立即执行函数

定义

函数声明以后立即执行该函数 ==》函数表达式

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

特殊立即执行函数

带有函数名的立即执行函数 ==》命名函数表达式
函数作用域外部自动忽略函数名
会创建一个特定的辅助对象,将函数名作为属性存储,内部可以访问,并且是只读的

var a = 1;
;(function a () {
  a = 2;
  console.log(a);//f a(){}  函数名是只读的,无法修改
  delete a;
  console.log(a);//f a(){}  函数名是只读的,无法删除
})

使函数声明变成表达式的4种方法

  1. 赋值符号
  2. 括号
  3. 逻辑运算符 & | && ||
  4. 数学运算符 + - * /
// 赋值符号
var a = function () { ... }
a()
// 括号
(function () { ... } ())
// 逻辑运算符
0&function () { ... } ()
0|function () { ... } ()
1&&function () { ... } ()
0||function () { ... } ()
// 数学运算符
+function () { ... } ()
-function () { ... } ()
0*function () { ... } ()
0/function () { ... } ()

函数执行完出栈问题

// 其中test 函数执行完,没有产生闭包,直接出栈销毁
var test = function test(){
 console.log('a');
}();
console.log(test);
// a  undefined

高阶函数

概念

Higher-order function,一个函数就可以接收另一个函数作为参数的函数,像数组的mapreducefilter这些都是高阶函数

// 简单的高阶函数
function add(x, y, f) {
    return f(x) + f(y);
}

//用代码验证一下:
add(-5, 6, Math.abs); // 11

柯里化函数

概念

Currying,把接受多个参数的参数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术

作用

参数复用,提前返回和延迟执行

实现函数的柯里化

// 实现函数柯里化
function curry(fn) {
    const fnArgsLength = fn.length // 传入函数的参数长度
    let args = []
    function calc(...newArgs) {
        // 积累参数保存到闭包中
        args = [...args, ...newArgs]
        // 积累的参数长度跟传入函数的参数长度对比
        if (args.length < fnArgsLength) {
            // 参数不够,返回函数
            return calc
        } else {
            // 参数够了,返回执行结果
            return fn.apply(this, args.slice(0, fnArgsLength)) // 传入超过fnArgsLength长度的参数没有意义
        }
    }
    return calc// 返回一个函数
}
function add(a, b, c) {
    return a + b + c
}
// add(10, 20, 30) // 60
var curryAdd = curry(add)
var res = curryAdd(10)(20)(30) // 60
console.info(res)

实现计算累加

实现 fun(1).add(1).add(2).res() 为 4

const fn = (num) => {
    return {
        add: (n) => fn(num + n),
        mine: (n) => fn(num - n),
        take: (n) => fn(num * n),
        divide: (n) => fn(num / n),
        res: () => num
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柳晓黑胡椒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值