函数进阶

124 阅读5分钟

函数定义和调用

1.函数的定义方式

  • 函数声明方式function关键字(命名函数)

      function fn(){}
    
  • 函数表达式(匿名函数)

     var fun=function(){}
     
    
  • 利用 new function('参数1','参数2','函数体');

    var f=new Function('a','b',console.log(123)');
    f();
    

function里面参数都必须是字符串格式

第三种效率低

所有函数都是Function的实例(对象)

22.png

函数调用方式

1.普通函数

  function fn(){
    console.log('我是大帅哥')
}
fn()

2.对象的方法

  var o = {
    say: function() {
        console.log('我是大帅哥')
    }
}
o.say()

3.构造函数

  function Star(){

}
new Star

4.绑定事件函数

   btn.onclick=function(){
    
}
//点击按钮调用

5.定时器函数

     setInterval(function(){},1000)
     //这个函数定时器自动一秒调用一次
     

6.立即执行函数

   (function(){
    console.log('我是大帅哥')
})//自动调用

函数中this的指向

33.png

js中为我们提供一些函数帮我们处理函数this的指向问题

1.call方法

  • 可以调用函数
  • 可以改变函数的this指向

2.apply方法(运用的意思)

  • 可以调用函数

  • 可以改变函数的this指向

  • 但是他的参数必须是数组形式的(伪数组)

     fn.apply(0.['pink'])
    
  • 主要应用:借助与数学内置对象求最大值

       var arr=[1,23,6,99,4]
     var max=  Math.max.apply(Math,arr);
    

3.bind()不会调用函数,只能改变函数内部this指向(绑定)

    fun.bind(thisArg,arg1,arg2,...)
    
  • thisArg:在fun函数运行时指定的this

  • arg1,arg2:传递的其他参数

  • 返回由指定的this值喝初始化参数改造的原函数拷贝

  • 有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind

  • 有一个按钮,我们点击后,就禁用按钮,三秒后开启

         <!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>
        <button>点击</button>
     </body>
         <script>
    
    var btn = document.querySelector('button');
     btn.click = function() {
      this.disabled = true; //this指向了btn
      setTimeout(function() {
      this.disabled=false;
      }.bind(this), 3000)
     }
    </script>
    
     </html>
    

三个按钮 点击禁用 三秒后开启

        <!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>
<button>点击</button>
<button>点击</button>
<button>点击</button>
    </body>
        <script>
var btn = document.querySelectorAll('button');
for (var i = 0; i < btn.length; i++) {
    btn[i].onclick = function() {
        this.disabled = true;
        setTimeout(function() {
            this.disabled = false;
        }.bind(this), 3000)
    }
}

   </script>

     </html>

总结 相同:改变函数内部的this指向 应用场景:

  • call经常用在继承
  • apply经常跟数组有关系
  • bind不调用函数,还想改变this的指向

严格模式

消除不合理的地方

  • 脚本开启严格模式

脚本开启:在所有语句之前放一个特定语句“use strict”

  • 函数开启严格模式

    开启:在函数语句之前放一个特定语句“use strict”

严格模式的变化

1.变量规定

  • 在正常模式中,一个变量没有声明默认全局变量,严格模式禁止这种用法,变量都必须用var 命令声明,然后在使用
  • 不能随意删除已经声明好的变量
  • 全局作用域中函数的this时underfined
  • 构造函数不加new调用,this会报错
  • new实例化的构造函数指向创建的对象实例
  • 定时器中的this指向的还是window
  • 事件对象指向的还是调用者

2.函数变化

  • 函数不能有重名的参数
  • 函数必须吸纳声明在顶层最新版本的js“块级作用域”为了喝新版本接轨,不允许在非函数的代码块内声明函数

高阶函数

对其他函数进行操作做的函数,他接收函数作为参或将函数作为返回值输出

闭包

  • 闭包:有权访问另一个函数作用域中变量的函数

简单理解:一个作用域可以访问另外一个函数内部的的局部变量

  • 闭包的作用:延伸了变量的作用范围
  • 闭包的应用

闭包应用-点击li输出当前li的索引号

//  闭包的应用:点击li输出当前li的索引号
//可以利用动态添加属性的方式
var lis = document.querySelectorAll('li').querySelector('.nav')
for (var i = 0; i < lis.length; i++) {
    lis[i].onclick = function() {
        console.log(this.index)
    }
}
//闭包方式得到
for (var i = 0; i < lis.length; i++) {
    //利用for循环常见了4个立即执行函数
    //立即执行函数也称为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i的变量
    (function(i) {
        console.log(i);
        lis[i].onclick = function() {
            console.log(i)
        }
    })(i)

}

闭包应用-3秒后打印所有li元素的内容

 (function(i){
for (var i = 0; i < lis.length; i++) {
    //利用for循环常见了4个立即执行函数
    setTimeout(function() {
        console.log(lis[i].innerHTML);
    }, 3000)

}
})(i) 

闭包应用-计算打车价格

需求:打车起步价13(三公里)多一公里就+5块钱,遇到拥堵就多收10块

 //打车
var car=(function() {
    var star = 13;
    var total = 0;
    return {
        //正常的总价
        price: function() {
            if (n <= 3) {
                total = star;
            } else {
                total = star + (n - 3) * 5
            }
            return total;
        },
        //拥堵得到价格
        yd: function(flag) {
            flag ? total + 10 : total;

        }
    }
})();
console.log(car.price(5));

递归函数

一个函数在内部可以调用他的本身那么这个函数就是递归函数

简单理解:函数内部自己调用自己就是递归

递归里面必须加退出条件

利用递归求阶乘

    //利用递归函数求阶乘
    function fn(n){
        if(n==1){
            return 1;
        }
        return n*fn(n-1);
    }
      console.log(fn(3))

利用递归函数求斐波那契数列(兔子序列)

         //  利用递归函数求斐波那契数列(兔子序列)
   //知道用户输入的n前面的两项就可以计算出n对应的值
     function fb(n){
    if (n===1||n===2){
        return 1;
 }
      return fb(n-1)+fb(n-2)
     }
      console.log(fn(3))

根据递归遍历数据

1.forEach遍历每一个对象

2.得到里面的数据利用递归

dg3.png

浅拷贝和深拷贝

1.浅拷贝知识拷贝一层,更深层次对象级别的只拷贝引用

2.深拷贝拷贝多层,每一级别的数据都会拷贝

3.Object.assign(target,...sources)

es6新增方法可以浅拷贝

44.png

550.png