JavaScript学习笔记(十一)--递归(深拷贝/浅拷贝)

222 阅读2分钟

递归

  • 什么是递归

递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。简单理解:函数内部自己调用自己, 这个函数就是递归函数 函数的递归,递归函数 递归:函数调用函数其本身 **注意:**递归函数的作用和循环效果一样,由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件return。


	利用递归求1~n的任意一个数的阶乘

	/* 3的阶乘==》3X2X1
		6的阶乘==》6X5X4X3X2X1
		 9的阶乘==》9X8X7X6X5X4X3X2X1
		 利用递归求1~n的任意一个数的阶乘*/

		 function jC (n) {
		 nx(n-1)x(n-1-1)x(n-1-1-1)......1
	 	if (n == 1) {
			return 1;
		 	}
			// 我们要的是一个结果
			return n * jC(n-1);
	 		return 4 * jC(3);
		 	return 4 * 3 * 2 * 1;
			}
		 console.log( jC(4) );


		/*利用递归求斐波那契数列
		利用递归函数求斐波那契数列(兔子序列) 
		 从第三个月开始生兔子
		 1、1、2、3、5、8、13、21...
		 第n个月有几对兔子*/
		function fb (n) {
			/* 递归点:前一个月 +前二的月的兔子
			 出口点:第一个月和第二个月是固定的都是1*/
			if (n == 1 || n == 2) {
				return 1;
			}

			return fb(n-1) + fb(n-2);
			/* return fb(5) + fb(4);
			   return 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1;*/

		    }
		console.log( fb(6) );
		/* console.log( fb(8) );
		   console.log( fb(13) );*/

	<script type="text/javascript">
		
			var data = [ 
			{
				id : 1,
				name : '家电',
				goods : [
					{
						id : 11,
						name : '冰箱',
						goods : [
							{
								id : 111,
								name : '海尔'
							},{
								id : 112,
								name : '美的'
							}
						]
					},{
						id : 12,
						name : '洗衣机 '
					}
				]
			},
			{
				id : 2,
				name : '服饰'
			}
		];

		
		// var data = [{},{}];
		// 写一个函数,根据给出得到id去能够获取指定的数据
		// 获取数据
		function getId (arr, id) {
			// 定义一个变量
			var obj = {};
			// 遍历
			arr.forEach(function (val, index) {
				// val = { id : 1, name : '加点'}
				if (val.id == id) {
					obj = val;
				} else if (val.goods && val.goods.length > 0) {
					obj = getId(val.goods, id);
				}
			});
			return obj;
		}


		console.log( getId(data,111) );

		// id = 10086
                

深拷贝和浅拷贝

  • 拷贝不能直接赋值,对象赋值的是地址
	var obj = {
		name : '张三丰',
		age : 22
	};
	var newObj = obj;
	console.log(newObj);
  • 浅拷贝:

    • 只拷贝最外面一层
    
    	var obj = {
    		name : '张三丰',
    		age : 22,
    		// color : ['red','blue','yellow'],
    		// message : {sex : '男',score : 99}
    	};
    
    	var newObj = {};
    
    	Object.assign(newObj, obj);
    
    	obj.name = '李寻欢';
    
    	console.log(obj, newObj);
    
    	// 遍历
    	 for ( key in obj ) {
    		// obj有什么newObj就有什么
    	 	newObj[key] = obj[key];
    	 }
    
    	 obj.name = '阿飞';
    	 obj.message.sex = '女';
    
    	 console.log(obj);
    	 console.log(newObj);
    
    	// obj.name
    	// obj有什么newObj就有什么
    	 newObj.name = obj.name;
    	 newObj.age = obj.age;
    
    	obj.name = '李寻欢';
    	 console.log(obj);
    	 console.log(newObj);
    
    	 newObj = '张三丰';
    </script>
    	 
    

深拷贝


			var obj = {
  		name : '张三丰',
  		age : 22,
  		color : ['red','blue','yellow'],
  		message : {sex : '男',score : 99}
  	};

  	var newObj = {};

  	// 封装
  	function kaobei (newObj, obj) {
  		/* 要把obj拷贝给newObj
  		 我们发现,obj[key]可能是数组,还能是对象,具有复杂数据
  		 那么此时直接拷贝,又会变成复杂数据类型传递*/
  		for ( key in obj ) {
  			// newObj[key] = obj[key];
  			if ( obj[key] instanceof Array ) { /* obj[key]是数组,就在遍历
  				在遍历
  				newObj[key] = obj[key]*/
  				newObj[key] = [];
  				kaobei(newObj[key], obj[key]);
  			} else if ( obj[key] instanceof Object ) { // obj[key]是对象,就在遍历
  				// newObj[key] = obj[key]
  				newObj[key] = {};
  				kaobei(newObj[key], obj[key]);
  			} else {
  				newObj[key] = obj[key];
  			}
  		}
  	}

  	kaobei(newObj, obj);

  	// obj.name = 'aaa';
  	obj.message.sex = '女';

  	console.log(obj);
  	console.log(newObj);


如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。

首先深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。

  • 浅拷贝:只拷贝最外面一层【Object.assign(newObj,obj)】

  • 深拷贝:所有层都拷贝