闭包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 实现一样

深拷贝

深拷贝理解 参考 https://www.cnblogs.com/echolun/p/7889848.html

// 利用递归实现深拷贝
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的影响
posted @ 2020-04-12 19:07  计算机相关人员  阅读(267)  评论(0)    收藏  举报