js-day21

70 阅读5分钟

bined(),call(),apply()

参数1表示指定函数里面的this指向那个对象

参数2表示传递参数

  • bind()方法:修改函数或方法中的this为指定的对象,并且会返回一个修改后的之后的新的函数给我们。
    • 注意点:bind()方法除了修改this以外,还可以传递参数,只不过参数必须写在this对象的后面
  • call()方法: 修改函数或方法中的this为指定的对象,并且会立即调用修改之后的函数。
  • apply()方法: 修改函数或方法中的this为指定的对象,并且会立即调用修改之后的函数。
    • 注意点:apply()方法除了可以修改this以外,还可以传递参数,只不过参数必须通过数组的方式传递

闭包

概念:闭包就是能够读取其他函数内部变量的函数
闭包的作用:就是可以让你在外界读取函数内部的数据,闭包的原理是利用了函数不销毁的执行空间
注意点:由于函数执行空间,当函数调用完毕后直接销毁,因此外界是无法访问函数内部的变量(作用域 --- 局部作用域)
function closureFn(){
   // 私有变量
   const a = 66
   return function(){
       // 返回给外界的函数使用了内部函数的私有变量
       console.log(a)
   }
}
// 外界有一个变量接收返回的函数
let res = closureFn()
res()

闭包实例

计数器:
<body>
    <button>0</button>
    <button>0</button>
    <script>
    // 计数器:一个按钮,当你点击它的时候,让它里面的数值自增
      const btn = document.querySelectorAll('button')
      // 才有闭包的形式
      function counterFn(){
          // 私有变量
          let counter = 0
          // 返回给外界一个函数
          return function(){
              counter++
              return counter
          }
      }
      const fn1 = counterFn()
      const fn2 = counterFn()
      btn[0].onclick = function(){
          this.innerHTML = fn1()
      }
      btn[1].onclick = function(){
          this.innerHTML = fn2()
      }
    </script>
</body>
封装方法
// 封装方法,可以封装一个加法和减法还有一个计算结果的方
function baseFn(){
  // 私有变量
  let result = 0
  // 设置一个添加的方法
  function add(num){
      result += num
  }
  // 设置一个减的方法
  function sub(num){
      result -= num
  }
  // 计算的方法
  function calc(){
      return result
  }
  // 最终可以把这些方法返回给外界
  return {
      add,
      sub,
      calc
  }
}
let obj = baseFn()
obj.add(10)
obj.sub(2)
console.log(obj.calc())
缓存数据

缓存数据:如果这个数据是已经存在的,那么就直接从缓存里面获取。如果没有这个数据,那么就添加这个数据

function cacheFn(){
  // 声明一个对象来存储缓存数据
  const cache = {}
  // 返回给外界
  // 对象里面存储数据是怎么存储的呢?key=value 形式 ||  key:value 形式
  return function(key, value){
      // 判断下有没有设置value值,如果没有设置那么表示的就是获取数据。如果有value值,说明就是设置数据
      if(value != undefined){
          cache[key] = value
      }
      return cache[key]
  }
}
const result = cacheFn()
console.log(result('username'))
result('username', '张三')
console.log(result('username'))
时间循环
<body>
  <button>按钮1</button>
  <button>按钮2</button>
  <button>按钮3</button>
  <button>按钮4</button>
  <button>按钮5</button>
  <script>
      const aBtn = document.querySelectorAll('button')
      for(var i=0; i<aBtn.length; i++){
          // 第二步:由于fn函数已经被调用了,所以进行形参赋值i=0,进入fn函数体里面
          function fn(i){
              // 第三步:把函数返回给外界,这个返回的函数内部使用了i变量,i变量属于fn函数的私有变量
              return function(){
                  console.log(i)
              }
          }
          // 第一步:把fn(i)赋值给事件了,fn()第一层含义表示函数的调用,直接调用了,并把i=0的这个参数传递给了fn函数本身
          // 第四步:aBtn[i].onclick进行赋值,接收到就是function(){console.log(i)}
          /*
              第五步:当你点击按钮调用这个函数的时候,其实语法变成了以下的形式
              aBtn[i].onclick = function(){
                  console.log(i) // 0
              }
          */
          aBtn[i].onclick = fn(i)
      }
  </script>
</body>

立即执行函数(IIFE)

函数不需要其他的方式调用,会直接自己调用

  • 语法
    • (function(){})()
    • (function(){}())
    • !function(){}()
    • ~function(){}()
  • 特点
    • 自己调用自己
    • 当函数调用完毕后,存储空间会被销毁
  • 作用
    • 适合做一些页面初始化的东西
    • 和闭包可以一起使用
    • 做模块化(伪)

注意点:js里面不能在下一个语句的前面使用()和[]

立即执行函数前最好加分号;

立即执行函数和闭包

<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>
    <script>
        const aBtn = document.querySelectorAll('button')
        for(var i=0; i<aBtn.length; i++){
            /*
                自执行函数和闭包的结合执行步骤:
                + 第一步:自执行(立即执行)函数会先自调用,自调用的时候把i变量作为实参进行传递
                + 第二步:函数进行形参赋值i=0, 再进入自执行函数体内
                + 第三步:把函数返回给外界,在返回给外界的函数里面使用了私有变量
                + 第四步:外界接收到的就是function(){console.log(i)}
                + 第五步:当你点击按钮执行的时候,实际上是以下形式代码在执行
                  aBtn[i].onclick = function(){
                     console.log(i)
                  }
            */
            aBtn[i].onclick = (function(i){
                return function(){
                    console.log(i)
                }
            })(i)
        }
    </script>
</body>

立即执行函数模块化

  • module
  • 把一个功能当成一个模块来使用
    • tab选项卡
    • 轮播图
    • 数据渲染
    • 购物车
    • 登录验证
    • ...
  • 一个功能其实就是一个js文件
  • 优势
    • 方便代码维护
    • 优化性能
    • 减少变量命名冲突
  • 注意点
    • 使用自执行函数做的模块化,不是真正的模块化,是一种伪模块化
<script src='cart.js'></script>
<script src='list.js'></script>
<script>
        console.log(modCart.index)
        console.log(modList.index)
        console.log('--------')
        modCart.render()
        modList.render()
</script>

cart.js

;(function(){
    // 私有变量
    let index = 0
    function render(){
        console.log('我是购物车功能!')
    }
    // 可以把需要在外界使用的数据挂载到window对象上面
    window.modCart = {
        index,
        render
    }
})()

list.js

;(function(){
    let index = 1
    function render(){
        console.log('我是列表功能')
    }
    window.modList = {
        index,
        render
    }
})()