Enhanced knowledge of JavaScript functions

1 Function attributes and arguments

2 Understanding and Application of Pure Functions

3 Understanding and Application of Currying

4 Understanding and Application of Combination Functions

5. Use of with and eval

6 Use of strict mode

The length attribute of the function object can get the number of formal parameters, which is useful for subsequent rationalization. length does not calculate the length of the remaining arguments.

In the picture below, the second default parameter and the third...others cannot be counted in the length of the function attribute. The length here is 1. 

The formal parameters of the function will be placed in the argument of the function object.

Function enhancement-function arguments

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    function foo(m, n) {
      // arguments 类似数组对象
      console.log(arguments)
      // 1.默认用法:
      // 通过索引获取内容
      // console.log(arguments[0])
      // console.log(arguments[1])

      // // for循环遍历
      // for (var i = 0; i < arguments.length; i++) {
      //   console.log(arguments[i])
      // }
      // for (var arg of arguments) {
      //   console.log(arg)
      // }

      // 2.需求获取所有参数中的偶数
      // 数组 filter
      // for (var arg of arguments) {
      //   if (arg % 2 === 0) {
      //     console.log(arg)
      //   }
      // }
    //这里不能调用数组的方法 FILTER
      // var evenNums = arguments.filter(item => item % 2 === 0)
      // console.log(eventNums)

      // 2.1.将arguments转成数组方式一: for循环深度拷贝
      // var newArguments = []
      // for (var arg of arguments) {
      //   newArguments.push(arg)
      // }
      // console.log(newArguments)

      // 2.2.将arguments转成数组方式三: ES6中方式
      // var newArgs1 = Array.from(arguments)
      // console.log(newArgs1)
      // var newArgs2 = [...arguments]
      // console.log(newArgs2)

      // 2.3.将arguments转成数组方式二: 调用slice方法,通过this的优先级;原型
      var newArgs = [].slice.apply(arguments)
      // var newArgs = Array.prototype.slice.apply(arguments)
      console.log(newArgs)
    }

    foo(10, 25, 32, 41)





    // slice方法的回顾: 了解细节
    // var names = ["abc", "cba", "nba", "mba"]
    // var newNames = names.slice() // this -> names

    // // slice方法 -> 函数
    // console.log(newNames)
    // obj.foo() // this -> obj


  </script>

</body>
</html>

Function enhancement-arguments of arrow function

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <script>
    // 1.箭头函数不绑定arguments
    // var bar = () => {
    //   console.log(arguments)
    // }

    // bar(11, 22, 33)


    // 2.函数的嵌套箭头函数,由于箭头函数没有argument,所以去外层作用域去找了,
    //这里的argument指向foo函数的。
    function foo() {
      var bar = () => {
        console.log(arguments)
      }
      bar()
    }

    foo(111, 222)

  </script>

</body>
</html>

Function enhancement - remaining parameters of the function

In es6, there are remaining parameters instead of argument.

Note: The remaining parameters need to be written at the end of other parameters

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 剩余参数: rest parameters
    function foo(num1, num2, ...otherNums) {
      // otherNums数组
      console.log(otherNums)
    }

    foo(20, 30, 111, 222, 333)


    // 默认一个函数只有剩余参数
    function bar(...args) {
      console.log(args)
    }

    bar("abc", 123, "cba", 321)

    // 注意事项: 剩余参数需要写到其他的参数最后

  </script>

</body>
</html>

Function enhancement-pure function concept understanding

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    function sum(num1, num2) {
      return num1 + num2
    }

    // 不是一个纯函数,info.flag = "已经打印结束"给对象添加了一个key,
    //  原来的对象发生了改变 ,这就是副作用
    var address = "广州市"
    function printInfo(info) {
      console.log(info.name, info.age, info.message)
      info.flag = "已经打印结束"
      address = info.address
    }

    var obj = {
      name: "why",
      age: 18,
      message: "哈哈哈哈"
    }

    printInfo(obj)

    console.log(obj)
    if (obj.flag) {
      
    }

  </script>

</body>
</html>

Function enhancement - array splice and slice

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    var names = ["abc", "cba", "nba", "mba"]

    // 1.slice: 纯函数
    var newNames = [].slice.apply(names, [1, 3])
    console.log(names)

    // 2.splice: 操作数组的利器(不是纯函数),会修改原函数
    names.splice(2, 2)
    console.log(names)
    
  </script>

</body>
</html>

Function enhancement - advantages of pure functions

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 1.安心的写: 你不需要去关心外层作用域中的值, 目前是什么状态
    var counter = 0

    function add(num) {
      return num
    }

    // 2.安心的用: 调用函数时, 可以知道: 确定的输入一定产生确定的输出
    add(5) // 10
    add(5) // 10


    // react中的编写函数组件,这样子写是错误
    function Foo(props) {
      console.log(props.name)
      props.name = "kobe"
    }


  </script>

</body>
</html>

Function enhancement-curried function transformation

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 普通的函数
    function foo1(x, y, z) {
      console.log(x + y + z)
    }

    // foo1(10, 20, 30)
    // foo1(20, 33, 55)


    // 因为foo不是一个柯里化的函数, 所以目前是不能这样调用
    // 柯里化函数
    function foo2(x) {
      return function(y) {
        return function(z) {
          console.log(x + y + z)
        }
      }
    }

    foo2(10)(20)(30)
    foo2(20)(33)(55)


    // 另外一种写法: 箭头函数的写法
    // function foo3(x) {
    //   return y => {
    //     return z => {
    //       console.log(x + y + z)
    //     }
    //   }
    // }

    var foo3 = x => y => z => {
      console.log(x + y + z)
    }

    foo3(10)(20)(30)


  </script>

</body>
</html>

Function Enhancement-Currying Case Exercise 1

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 案例一: 打印一些日志
    // 信息一: 日志的时间
    // 信息二: 日志的类型: info/debug/feature
    // 信息三: 具体的信息

    // 1.没有柯里化的时候做法
    function logInfo(date, type, message) {
      console.log(`时间:${date} 类型:${type} 内容:${message}`)
    }

    // // 打印日志
    // logInfo("2022-06-01", "DEBUG", "修复界面搜索按钮点击的bug")

    // // 又修复了一个bug
    // logInfo("2022-06-01", "DEBUG", "修复了从服务器请求数据后展示的bug")
    // logInfo("2022-06-01", "DEBUG", "修复了从服务器请求数据后展示的bug")
    // logInfo("2022-06-01", "DEBUG", "修复了从服务器请求数据后展示的bug")
    
    // logInfo("2022-06-01", "FEATURE", "增加了商品的过滤功能")


    // 2.对函数进行柯里化: 柯里化函数的做法
    // var logInfo = date => type => message => {
    //   console.log(`时间:${date} 类型:${type} 内容:${message}`)
    // }
    function logInfo(date) {
      return function(type) {
        return function(message) {
          console.log(`时间:${date} 类型:${type} 内容:${message}`)
        }
      }
    }

    var logToday = logInfo("2022-06-01")
    var logTodayDebug = logToday("DEBUG")
    var logTodayFeature = logToday("FEATURE")

    // 打印debug日志
    logTodayDebug("修复了从服务器请求数据后展示的bug")
    logTodayDebug("修复界面搜索按钮点击的bug")
    logTodayDebug("修复界面搜索按钮点击的bug")
    logTodayDebug("修复界面搜索按钮点击的bug")
    logTodayDebug("修复界面搜索按钮点击的bug")

    logTodayFeature("新建过滤功能")
    logTodayFeature("新建搜索功能")

  </script>

</body>
</html>

Function Enhancement - Curry Case Exercise 2

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    function sum(num1, num2) {
      return num1 + num2
    }

    sum(5, 10)
    sum(5, 15)
    sum(5, 18)

    // makeAdder函数就是对sum的柯里化
    function makeAdder(count) {
      function add(num) {
        return count + num
      }
      return add
    }

    // 1.数字和5相加
    var adder5 = makeAdder(5)
    adder5(10)
    adder5(15)
    adder5(18)

    // 2.数组和10相加
    var adder10 = makeAdder(10)
    adder10(10)
    adder10(16)
    adder10(19)

    // adder5 = null
    // adder10 = null

  </script>

</body>
</html>

It is very troublesome to manually change it every time you want to generate a Ke physical and chemical function, so you need an automatic generation method.

It is not necessary to use the Kelichemical function, but sometimes when we need to reuse certain parameters, we can use this to optimize the code.

Function Enhancement - Automatic Currying of Functions

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    function foo(x, y, z) {
      console.log(x + y + z)
    }

    function sum(num1, num2) {
      return num1 + num2
    }

    function logInfo(date, type, message) {
      console.log(`时间:${date} 类型:${type} 内容:${message}`)
    }

    // 手动转化

    // 封装函数: 自动转化柯里化过程(有一点难度)
    function hyCurrying(fn) {
      function curryFn(...args) {
        // 两类操作:
        // 第一类操作: 继续返回一个新的函数, 继续接受参数
        // 第二类操作: 直接执行fn的函数
        if (args.length >= fn.length) { // 执行第二类
          // return fn(...args)
          return fn.apply(this, args)
        } else { // 执行第一类
          return function(...newArgs) {
            // return curryFn(...args.concat(newArgs))
            return curryFn.apply(this, args.concat(newArgs))
          }
        }
      }

      return curryFn
    }

    // 对其他的函数进行柯里化
    var fooCurry = hyCurrying(foo)
    fooCurry(10)(20)(30)
    fooCurry(55, 12, 56)

    var sumCurry = hyCurrying(sum)
    var sum5 = sumCurry(5)
    console.log(sum5(10))
    console.log(sum5(15))
    console.log(sum5(18))

    var logInfoCurry = hyCurrying(logInfo)
    logInfoCurry("2022-06-01")("DEBUG")("我发现一个bug, 哈哈哈哈")


    // 举个栗子
    // var names = ["abc", "cba", "nba"]
    // // spread
    // console.log(...names)

  </script>

</body>
</html>

Function Augmentation - The Case for Composite Functions

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    var num = 100

    // 第一步对数字*2
    function double(num) {
      return num * 2
    }

    // 第二步对数字**2
    function pow(num) {
      return num ** 2
    }

    console.log(pow(double(num)))
    console.log(pow(double(55)))
    console.log(pow(double(22)))

    // 将上面的两个函数组合在一起, 生成一个新的函数
    function composeFn(num) {
      return pow(double(num))
    }

    console.log(composeFn(100))
    console.log(composeFn(55))
    console.log(composeFn(22))

  </script>

</body>
</html>

Function Enhancement - Encapsulation of Composite Functions

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    // 第一步对数字*2
    function double(num) {
      return num * 2
    }

    // 第二步对数字**2
    function pow(num) {
      return num ** 2
    }

    // 封装的函数: 你传入多个函数, 我自动的将多个函数组合在一起挨个调用
    function composeFn(...fns) {
      // 1.边界判断(edge case)
      var length = fns.length
      if (length <= 0) return
      for (var i = 0; i < length; i++) {
        var fn = fns[i]
        if (typeof fn !== "function") {
          throw new Error(`index position ${i} must be function`)
        }
      }

      // 2.返回的新函数
      return function(...args) {
        var result = fns[0].apply(this, args)
        for (var i = 1; i < length; i++) {
          var fn = fns[i]
          result = fn.apply(this, [result])
        }
        return result
      }
    }

    var newFn = composeFn(double, pow, console.log)
    newFn(100)
    newFn(55)
    newFn(22)
    // console.log(newFn(100))
    // console.log(newFn(55))
    // console.log(newFn(22))

  </script>

</body>
</html>

Additional Knowledge - Using Strict Mode

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    // 给整个script开启严格模式
    "use strict"

    // 给一个函数开启严格模式
    function foo() {
      "use strict"
    }

    //默认严格模式
    class Person {
      
    }


  </script>

</body>
</html>

Extra Knowledge - Limitations of Strict Mode

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    "use strict"
    // 1.不会意外创建全局变量
    // function foo() {
    //   message = "Hello World"
    // }

    // foo()
    // console.log(message)

    // 2.发现静默错误
    var obj = {
      name: "why"
    }

    Object.defineProperty(obj, "name", {
      writable: false,
      configurable: false
    })

    // obj.name = "kobe"
    console.log(obj.name)

    // delete obj.name
    console.log(obj)

    // 3.参数名称不能相同
    // function foo(num, num) {

    // }

    // 4.不能以0开头
    // console.log(0o123)

    // 5.eval函数不能为上层创建变量
    // eval(`var message = "Hello World"`)
    // console.log(message)

    // 6.严格模式下, this是不会转成对象类型的
    function foo() {
      console.log(this)
    }
    foo.apply("abc")
    foo.apply(123)
    foo.apply(undefined)
    foo.apply(null)
    
    // 独立函数执行默认模式下, 绑定window对象
    // 在严格模式下, 不绑定全局对象而是undefined
    foo()

  </script>

</body>
</html>

Object Enhancement - Control of Object Properties

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    var obj = {
      name: "why",
      age: 18
    }

    // 默认情况下属性都是没有特别的限制
    // obj.name = ""
    // delete obj.name
    // console.log(obj.name)


    // 可以对对象中的属性进行某些限制
    

  </script>

</body>
</html>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/weixin_56663198/article/details/131470854