函数的定义和调用
函数的定义
命名函数
匿名函数
利用 new Function('参数1','参数2', ... ,'函数体')
效率很低
1、Function 里面的参数都必须是字符串格式
2、所有的函数都是 Function 的实例 (对象)
3、第三种方式执行效率低,也不方便书写,因此较少使用
4、函数也属于对象
函数的调用方式
普通函数
对象的方法
构造函数
用 new 来创建实例对象
绑定事件函数
定时器函数
立即执行函数
this
this一般都指向调用者
普通函数
普通函数里面的this 指向 window
对象的方法
对象里方法的this 指向 对象
构造函数
构造函数里面的this 指向实例对象
绑定事件对象
绑定事件对象里面的this 指向函数的调用者
定时器函数
定时器里面的this 指向 window
立即执行函数
立即执行函数里面的this指向window
call 、 apply 、 bind
call
作用
1、调用函数
2、改变this指向
通过 call 可以改变this的指向
3、( ) 里面还可以传递参数 ,传递的参数是一个一个,单个的。
应用
call的主要作用是可以实现继承
因为 call可以改变this指向,
分析 : call把Father的指向改变了,而在Son里面的this 指向的是Son,且把uname 和 age 传给Father
apply
作用
1、调用函数
2、改变this指向
3、() 里面可以传递参数 ,传递的参数是以数组的形式传递的
应用
通过apply 来使用数学里面的方法
数组中没有求最大值,最小值的方法 ; 是数学对象里面才有的
Math.max() ; Math.min()
比如说,我们可以利用 apply借助于数学内置对象求最大值
1、创建数组arr
数组里面的形式是 数字型
2、求出数组中最大的值 , 利用数学.max 方法
分析 : apply传递的参数是数组形式的 ; 而且 在函数中,通过apply传递进去的数组,会拆分开来 ; 若数组里面是数字型,那么就拆为一个个数字 ; 若 里面是字符串型,那么就会拆成一个个字符串
所以这里面会把arr1 拆为一个个数字,然后使用 数学对象.max 方法 ,就可以得出最大值
bind
作用
注:它不会调用函数
1、改变this指向
它返回的是一个新的函数 ; 这个新函数是 原函数改变this之后 产生的新函数 ,所以要var 一个变量来接收
2、() 里面可以传递参数 , 也是传递的是一个一个单个的参数
应用
适合于 : 有一些函数是不需要立即调用,但又想改变这个函数内部的this指向
案例1 : 有一个按钮,点击之后,就禁用这个按钮,3秒后再显示
call、apply、bind 的区别
call 和 apply 的区别
call 传递的参数是一个一个,单个参数的 ;
而apply传递的参数以数组的形式传递的
call 和 bind 的区别
call 可以 调用函数 , 但bind 不可以调用
apply 和 bind 的区别
apply 可以调用函数,且传递的参数是 数组形式的
bind 无法调用函数 ,且传递的参数是 一个一个,单个参数的
严格模式
在js中可以模式可以分为 正常模式 和 严格模式 ;
es5的严格模式是采用具有限制性js变体的一种方式,即在严格的条件下运行JS代码
ie10以上才支持,旧版本会忽略严格模式
- 严格模式 对正常的js语义做了一些更改
-
消除了js语法的一些不合理、不严谨之处,减少了一些怪异行为
-
消除代码运行的一些不安全之处,保证代码运行的安全
-
提高编译器效率,增加运行速度
-
禁用了在ECMAScript的未来版本中可能会定义的一些语法,为未来新版本的js做好铺垫,eg : 一些保留字 : class 、 enum 、export 、 extends 、 import 、 super 不能做变量名
开启严格模式
严格模式可以应用到整个脚本 或者 个别函数中,因此在使用时,我们可以将严格模式分为 为脚本开启严格模式 和 为函数开启严格模式两种情况
为脚本开启严格模式
为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句 “use strict“ ; (或者 'use strict' ;)
有的script 基本是严格模式,有些script脚本是正常模式,这样不利于文件合并,
所以我们可以将整个脚本文件放在一个立即执行的匿名函数中,这样就可以独立创建一个作用域而不影响其他script脚本文件
为函数开启严格模式
严格模式的变化
变量规定
- 在正常模式下,若变量没有声明,直接赋值的话,会被当作是全局变量 ; 而在严格模式中,必须先声明后赋值
- 严禁删除已经声明好的变量
严格模式下的this指向
- 在正常模式下,全局函数的this 指向window ; 但在严格模式下的this指向 undefined
- 在正常模式下,构造函数不加new 也可以调用 , 就是当普通函数来调用了
但在严格模式下,构造函数若不加new 来调用,那么就会报错,是因为 严格模式下的this 指向undefined , 而不能给 undefined 添加属性
若 new 了构造函数,那么此时的this 指向创建的实例对象
- 定时器里面的this 指向的还是window
- 事件、对象里面的this指向的还是调用者
函数变化
- 函数里面不可以有重名的参数
- 在严格模式下,函数可以写在最外面,但是不允许写在非函数的代码块
就是在if 、 for 里面声明函数
高阶函数
高阶函数 是对其他函数进行操作的函数,它接收函数作为参数 或者 将函数作为返回值输出
高阶函数 -- 接收函数作为参数
那么此时的 fn 就是一个高阶函数
函数也是一种数据类型,同样也可以作为参数,传递给另外一个参数使用,最典型的就是作为回调函数
高阶函数 -- 将函数作为返回值输出 ( 闭包 )
闭包
闭包的定义
闭包也是一个高阶函数
闭包是指 有权访问另一个函数作用域中变量的函数
简单理解 : 一个作用域可以访问另外一个函数内部的局部变量
- 在函数外部访问函数内部的变量
函数也是一个数据类型,数据类型就可以当参数传递进去 , 也可以当返回值返回回来
闭包的使用
1、 返回内部函数
2、调用外部函数 fn() ,那么就会有内部函数的返回
3、声明变量接收
4、那么,在函数内部就是 先定义 var num = 10 ; 然后 function fun 不执行(因为没调用不执行),再执行 return一下 fun 函数
注 : 里面有return 就得放变量名去接收一下
5、现在f里面存的就是一个函数 ,那么就可以调用
6、那么此时的fun 本身就在fn 里面,所以就可以打印出来num的值了,那么就可以实现在函数外部访问函数内部的值了
此时的闭包函数就是 fn
注 : 被访问的变量所在的函数就是闭包
里面的return 还可以写为 函数形式
闭包的作用
闭包函数的作用 : 延伸了变量的作用范围
闭包的面试题
案例 : 点击li 打印当前索引号
1、获取所有的li
2、利用 for 循环遍历lis
3、在 for 循环里面 创建立即执行函数
4、在立即执行函数里面 ,把 所有索引传递进去 ,且接收
5、所以在立即执行函数里面,就可以通过点击 li来获取值了
小tips :立即执行函数也称为小闭包, 因为 立即执行函数里面的任何一个函数都可以使用它传进来的这个变量
递归
递归的定义
-
若一个函数在内部可以调用其本身,那么这个函数就是递归函数
-
简单理解 : 函数内部自己调用自己,则这个函数就是递归函数
-
递归函数的作用和循环效果一样 ;
-
由于递归很容易发生 “ 栈溢出 ” 错误 ,所以必须要加退出条件 return
递归的应用
案例 : 求阶乘 123*...*n
详细思路 :
浅拷贝和深拷贝
浅拷贝
定义
只是拷贝一层,对于复杂数据类型来说,浅拷贝只会拷贝地址(引用)
使用
利用 for in 进行遍历对象 ,o[k] 就相当于 o.k ,也就相当于 在对象o里面添加属性k
- 所以 若修改拷贝后的对象 o , 那么 obj 里面的值也会被修改
es6语法糖
Object.assign(要拷贝给谁(目标对象),拷贝的是哪一个对象)
这样可以直接进行浅拷贝的复制
深拷贝
定义
是拷贝多层,每一级别的数据都会拷贝 ,
应用
1、创建 obj 和 o
2、封装了一个函数,用于进行深拷贝 , 把创建的 obj 和 o 传到函数里面
3、for in 遍历对象
4、判断属性值,判断 需要拷贝的值是属于数组还是对象还是简单数据类型
5、若是数组,那么就 给 newobj[k] = [] ,意思就是 给 newobj.k 开辟一个新的内存空间 , 是数组形式的 ; 然后进行递归
6、若都不是,那么就直接传进去
小tips : 先判断 是否属于数组形式的,再判断是否属于对象形式 ,因为 数组也属于对象