递归函数与复杂数据类型

136 阅读7分钟

续 上次练习作业

  • 封装一个函数, 判断一个四位数字是否为 水仙花数 (各个位置的四次方和)
        /**
         *  1. 封装一个函数
         *  2. 需要一个参数
         *  3. 可以写一个 return / console
        */




        function fn(num) {
            // 判断 num 这个 四位数字, 是否为 水仙花数

            // 1. 拿到 num 各个位置上的数字
            var geW = num % 10
            var shiW = parseInt(num / 10) % 10
            var baiW = parseInt(num / 100) % 10
            var qianW = parseInt(num / 1000)

            // 2. 计算各个位置上的 四次方和
            var sum = geW ** 4 + shiW ** 4 + baiW ** 4 + qianW ** 4

            // 3. 判断 四次方和 是否等于 自身
            if (sum === num) {
                console.log('是水仙花数')
            } else {
                console.log('不是水仙花数')
            }
        }

        fn(1634)
  • 封装一个函数, 对一个四位数字加密 加密规则: 1. 每一位上的数字 +5 然后使用 10的余数替代 2. 一三交换位置, 二四交换位置 举例: 输入 1234 3. 每一位上的数字 +5 ===> 6789 4. 使用 10 的余数代替 ===> 6789 5. 一三 二四 交换位置 ===> 8967

输入 5655 1. 每一位上的数字 +5 ===> 0100 2. 使用 10 的余数代替 ===> 0100 1. 一三 二四 交换位置 ===> 0001 (这里需要打印0001, 不能打印1)

function fn1(num) {
            // 书写 加密逻辑

            // 1. 拿到各个位置上的数字
            var geW = num % 10
            var shiW = parseInt(num / 10) % 10
            var baiW = parseInt(num / 100) % 10
            var qianW = parseInt(num / 1000)

            // 2. 每一位上的数字 +5    然后使用 10的余数替代
            // geW = geW + 5
            // geW += 5
            geW = (geW + 5) % 10
            shiW = (shiW + 5) % 10
            baiW = (baiW + 5) % 10
            qianW = (qianW + 5) % 10

            /**
             *  3. 一三交换位置, 二四交换位置
             * 
             *  原本 -> qianW + baiW + shiW + geW
             *  一三交换 -> shiW + baiW + qianW + geW
             *  二四交换 -> shiW + geW + qianW + baiW
            */
            var sum = '' + shiW + geW + qianW + baiW

            // 4. 加密完毕, 可以 return, 也可以使用 console 代替
            console.log(sum)
        }

        fn1(1234)
        fn1(5655)

递归函数

  • 在一个函数内, 调用了 自身, 就算是一个递归函数, 只不过这个函数需要再设置一个结束条件
  • 小练习
function fn(num) {
            if (num === 1) {    // 如果 num === 1 代表现在要计算 1 的阶乘
                return 1
                // 所以这里直接将 1 的阶乘 返回出去, 因为 1 的阶乘还是1, 所以这里 直接 return 1, 如果 1 的阶乘 是 100, 我们就需要 return 100 了
            }

            // 需要将 num 的阶乘返回出去, 现在假设 num 就是 4
            // return fn(4)
            // return 4 * fn(4 - 1)
            return num * fn(num - 1)
        }

        // 计算 4 的阶乘
        var res = fn(4)
        console.log(res)

    // 我们现在假设 fn 函数就是求某一个数字的 阶乘
    //     如果你要计算 99 的阶乘 -> fn(99)
    //     如果你要计算 60 的阶乘 -> fn(60)
    //     如果你要计算 4 的阶乘 -> fn(4)        
  • 小练习
    • 前两位是固定的, 从第三位开始, 他的值是 它自身的前两位的和
      • 1, 1, 2, 3, 5, 8, 13, 21, 34
function fn(num) {
            if (num === 1 || num === 2) {
                // 如果当前分支执行, 说明我们在寻找 数列中 第一位或者第二位的值, 那么固定返回一个 1
                return 1
            }

            // 要计算 第 5 位的数字 === 第 4 位 + 第 3 位
            // return fn(4) + fn(3)
            return fn(num - 1) + fn(num - 2)
        }

        console.log(fn(10))

        // var res = fn(5)
        // console.log(res)

        /**
         *  现在 假设 fn 函数就是求 这个 某一个位置上的值
         * 
         *  fn(5)   ->  得到这个数列的第五位的数字
         *  fn(20)   ->  得到这个数列的第 20 位的数字
        */

对象

  • 是 JS 中的一种数据类型
  • 对象属于 引用数据类型 (复杂数据类型)
  • 算是一种数据的集合, 内部可以存储任意的数据类型
// 1. 字面量的方式创建对象 (很常用)
        var obj = {
            // 这个大括号内部不书写代码, 内部书写数据
        }

        // 2. 内置构造函数去创建
        var obj1 = new Object()

        // console.log(obj)
        // console.log(obj1)

        /**
         *  键值对  --- 属性名/属性值   ---  key/value
         * 
         *      对象中存储数据的时候, 是按照固定的格式存储的, 这种格式我们叫做 键值对
         * 
         *          拿 obj2 举例子:
         *              a -> 键/属性名/key
         *              冒号后的 数字 1         是 a 对应的 值/属性值/value
         * 
         *      多个键值对之间, 使用 逗号间隔
        */

        var obj2 = {
            b: 'QF666',
            a: 1
        }

        var users = {
            name: '张三',
            age: 18,
            number: 1340000000,
        }

        console.log(users)

对象的基本操作

  • 前置: 对象内对于 key/属性名/键 的要求 1. 推荐书写 属性名 时, 参考 变量的命名规范 2. 可以使用 纯数字 当成 属性名 3. 可以使用 特殊符号 #@ 但是需要使用 引号包裹
var obj = {
            name: 'QF001',
            100: 18,
            "@": '我是一个特殊符号'
        }
        console.log(obj)
  • 基本操作: 增删改查
    1. 分为两种语法:
      1. 点语法
      2. 中括号语法 (数组语法)
// 1. 点语法
        // var obj = {
        //     name: 'QF001'
        // }
        // console.log('源对象: ', obj)

        // 增   ->      对象.新属性名 = 对应的属性值
        // obj.age = 18

        // 删除 ->      delete 对象.要删除的属性名
        // delete obj.name

        // 改   ->  对象.要修改的属性名 = 新的属性值
        // obj.name = 'QF002'

        // 查   -> 对象.要查询的属性名
        // console.log(obj.name)

var obj = {
            name: 'QF001',
            100: 18,
            "@": '我是一个特殊符号'
        }       
// 2. 中括号语法

        // 增   ->  对象['新属性名'] = 对应的属性值
        // obj['age'] = 18

        // 删除 -> delete    对象[要删除的属性名]
        // delete obj['name']

        // 改   ->   对象[要修改的属性名] = 新的属性值
        // obj['name'] = 'QF002'
        // console.log('新对象: ', obj)

        // 查   -> 对象[要查询的属性名]
        // console.log(obj['name'])
/**
  两种语法的差别
 
      如果对象的属性名 是符合变量的命名规范的话, 那么 这两种语法没有任何差异
      如果操作一些 不符合变量的命名规范的属性名的时候, 更多的场景需要使用 中括号语法
 
      如果你要 用的是 变量 , 那么也需要使用中括号语法
*/

        var str = 'name'
        // console.log(obj.name)
        // console.log(obj.100)
        // console.log(obj.@)

        // console.log(obj['name'])
        // console.log(obj[100])
        // console.log(obj['@'])


        console.log(obj.str) 

/**
  对象的 点语法 后续跟的内容, 会自动转换为 一个 字符串
 
      也就是说, obj.str   他不会将 str 当成一个变量, 而是一个 字符串
      所以会去对象 obj 中寻找一个 属性名 位 str 的键值对
      但是当前对象中没有这个属性, 所以返回一个 undefined
*/
/**
  对象的 中括号语法内可以书写变量
 
  在查找的时候, 会先将 str 转换为 对应的值, 也就是一个 字符串类型 name
 
  所以会去这个对象中, 查找一个 属性名位 name 的键值对
 
      因为对象中有一个 属性名位 name 的键值对, 对应的属性值为 'QF001'
*/        

遍历对象

/**
  循环遍历对象
 
  for...in
*/
var obj = {
            name: 'QF001',
            age: 18,
            str: 'qwer'
        }

        for (var k in obj) {
            // console.log(k)
            console.log(k, obj[k])
            // console.log(obj.k)
        }

数组

  • 一个存放一组数据的集合
  • 我们将一组数据, 存放到一个盒子中, 这个盒子就是一个数组
    • 数组的创建:
      1. 字面量的方式 (常用)
      2. 内置构造函数
    • 数组的 length
      1. 其实就是数组的长度, 由数组内部多少个 成员(数据) 来决定的
      2. 跟数组每个成员的值, 没有任何关系
    • 数组的 索引(下标)
      1. 下标表示的是 数组当前位置
      2. 从 0 开始!!! 到 数组.length - 1 结束
// 1. 字面量的方式
        // var arr = [] 创建一个空数组
        // var arr = [1, 2, 'qwe', 'rty', true, false, undefined, { name: 'QF001' }]
        // console.log(arr)

        // 2. 内置构造函数
        // var arr = new Array()    空数组
        // var arr = new Array(5)  创建一个 长度 为 5 的空数组
        // var arr = new Array(1, 2, 3, 4, 5)  // 创建一个 内容为 1 2 3 4 5 的数组
        // console.log(arr)


        // length
        // var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        // var arr1 = [100, 200, 300, 400, 500]
        // console.log(arr1)
        // console.log(arr1.length)


        // 下标
        var arr1 = [100, 200, 300, 400, 500]
        var arr2 = [100, 300, 400, 500]
        // console.log(arr1)
        // console.log(arr2)

        // 需求: 拿到数组某一个位置的值;    语法: 数组[下标]
        console.log(arr1[0])

        /**
         *  需求:
         *      利用 for 循环, 拿到数组的每一项
        */

遍历数组

var arr = [100, 200, 300, 400, 500, 600]

        // console.log(arr[0]) // 100
        // console.log(arr[1]) // 200
        // console.log(arr[2]) // 300
        // console.log(arr[3]) // 400
        // console.log(arr[4]) // 500

        for (var i = 0; i < arr.length; i++) {
            // console.log(i)
            console.log(arr[i])
        }