闭包closure,递归,深浅拷贝
闭包 closure
什么是闭包
闭包 closure 值有权访问另一个函数作用中变量的函数;-- JavaScript 高级程序设计
简单理解就是,一个作用域可以访问另外一个函数内部的局部变量
闭包的主要作用就是延伸了变量的作用范围;
// 一个局部作用域访问另一个局部作用域
function fn() {
var num = 10;
function fun() {
// fun 作用域中函数想要访问 fn 作用域中 num 变量 此时就会触发闭包,闭包也可以理解为一种现象;
console.log(num);
}
fun();
}
fn();
// 全局访问局部
function fn() {
var num = 10;
return function () {
console.log(num);
}
}
var f = fn(); // 因为return了这个匿名函数,f作为返回值接收了那么在执行f的时候 内部的匿名函数会找到上一个局部作用域中的num变量,就实现了全局作用域中访问了这个局部作用域
f(); // 10
// 如果没有闭包那么这个函数会在执行完毕后销毁这个变量,因为触发了闭包,这个num变量一直到f()调用后才会被销毁
案例 3s之后输出所有li
for (var i = 0; i < lis.length; i++) {
// 因为setTimeout内部是个异步函数,循环结束后才会执行,所以会报错
setTimeout(function () {
console.log(lis[i].innerHTML);
});
}
// 闭包实现方案
for (var i = 0; i < lis.length; i++) {
// 使用立即执行函数接收这个参数, 然后通过内部作用域访问外部作用域中的变量实现
// 但是这样会直接创建多个匿名函数,是不合理的所以闭包并不是都是好的
(function (i) {
setTimeout(function (){
console.log(lis[i].innerHTML);
})
})(i);
}
递归
什么是递归
如果在一个函数内部可以调用函数本身,那么这个函数就是递归函数
简单理解就是:函数内部自己调用自己, 这个函数就称为递归函数
递归函数的作用和循环效果一样,由于递归很容易发生 “栈溢出”(stack overflow),所以必须要加退出条件 return
function fn() { fn(); } fn(); // Maximum call stack size exceeded
1~n之间的阶乘
function fn(n) {
if (n == 1) return 1;
return n * fn(n - 1);
}
fn(3);
// 第一次调用 3 * fn(3 - 1);
// 3 * 2;
// 6 * fn(2 - 1);
// 6 * 1; 等于1 直接return 1
// 6;
斐波那契数列(前两个值得和等于第三个值)
function fb(n) {
// 前两个值相加等于第三个值,所以 1 和 2 都会返回 1
if (n === 1 || n === 2) return 1;
return fb(n - 1) + fb(n - 2);
}
浅拷贝与深拷贝
- 浅拷贝只是拷贝一层,更深层次对象级别只拷贝引用
- 深拷贝拷贝多层,每一级别的数据都会拷贝
浅拷贝
var obj = {
name: 'zs',
age: 23,
// msg 是一个对象,所以会重新开辟一块内存地址,存储进去
msg: {
desc: '浅拷贝'
}
}
var o = {}
// ES5实现
for (var key in obj) {
o[key] = obj[key]
}
console.log(o); // 此种拷贝方法只拷贝了一层;如果此时修改了obj的msg属性,那么o的msg属性也会被修改
obj.msg = 'ls';
console.log(o.msg.desc); // 此时obj的msg和o的msg就都修改为了 ls
// ES6中提供了实现浅拷贝的语法糖
Object.assign(o, obj); // 此时方式与上面for in 实现一样
深拷贝
// 利用递归实现深拷贝
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
// 先获取oldobj的每一项属性值
var item = oldobj[k];
// 因为数组也属于对象,所以一定要先判断数组
if (item instanceof Array) {
newobj[k] = [];
// 使用for in 循环数组时, newobj[k] = 数组中每一项值;k = 数组中每一项的索引
deepCopy(newobj[k], item);
} else if (item instanceof Object) {
newobj[k] = {};
deepCopy(newobj[k], item);
} else {
newobj[k] = item;
}
}
}
deepCopy(o, obj);
// 使用 JSON.stringify() 和 JSON.parse()
var temp = JSON.stringify(obj);
var o = JSON.parse(temp); // 此时在修改o的里面的对象以及数组也不会受到obj的影响

浙公网安备 33010602011771号