24 js高级 -- 函数进阶

232 阅读9分钟

函数的定义和调用

函数的定义

命名函数

image.png

匿名函数

image.png

利用 new Function('参数1','参数2', ... ,'函数体')

效率很低

image.png

1、Function 里面的参数都必须是字符串格式

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

3、第三种方式执行效率低,也不方便书写,因此较少使用

4、函数也属于对象

image.png

函数的调用方式

普通函数

image.png

对象的方法

image.png

构造函数

用 new 来创建实例对象

image.png

绑定事件函数

image.png

定时器函数

image.png

立即执行函数

image.png

this

this一般都指向调用者

普通函数

普通函数里面的this 指向 window

image.png

对象的方法

对象里方法的this 指向 对象

image.png

构造函数

构造函数里面的this 指向实例对象

image.png

绑定事件对象

绑定事件对象里面的this 指向函数的调用者

定时器函数

定时器里面的this 指向 window

image.png

立即执行函数

立即执行函数里面的this指向window

call 、 apply 、 bind

call

作用

1、调用函数

image.png

2、改变this指向

image.png

通过 call 可以改变this的指向

image.png

3、( ) 里面还可以传递参数 ,传递的参数是一个一个,单个的。

image.png

应用

call的主要作用是可以实现继承

因为 call可以改变this指向,

image.png

分析 : call把Father的指向改变了,而在Son里面的this 指向的是Son,且把uname 和 age 传给Father

apply

作用

1、调用函数

image.png

2、改变this指向

image.png

3、() 里面可以传递参数 ,传递的参数是以数组的形式传递的

image.png

应用

通过apply 来使用数学里面的方法

   数组中没有求最大值,最小值的方法 ; 是数学对象里面才有的
   
   Math.max() ; Math.min()

   比如说,我们可以利用 apply借助于数学内置对象求最大值

1、创建数组arr

image.png

数组里面的形式是 数字型

2、求出数组中最大的值 , 利用数学.max 方法

image.png

分析 : apply传递的参数是数组形式的 ; 而且 在函数中,通过apply传递进去的数组,会拆分开来 ; 若数组里面是数字型,那么就拆为一个个数字 ; 若 里面是字符串型,那么就会拆成一个个字符串

所以这里面会把arr1 拆为一个个数字,然后使用 数学对象.max 方法 ,就可以得出最大值

image.png

bind

作用

注:它不会调用函数

1、改变this指向

image.png

它返回的是一个新的函数 ; 这个新函数是 原函数改变this之后 产生的新函数 ,所以要var 一个变量来接收

image.png

2、() 里面可以传递参数 , 也是传递的是一个一个单个的参数

image.png

应用

适合于 : 有一些函数是不需要立即调用,但又想改变这个函数内部的this指向

案例1 : 有一个按钮,点击之后,就禁用这个按钮,3秒后再显示

image.png

call、apply、bind 的区别

call 和 apply 的区别

call 传递的参数是一个一个,单个参数的 ;

而apply传递的参数以数组的形式传递的

call 和 bind 的区别

call 可以 调用函数 , 但bind 不可以调用

apply 和 bind 的区别

apply 可以调用函数,且传递的参数是 数组形式的

bind 无法调用函数 ,且传递的参数是 一个一个,单个参数的

严格模式

在js中可以模式可以分为 正常模式 和 严格模式 ;

es5的严格模式是采用具有限制性js变体的一种方式,即在严格的条件下运行JS代码

ie10以上才支持,旧版本会忽略严格模式


  • 严格模式 对正常的js语义做了一些更改
  1. 消除了js语法的一些不合理、不严谨之处,减少了一些怪异行为

  2. 消除代码运行的一些不安全之处,保证代码运行的安全

  3. 提高编译器效率,增加运行速度

  4. 禁用了在ECMAScript的未来版本中可能会定义的一些语法,为未来新版本的js做好铺垫,eg : 一些保留字 : class 、 enum 、export 、 extends 、 import 、 super 不能做变量名

开启严格模式

严格模式可以应用到整个脚本 或者 个别函数中,因此在使用时,我们可以将严格模式分为 为脚本开启严格模式为函数开启严格模式两种情况

为脚本开启严格模式

为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句 “use strict“ ; (或者 'use strict' ;)

image.png

有的script 基本是严格模式,有些script脚本是正常模式,这样不利于文件合并

所以我们可以将整个脚本文件放在一个立即执行的匿名函数中,这样就可以独立创建一个作用域而不影响其他script脚本文件

image.png

为函数开启严格模式

image.png

严格模式的变化

变量规定

  1. 在正常模式下,若变量没有声明,直接赋值的话,会被当作是全局变量 ; 而在严格模式中,必须先声明后赋值

image.png

image.png
  1. 严禁删除已经声明好的变量

image.png

image.png

严格模式下的this指向

  1. 在正常模式下,全局函数的this 指向window ; 但在严格模式下的this指向 undefined

image.png

image.png

  1. 在正常模式下,构造函数不加new 也可以调用 , 就是当普通函数来调用了

image.png

image.png

但在严格模式下,构造函数若不加new 来调用,那么就会报错,是因为 严格模式下的this 指向undefined , 而不能给 undefined 添加属性

若 new 了构造函数,那么此时的this 指向创建的实例对象

  1. 定时器里面的this 指向的还是window

image.png

image.png

  1. 事件、对象里面的this指向的还是调用者

函数变化

  1. 函数里面不可以有重名的参数

image.png

image.png
  1. 在严格模式下,函数可以写在最外面,但是不允许写在非函数的代码块

就是在if 、 for 里面声明函数

高阶函数

高阶函数 是对其他函数进行操作的函数,它接收函数作为参数 或者 将函数作为返回值输出

高阶函数 -- 接收函数作为参数

image.png

那么此时的 fn 就是一个高阶函数

函数也是一种数据类型,同样也可以作为参数,传递给另外一个参数使用,最典型的就是作为回调函数

高阶函数 -- 将函数作为返回值输出 ( 闭包 )

image.png

闭包

闭包的定义

闭包也是一个高阶函数

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

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


  • 在函数外部访问函数内部的变量
函数也是一个数据类型,数据类型就可以当参数传递进去 , 也可以当返回值返回回来

闭包的使用

1、 返回内部函数

image.png

2、调用外部函数 fn() ,那么就会有内部函数的返回

image.png

3、声明变量接收

image.png

4、那么,在函数内部就是 先定义 var num = 10 ; 然后 function fun 不执行(因为没调用不执行),再执行 return一下 fun 函数

注 : 里面有return 就得放变量名去接收一下

image.png

5、现在f里面存的就是一个函数 ,那么就可以调用

image.png

6、那么此时的fun 本身就在fn 里面,所以就可以打印出来num的值了,那么就可以实现在函数外部访问函数内部的值了

此时的闭包函数就是 fn

注 : 被访问的变量所在的函数就是闭包


里面的return 还可以写为 函数形式

image.png

闭包的作用

闭包函数的作用 : 延伸了变量的作用范围

闭包的面试题

案例 : 点击li 打印当前索引号

1、获取所有的li

image.png

2、利用 for 循环遍历lis

image.png

3、在 for 循环里面 创建立即执行函数

image.png

4、在立即执行函数里面 ,把 所有索引传递进去 ,且接收

image.png

5、所以在立即执行函数里面,就可以通过点击 li来获取值了

image.png

小tips立即执行函数也称为小闭包, 因为 立即执行函数里面的任何一个函数都可以使用它传进来的这个变量

递归

递归的定义

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

  • 简单理解 : 函数内部自己调用自己,则这个函数就是递归函数

  • 递归函数的作用和循环效果一样 ;

  • 由于递归很容易发生 “ 栈溢出 ” 错误 ,所以必须要加退出条件 return

递归的应用

案例 : 求阶乘 123*...*n

image.png

详细思路 :

image.png

浅拷贝和深拷贝

浅拷贝

定义

只是拷贝一层,对于复杂数据类型来说,浅拷贝只会拷贝地址(引用)

55fe4e4fefb7aad4ed988c0353d9a7e.jpg

使用

image.png

利用 for in 进行遍历对象 ,o[k] 就相当于 o.k ,也就相当于 在对象o里面添加属性k

  • 所以 若修改拷贝后的对象 o , 那么 obj 里面的值也会被修改

es6语法糖

 Object.assign(要拷贝给谁(目标对象),拷贝的是哪一个对象)
 

image.png

这样可以直接进行浅拷贝的复制

深拷贝

定义

是拷贝多层,每一级别的数据都会拷贝 ,

277d2f9fbf8d366f57d8170dc806cae.jpg

应用

1、创建 obj 和 o

image.png

2、封装了一个函数,用于进行深拷贝 , 把创建的 obj 和 o 传到函数里面

image.png

3、for in 遍历对象

image.png

4、判断属性值,判断 需要拷贝的值是属于数组还是对象还是简单数据类型

image.png

5、若是数组,那么就 给 newobj[k] = [] ,意思就是 给 newobj.k 开辟一个新的内存空间 , 是数组形式的 ; 然后进行递归

image.png

6、若都不是,那么就直接传进去

image.png


小tips : 先判断 是否属于数组形式的,再判断是否属于对象形式 ,因为 数组也属于对象

image.png