一、統(tǒng)計(jì)html文檔元素
HTML:
<!DOCTYPE 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>寫一個(gè)方法,統(tǒng)計(jì)一下html文檔的元素包括元素的數(shù)量</title>
</head>
<body>
<h2>標(biāo)題</h2>
<div>
<p>段落<span>文字</span></p>
</div>
</body>
<script></script>
</html>
1、js獲取頁面上的所有標(biāo)簽
var a = new Set([...document.querySelectorAll('*')].map(v => v.tagName));
var b = new Set(Array.from(document.querySelectorAll('*')).map(v => v.tagName));
console.log(a,b);
結(jié)果如下圖:

2、js遞歸獲取html頁面所有標(biāo)簽
var child = document.children;
var arr = [];//用來存放獲取到的所有的標(biāo)簽
function fn(obj) {
for(var i=0;i<obj.length;i++){
if(obj[i].children){//當(dāng)當(dāng)前元素還存在子元素的時(shí)候,遞歸
fn(obj[i].children);
}
arr.push(obj[i]); //遍歷到的元素添加到arr這個(gè)數(shù)組中間
}
}
fn(child);
console.log(arr);//打印出最后獲取到的結(jié)果
//(12) [meta, meta, meta, title, head, h2, span, p, div, script, body, html]
3、js獲取頁面所有元素并統(tǒng)計(jì)每個(gè)標(biāo)簽的個(gè)數(shù)
let el = document.getElementsByTagName('*');
let elObj = {};
for(var i=0; i<el.length;i++){
if(!elObj[el[i].tagName.toLowerCase()] ){
elObj[el[i].tagName.toLowerCase()] = 1;
}else{
elObj[el[i].tagName.toLowerCase()] ++;
}
}
console.log(elObj)
結(jié)果如下圖:

二、js 遞歸調(diào)用
1、遞歸的概念
在程序中函數(shù)直接或間接調(diào)用自己
遞歸遍歷是比較常用的方法,比如:省市區(qū)遍歷成樹、多叉樹、階乘等。
注意:使用遞歸函數(shù)一定要注意,處理不當(dāng)就會(huì)進(jìn)入死循環(huán)。遞歸函數(shù)只有在特定的情況下使用 ,比如階乘問題。
2、例子
(1)一個(gè)階乘的例子
function fact(num) {
if (num <= 1) {
return 1;
} else {
return num * fact(num - 1);
}
}
console.log(fact(3)) // 結(jié)果為 6
以下代碼可導(dǎo)致出錯(cuò):
var anotherFact = fact;
fact = null;
alert(antherFact(4)); //出錯(cuò)
由于fact已經(jīng)不是函數(shù)了,所以出錯(cuò)。
使用arguments.callee
arguments.callee 是一個(gè)指向正在執(zhí)行的函數(shù)的指針,arguments.callee 返回正在被執(zhí)行的對現(xiàn)象。
新的函數(shù)為:
function fact(num){
if (num<=1){
return 1;
}else{
return num*arguments.callee(num-1); //此處更改了。
}
}
var anotherFact = fact;
fact = null;
console.log(anotherFact(4)); //結(jié)果為24.
(2)一個(gè)多叉樹的例子
先看圖

數(shù)據(jù)結(jié)構(gòu)格式,參考如下代碼:
var headerData = {
name: '總數(shù)據(jù)',
children: [
{
name: '數(shù)據(jù)1',
children: [
{
name: '數(shù)據(jù)11',
children: [
{
name: '數(shù)據(jù)111',
},
{
name: '數(shù)據(jù)112',
}
]
},
{
name: '數(shù)據(jù)12',
children: [
{
name: '數(shù)據(jù)121',
},
{
name: '數(shù)據(jù)122',
}
]
},
{
name: '數(shù)據(jù)13',
children: [
{
name: '數(shù)據(jù)131',
},
{
name: '數(shù)據(jù)132',
}
]
},
{
name: '數(shù)據(jù)14',
},
]
}
]
}
我們?nèi)绾潍@取節(jié)點(diǎn)的所有葉子節(jié)點(diǎn)個(gè)數(shù)呢? 遞歸代碼如下:
/**
* 獲取 節(jié)點(diǎn)的所有 葉子節(jié)點(diǎn) 個(gè)數(shù)
* @param {Object} json Object對象
*/
function getLeafCountTree(json) {
if(!json.children){
return 1;
}else{
var leafCount = 0;
for(var i = 0 ; i < json.children.length ; i++){
leafCount = leafCount + getLeafCountTree(json.children[i]);
}
return leafCount;
}
}
console.log(getLeafCountTree(headerData)); // 7