递归: 函数自己调用自己
递归,一般都要写一个结束的条件,不然会因为
内存溢出
(超过了最大的堆栈大小),而报错
Maximum call stack size exceeded
// 递归推导过程:
// n = 3, 3 + getSum(3 - 1) -> 2 + 1
// n = 2, 2 + getSum(2 - 1) -> 1
// n = 1, 1
function getSum(n) {
// 递归结束的条件
if (n === 1) {
return 1;
}
return n + getSum(n - 1); // 不断调用getSum()函数,直到满足条件退出
}
console.log(getSum(3)); // 结果是:6
需求:1 * 2 * 3…* n
// 递归推导过程:
// n = 3, 3 * fn(3 - 1)
// n = 2, 2 * fn(2 - 1)
// n = 1, 1
function fn(n) {
if (n === 1) {
return 1;
}
return n * fn(n - 1);
}
console.log(fn(3)); // 1*2*3 结果是:6
console.log(fn(4)); // 1*2*3*4 结果是:24
1、1、2、3、5、8、13、21、34、
// 从第三个数开始:第三个数是前两个数之和
// 第n个数是 n-1个数 和 n-2 个数之和(n>=3)
function fn(n) {
if (n === 1 || n === 2) {
return 1;
}
return fn(n - 1) + fn(n - 2);
}
console.log(fn(3)); // 结果为:2
console.log(fn(5)); // 结果为:5
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
<script>
// .................对象的拷贝..............
var obj1 = {
name: 'zs',
age: 18,
sex: '男'
}
var obj2 = {
};
// 遍历对象中的成员
for (var key in obj1) {
// obj1[key] //属性作为变量可以采用[]形式
obj2[key] = obj1[key];
}
// 修改obj1的成员,此时不会影响obj2
obj1.name = 'xx';
console.dir(obj2);
// ............封装函数 - 把o1 的成员,复制给o2......
var obj1 = {
name: 'zs',
age: 18,
sex: '男'
}
var obj2 = {
};
function copy(o1, o2) {
for (var key in o1) {
o2[key] = o1[key];
}
}
copy(obj1, obj2);
console.dir(obj2);
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
<script>
// 注意:只有复杂数据类型:才有拷贝的价值!
// 然后复杂数据类型里面:再分 简单数据类型 和 复杂数据类型
// (1)在浅拷贝中:
// 简单数据类型:复制值;一方修改不会影响另一方
// 复杂数据类型:复制地址;一方修改会影响另一方
// (2)而在深拷贝中:
// 简单数据类型:一方修改不会影响另一方
// 复杂数据类型:一方修改不会影响另一方
// ...............对象的拷贝......................
// 简单数据类型:复制值;一方修改不会影响另一方
// 复杂数据类型:复制地址;一方修改会影响另一方
// .....浅拷贝 封装函数 - 把o1 的成员,复制给o2.....
var obj1 = {
name: 'zs',
age: 18,
sex: '男',
dog: {
name: '金毛',
age: 2,
yellow: '黄色'
}
}
var obj2 = {
};
function copy(o1, o2) {
for (var key in o1) {
o2[key] = o1[key];
}
}
copy(obj1, obj2);
// 修改obj1中的成员
obj1.name = 'xxxx'; // 简单数据类型
obj1.dog.name = '大黄'; // 复杂数据类型
console.dir(obj2);
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
<script>
// 注意:只有复杂数据类型:才有拷贝的价值!
// 然后复杂数据类型里面:再分 简单数据类型 和 复杂数据类型
// (1)在浅拷贝中:
// 简单数据类型:复制值;一方修改不会影响另一方
// 复杂数据类型:复制地址;一方修改会影响另一方
// (2)而在深拷贝中:
// 简单数据类型:一方修改不会影响另一方
// 复杂数据类型:一方修改不会影响另一方
// .............对象的拷贝--深拷贝................
var obj1 = {
name: 'zs',
age: 18,
sex: '男',
dog: {
name: '金毛',
age: 2,
yellow: '黄色'
},
friends: ['lilei', 'hanmeimei']
}
var obj2 = {
};
var arr = [];
// // 证明:数组也是对象
// console.log(arr instanceof Array); // true
// console.log(arr instanceof Object); // true
// 深拷贝
// 判断一个变量(属性也相当于变量)的类型: instanceof
// 情形一:如果key是数组类型
// 分析:1.首先我们给o2增加属性[key],它的值应该等于?
// 我不能像之前的基本类型一样直接赋值,基本类型直接赋值就是把值直接赋值过去
// 如果是复杂类型复制的是另一个对象的引用式地址
// 所以如果我们想把对象在内存中复制一份,我们要做一次拷贝的操作
// 如果是数组先初始化一个空数组,因为数组的本质也是对象;我们可以把数组的索引看成属性
// 我们把o1中friends属性的第0项拷贝到02的数组[]中;接着拷贝第二项...o2[key] = [];
// 2.把数组的索引看成属性,接着把数组看成对象;我们要拷贝对象的所有属性,我们就可以调用deepCopy方法
// 用递归的方式解决问题 o1[key]是个属性但这个属性也是一个对象;我们将这个对象的所有成员拷贝给 o2[key]
// 情形一:如果key是复杂类型 Object? {}
// 分析:1.首先我们给o2增加属性[key],因为它是对象所以初始化为空对象{}
// 2.o1[key]是个属性但这个属性也是一个对象;我们将这个对象的所有成员拷贝给 o2[key]
function deepCopy(o1, o2) {
for (var key in o1) {
if (o1[key] instanceof Array) {
console.log(key);
// 1.如果key是数组类型 Array? []
o2[key] = [];
deepCopy(o1[key], o2[key]);
} else if (o1[key] instanceof Object) {
// 2.如果key是复杂类型 Object? {}
o2[key] = {
};
deepCopy(o1[key], o2[key]);
} else {
// 3.如果key这个属性 是基本类型
o2[key] = o1[key];
}
}
}
deepCopy(obj1, obj2); // obj1里面的内容 拷贝给 obj2
// 修改obj1中的成员
obj1.name = 'xxxx';
obj1.dog.name = '大黄';
obj1.friends[0] = 'xxxx';
console.dir(obj1);
console.dir(obj2);
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
head>
<body>
<script>
// 注意:只有复杂数据类型:才有拷贝的价值!
// 然后复杂数据类型里面:再分 简单数据类型 和 复杂数据类型
// (1)在浅拷贝中:
// 简单数据类型:复制值;一方修改不会影响另一方
// 复杂数据类型:复制地址;一方修改会影响另一方
// (2)而在深拷贝中:
// 简单数据类型:一方修改不会影响另一方
// 复杂数据类型:一方修改不会影响另一方
// .............对象的拷贝--深拷贝................
var obj1 = {
name: 'zs',
age: 18,
sex: '男',
dog: {
name: '金毛',
age: 2,
yellow: '黄色'
},
friends: ['lilei', 'hanmeimei']
}
var obj2 = {
};
var arr = [];
// // 证明:数组也是对象
// console.log(arr instanceof Array); // true
// console.log(arr instanceof Object); // true
// 深拷贝
// 判断一个变量(属性也相当于变量)的类型: instanceof
// 情形一:如果key是数组类型
// 分析:1.首先我们给o2增加属性[key],它的值应该等于?
// 我不能像之前的基本类型一样直接赋值,基本类型直接赋值就是把值直接赋值过去
// 如果是复杂类型复制的是另一个对象的引用式地址
// 所以如果我们想把对象在内存中复制一份,我们要做一次拷贝的操作
// 如果是数组先初始化一个空数组,因为数组的本质也是对象;我们可以把数组的索引看成属性
// 我们把o1中friends属性的第0项拷贝到02的数组[]中;接着拷贝第二项...o2[key] = [];
// 2.把数组的索引看成属性,接着把数组看成对象;我们要拷贝对象的所有属性,我们就可以调用deepCopy方法
// 用递归的方式解决问题 o1[key]是个属性但这个属性也是一个对象;我们将这个对象的所有成员拷贝给 o2[key]
// 情形一:如果key是复杂类型 Object? {}
// 分析:1.首先我们给o2增加属性[key],因为它是对象所以初始化为空对象{}
// 2.o1[key]是个属性但这个属性也是一个对象;我们将这个对象的所有成员拷贝给 o2[key]
function deepCopy(o1, o2) {
for (var key in o1) {
if (o1[key] instanceof Array) {
console.log(key);
// 1.如果key是数组类型 Array? []
o2[key] = [];
deepCopy(o1[key], o2[key]);
} else if (o1[key] instanceof Object) {
// 2.如果key是复杂类型 Object? {}
o2[key] = {
};
deepCopy(o1[key], o2[key]);
} else {
// 3.如果key这个属性 是基本类型
o2[key] = o1[key];
}
}
}
deepCopy(obj1, obj2); // obj1里面的内容 拷贝给 obj2
// 修改obj1中的成员
obj1.name = 'xxxx';
obj1.dog.name = '大黄';
obj1.friends[0] = 'xxxx';
console.dir(obj1);
console.dir(obj2);
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>遍历DOM树title>
head>
<body>
<h1>遍历 DOM 树h1>
<p style="color: green;">Tip: 可以在遍历的回调函数中任意定制需求p>
<div>
<ul id="list">
<li>123li>
<li>456li>
<li>789li>
ul>
div>
<script>
// .....遍历指定元素下所有的子元素:应用如:注册事件或者设置样式..........
// loadTree的时候我们找到了所有的子元素,并且把它们打印出来;这样做没有什么实际意义
// 我们希望找到这些子元素之后,可以为子元素注册事件或者设置样式...
// 让外面的人操作我们找到的这些子元素;
// 我们做这些操作需要指定一些代码,这些代码我们可以通过函数传递进来callback,通过callback不停的调用回调函数
// 中途用户有可能忘记传递参数了,所以进行if判断,保证用户传递内容
function loadTree(parent, callback) {
for (var i = 0; i < parent.children.length; i++) {
// 遍历第一级子元素
var child = parent.children[i];
console.log(child);
if (callback) {
// 处理找到的子元素
callback(child); // 调用callback的时候,把child传给function(element)
}
// 递归调用
loadTree(child); // 此时child作为父元素再找child里面的子元素
}
}
var ul = document.getElementById('list');
loadTree(ul, function (element) {
// 为所有子元素注册点击事件
element.onclick = function () {
console.log(this.innerText);
this.style.color = 'red';
}
});
// 构思:loadTree的第一个参数:找谁里面的子元素 ;第二个参数:找到子元素后干什么(传入函数--> callback进行调用)
// 需求:给ul的所有子元素注册点击事件
// 1.获取ul元素
// 2.调用loadTree
script>
body>
html>