JS函数全解、闭包、递归、柯里化

文章探讨了函数返回值受调用时参数、定义时环境的影响,解释了闭包的概念及其特点,介绍了JavaScript中函数(包括箭头函数)的特性,讨论了this的确定方式以及递归算法在渲染树组件和性能优化中的应用,还提到了React的memo和柯里化的概念。

函数的返回值由什么确定? 

影响因素:

1.调用时输入的参数params

2.定义时的环境env

let x1 = 'x'
let a = '1'
function f1(x1){
    return x1 + a
}

a = '3'
{
    let a = '2'
    
    console.log(f1('x'))   // 'x3'
    
}
a = '4'

// 这个例子说明a是定义时的a ,而不是执行时的a
let x1 = 'x'
let a = '1'
function f1(c){
    c()
}

{

    let a = '2'
    function f2(){
        console.log(x1+a)  // x2
        
    }
    f1(f2)
}

闭包

如果在函数里面可以访问外面的变量,那么这个函数+这些变量=闭包

闭包特点:

1 能让一个函数维持住一个变量

2 但并不能维持这个变量的值

3 尤其是变量的值会变化的时候

JS里的函数特点:

  • 支持闭包
  • 创建函数作用域
  • *有arguments
  • *有this
  • *支持new语法糖
  • 是一个对象,有name、length、call、apply、bind属性
  • 0-n个参数、1个返回值

注:箭头函数没有arguments、this、不支持new语法糖

const a = 222
const f2 = ()=>console.log(a)

console.log(this)
const f1 = ()=>console.log(this)

// 箭头函数如何处理a,就如何处理this

即  箭头函数把this当做外部的变量,仅此而已

但是非箭头函数的this有很多特殊处理

箭头函数不支持this指的就是箭头函数对this与其他变量一视同仁,不会特殊对待。

this的确定

显示this

fn.call(asThis,1,2)
fn.bind(asThis,1,2)()
obj.method.call(obj,'hi')

隐式this

fn(1,2)  // fn.call(undefined,1,2)
obj.method('hi')  // obj.method.call(obj,'hi')
array[0]('hi') // array[0].call(array,'hi')

递归

递归算法:是一种直接或者间接地调用自身的算法。

斐波那契数列

fib=(n) =>
     n === 0 ? 0 :
     n === 1 ? 1 :
     fib(n-1) + fib(n-2)

所有的递归都可以改写循环

fib = (n) =>{

    let array = [0,1]
    for(let i=0;i<=n-2;i++){
        array[i+2] = array[i+1] + array[i]
        
    }

    return array[array.length - 1]

}

通过递归实现树组件的渲染

App.vue 

<script setup lang="ts">
import { ref } from "vue"
import TreeComponent from "./TreeComponent.vue"
const treeData = ref([{
  key: '1',
  title: 'Parent 1',
  children: [{
    key: '1-1',
    title: 'child 1',
  }, {
    key: '1-2',
    title: 'child 2',
    children: [{
      key: '1-2-1',
      title: 'grandchild 1',
      children:[]
    }, {
      key: '1-2-2',
      title: 'grandchild 2',
    },]
  },]
}, {
  key: '2',
  title: 'Parent 2',
  children: [{
    key: '2-1',
    title: 'child 1',
    children: [{
      key: '2-1-1',
      title: 'grandchild 1',
    }, {
      key: '2-1-2',
      title: 'grandchild 2',
    },]
  }, {
    key: '2-2',
    title: 'child 2',
  },]
}])
</script>

<template>
  <TreeComponent :data="treeData" />
</template>

TreeComponent.vue

<script setup lang="ts">
interface TreeData {
  key: string
  title: string
  children: TreeData[]
}
defineProps<{data: TreeData[]}>()

</script>

<template>
  <template v-for="parent in data" :key="parent.key">
    {{ parent.title }}
    <template v-if="parent.children && parent.children.length">
      <TreeComponent :data="parent.children" />
    </template>
  </template>
  <!-- do something.... -->
</template>

 递归算法的优化:

例如使用React.memo、 React.userCallback 通过记忆化减少不必要的递归次数,来减少计算

柯里化 currying

让所有函数只接受一个参数,主要用于函数式编程。

单一参数有什么意义?

基于单一参数函数,已经衍生出非常多理论知识,如λ演算等。

柯里化一个函数就是 把多参数函数,变成单参数函数。

如何把add(1,2,3)变成curriedAdd(1)(2)(3)

const curriedAdd = a =>

                   b=>

                   c=>

                   a+b+c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值