javascript递归

递归函数就是函数直接或间接调用自己

//无限递归
function fu() {
console.log('hello');
}
fu()   //使用无限递归时必须注意给函数设置出口

作用域scope

作用域的产生时间:函数定义(声明)的时候产生

作用域的分类:

1、全局作用域

2、局部作用域:包含函数、和块级{}

3、eval()作用域

执行上下文Execution Context

执行上下文的产生时间:函数调用时产生

生命周期

全局上下文

生命周期:窗口打开=>窗口关闭,node打开=>node关闭

局部上下文(函数上下文)

生命周期:函数调用=>调用完毕

概述

每当调用一个一个函数时一个新的EC就会被创建出来,在js内部有三个阶段

1、EC创建阶段

2、EC激活阶段

3、EC销毁阶段

当js执行时就会进入不同的ec,而每个ec的组成

组成部分内容
Variable Object{arguments,function declarations,variables}
Scope指向作用域链
this指向一个环境对象

EC的创建发生在:当调用一个函数但又在执行函数体内具体代码前。创建的同时,其内部还会分别为:

1、建立变量对象VO。及包含变量对象,无法访问。如果是函数则还会建立arguments

2、建立作用域链SC

3、确定this指向

激活阶段

1、函数引用

2、变量赋值

3、执行其他代码

变量对象VO

Variable Object是EC创建阶段内部创建的一个对象,用来记录当前作用域所有可用的变量

VO中的属性是不可被访问的,只有等激活AO(Active Object)后才可被访问

VO与AO实际上是同一个对象,只是状态不同

 

function outer() {
    console.log(a);    //undefined
    console.log(inner());   //2
    var a=1;
    function inner() {
        return 2;
    }
    console.log(a);   //1
}
outer();


function fn(a,b) {
var c=10;
function fnD() {}
var e =function fnE(){}
b=20;
console.log(a,b,c); //10,20,10
}
fn(10);


var a=1;
function fn(){
    console.log(a);  //第二步:undefined
    a=2;
    console.log(a);  //第三步:2
    var a=3;
    console.log(a);    //第四步:3
}
console.log(a);//第一步:1
fn()
console.log(a);//第五步:1


var fn=function(){
     console.log(a);  //第一步:function a
     var a=1
     console.log(a);  //第二步:1
     a();             //第三步:报错
     function a(){}   
}
fn();


function foo(number) {
    if (number>3) {
        foo(--number);
    }
    console.log(number);  //3,3,4
}
foo(5);

scope chain 作用域链:

SC:访问规则是:先访问自身EC,若找不到变量,则访问声明时所在的EC里的变量,依次类推,直到找到全局EC

var a=1;
function eat() {
    console.log(a);  //第三步:1    (在当前找a,当前没有在全局找)
}
function foo() {
    var a=2;
    eat();//第二步
}
foo();//第一步

垃圾回收机制

1、不在使用的变量

2、没有引用的对象

3、局部变量

 function foo() {
                let a=10;
 当变量进入环境   let b='hello'              //进入环境
              }
  foo();                      //离开环境


function fn() {
    let i=5;
    console.log(i);
}
fn();
console.log(i);
//函数作用域中的i在调用完成后销毁


let obj={
    name:'zhangsan'
}
obj=null;
//obj是引用堆中的对象,当obj赋值为空,堆中的对象就是垃圾

闭包Closure

function outer() {
    let number=5;
    return function () {
        console.log(number);
    }
}
let result= outer() ;
result();//5
//函数套函数,返回出一个函数,反出去的函数在声明处以外被调用,访问外部作用域

闭包由函数以及声明该函数的EC组合而成,正常情况下该销毁的数据,由于外部还有引用,就形成了闭包

广义:所有函数都是闭包(每当函数被创建时,就会在函数生成时生成闭包)

狭义:函数在执行完成时,该销毁的,由于继续被引用,就没有被销毁

函数的嵌套

内部函数在访问外部函数的作用域

内部函数在自身所在作用域意外被调用

闭包的优缺点:

1、延长了生命周期,或者说扩大局部变量的作用范围

2、实现了变量的私有化

3、在内存维持一个变量,就避免了变量污染(重名),但作为常驻内存,使用不当容易造成无效内存

4、变量该销毁的没有销毁,浪费内存,性能略低

多维数组转一维数组

let arr = ['a', 'b', 'c', ['a1', 'b1', 'c1', ['a2', 'b2', 'c2']]];
//字符串方法
let str = arr.join(',')
let arr1 = str.split(',')
//数组的方法
let arr1=arr.flat(Infinity);
//扁平化
let arr2 = []
function render(arr) {
    for (let key in arr) {
        let item=arr[key];
        if (Array.isArray(arr[key])) {
            render(item);
        } else {
            arr2.push(item);
        }
    }
    return arr2
}
render(arr)
console.log(arr2);

函数柯里化

function render(province,region) {
    return function (name,age) {
        console.log(`我叫${name},今年${age},来自${province}的${region}`);
    }
}
let i=render('xx公司','xx部门')
i('张三','29')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 递归是一种编程技巧,其中一个函数调用自身。在 JavaScript 中,递归可以用来解决复杂的问题,并使代码更简洁易读。 递归的基本模型包括以下几个步骤: 1. 定义递归终止条件:当递归达到一定的深度时,必须终止递归。 2. 分治:将问题分解为规模更小的子问题。 3. 调用自身:通过解决子问题来解决整个问题。 4. 记录结果:在递归的过程中,记录每一步的结果。 下面是一个简单的递归例子,计算阶乘: ``` function factorial(n) { if (n === 0) { return 1; } return n * factorial(n - 1); } ``` 在这个例子中,递归终止条件是 `n` 为 0,分治的子问题是计算 `n-1` 的阶乘,调用自身的方式是通过函数 `factorial` 调用,并将计算结果返回。 ### 回答2: 递归是一种在编程中常见的技巧,特别在JavaScript中,递归经常被用来解决问题。递归是指一个函数调用自身的过程。下面是关于JavaScript递归的一些重要信息: 1. 递归必须包含一个终止条件,否则函数将无限地调用自身。这个终止条件通常是某个特定条件的判断,一旦满足了该条件,递归将停止。 2. 递归必须能够将问题分解为更小的子问题,同时保持问题的解决方案是相同的。 3. 递归可以方便地解决一些复杂的问题,例如树和图的遍历,阶乘计算等。 4. 使用递归时需要小心,因为它可能会导致性能问题。递归过程中使用大量的函数调用,可能导致堆栈溢出。 5. 尽管递归可以让代码更简洁和易于理解,但在某些情况下,使用循环可能更高效和可维护。因此,在选择使用递归之前,需要仔细权衡。 总的来说,JavaScript递归是一种强大而灵活的编程技巧,可以解决各种问题。但在使用时需要注意终止条件和性能问题,以确保代码的正确性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值