高级函数
1.闭包的使用范围
//1.想访问函数中的局部变量的时候
function outer() {
var a = 10;
function inner() {
return a;
}
return inner
}
var res = outer();
var a1 = res();// a1 10
//2.解决全局作用域问题
var arr = [];
for (var i = 0; i < 10; i++) {
arr.push(function () { console.log(i) })
}
console.log(arr);//[ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]
arr[3]();// 10
//修改
var arr = [];
for (var i = 0; i < 10; i++) {
(function (i) {
arr.push(function () { console.log(i) })
})(i)
}
console.log(arr);//[ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]
arr[3]();// 3
// 3.模拟私有属性
function Student() {
var name = "张三";// name是Student的私有属性
function getName() {
return name
}
function setName(a) {
name = a
}
return {
"get": getName,
"set": setName
}
}
var s = new Student();//可以随意访问私有属性
console.log(s);
var a1 = s.get();
console.log(a1);//张三
s.set("李四")
2.递归函数
2.1阶乘递归
- 递归函数:在函数内部调用函数本身 自己调自己
- 和for循环的区别:循环无线执行回变成死循环,卡死;递归右最大栈调用次数 超过就报错
- 递归函数的实现步骤
- 找规律
- 递:在函数内部调用函数本身 自己调自己
- 归:在函数开头一定要有结束条件 如果没有结束条件 就会报错栈溢出
<script>
//1.求10! 10*9*8......*1
// for循环 始终不结束循环 会导致死循环 不会提示报错 卡死
var s = 1
for (var i = 1; i <= 5; i++) {
s *= i;//s = s* i
}
console.log(s);
/*
2.递归:在函数内部调用函数本身 自己调自己
1.找规律
2.递 自己调用自己
3.归 在函数开头一定要有结束条件 如果没有结束条件 就会报错栈溢出
6! 6*5!
5! 5*4!
4! 4*3!
3! 3*2!
2! 2*1!
1! 1
n! = n*(n-1)!
*/
function jc(n) {
if (n == 1) return 1;
return n * jc(n - 1)
}
/* jc(6)
6*jc(5)
5*jc(4)
4*jc(3)
3*jc(2)
2*jc(1)
1
*/
var res = jc(5);
console.log(res);
/*
递归和for循环的区别
循环无线执行回变成死循环,卡死
递归右最大栈调用次数 超过就报错
*/
</script>
2.2斐波那契数列
<script>
/*
1.找规律
1、1、2、3、5、8、13、21、34..........
//n 代表第几位 是位置
第4个数 = (4-1)位数 + (4-2)位数
第5个数 = (5-1)位数 + (5-2)位数
第n个数 = (n-1)位数 + (n-2)位数
f(n) = f(n-1) + f(n-2)
2.归
n = 1 n = 2 值都是1
*/
function fun1(n) {
if (n == 1 || n == 2) return 1;
return fun1(n - 1) + fun1(n - 2)
}
var res = fun1(5);
console.log(res);
2.3快速排序
- 获取数组中中间的值 var middle = arr.splice(Math.floor(arr.length/2),1)[0]
- 定义两个空数组 left和right
- 依次用数组元素和中间值作比较 比中间值小放入left 比中间中大的放入right
- 组合成一个新的数组 concat
<script>
/*
1.获取数组中中间的值
var middle = arr.splice(Math.floor(arr.length/2),1)[0]
2.定义两个空数组 left和right
3.依次用数组元素和中间值作比较 比中间值小放入left 比中间中大的放入right
4.组合成一个新的数组 concat
结束条件:当数组的length为0或者为1
*/
var arr = [12, 7, 10, 4, 5, 9, 8];//4 下标值3 Math.floor(arr.length/2)
function quick(arr) {
if (arr.length <= 1) return arr;
// 1.找中间值
var middle = arr.splice(Math.floor(arr.length / 2), 1)[0];
// 2.定义left和right
var left = [];
var right = [];
//3.依次和中间值比较
for (var i = 0; i < arr.length; i++) {
if (arr[i] < middle) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
// 4.组合新新数组
return quick(left).concat(middle, quick(right))
}
var res = quick(arr);
console.log(res);
</script>
3.防抖和节流
1.为什么要使用防抖和节流
有些事件的操作是高频率触发的 但其实触发一次就可以了
防抖和节流就是减少事件发生的频率
2. 防抖的原理
在事件处理函数中添加一个定时器 在定时器中执行代码 延迟一定的时间执行代码
如果你在定时器执行过程中再次触发事件 把原先的定时器清除,再重新定义
function debounce(fun, wait) {
var timer;
function show() {
// 如果timer有值 定时器没有走完
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(fun, wait)
}
return show
}
3.节流的原理
在事件处理函数中添加一个延时定时器,延迟一定的时间执行代码
在当前定时器没有完成之前 禁止事件执行 等定时器完成之后再允许事件执行
function throttle(fun, wait) {
var timer;
function show() {
// 如果timer有值 定时器没有结束 没有值的时候才去执行
if (!timer) {
timer = setTimeout(function () {
fun();//要做的事有很多 放入函数执行
timer = undefined;
}, wait)
}
}
return show
}