闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数(一个作用域可以访问另外一个函数内部的局部变量)
function fn() {
var num = 10;
function fun() {
console.log(num)
}
return fun;
}
var f = fn(); // 可以访问fn内部的局域变量
f(); // 10
闭包的主要作用:延伸变量的使用范围。
闭包案例
1.循环注册点击事件(获取索引号)
常规写法:
<ul class = "nav">
<li>华为</li>
<li>vivo</li>
<li>oppo</li>
<li>小米</li>
</ul>
<script>
var lis = document.querySelector('.nav').querySelectorAll('li');
for(var i= 0; i<lis.length; i++) {
lis[i].index = i; // 动态添加属性
lis[i].onclick = function() {
console.log(this.index);
}
}
利用闭包方式:
<ul class = "nav">
<li>华为</li>
<li>vivo</li>
<li>oppo</li>
<li>小米</li>
</ul>
<script>
var lis = document.querySelector('.nav').querySelectorAll('li');
for(var i= 0; i<lis.length; i++) {
(function(i){
lis[i].onclick = function() {
console.log(i);
}
})(i);
2.循环中的setTimeout()(3秒后打印li中所有内容
闭包写法(解决异步执行问题):
for(var i=0; i<lis.length; i++) {
(function(i) {
setTimeout(function() {
console.log(lis[i].innerHTML);
},3000)
})(i);
}
递归
递归函数:一个函数在内部可以调用其本身;作用和循环效果一样;但容易发生栈溢出错误,必须在后面加退出条件return
利用递归求数学题:
// 求1-n 的阶乘
function fn(n) {
if(n == 1) {
return 1;
}
return n*fn(n-1);
}
fn();
// 求斐波纳契数列(兔子序列) 1 1 2 3 5 8 13 .....
function fnn(n) {
if(n ===1 || n===2) {
return 1;
}
return fnn(n-1) + fnn(n-2);
}
fnn();
利用递归求:根据id返回对应的数据对象
var data = [{
id:1,
name:'家电',
goods:[{
id:11,
gname:'冰箱'
},{
id:12,
gname:'洗衣机'
}]
},{
id:2,
name:'手机'
}];
// 输入id号,就可以返回数据对象
function getID(json,id) {
var = {};
// forEach用处与for相同,可以做循环
json.forEach(functioin(item) {
if (item.id == id) {
o = item;
return item;
} else if (item.goods && item.goods.length > 0) {
o = getID(item.goods,id);
}
});
return o;
}
console.log(getID(data,1));
console.log(getID(data,2));
console.log(getID(data,11));
深(浅)拷贝
1.浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用;
2.深拷贝拷贝多层,每一级别的数据都会拷贝;
3.Object.assign(target,…sources) es6新增方法可以浅拷贝
// 浅拷贝
var obj = {
id:1,
name:'andy',
mag:{
age:18
}
};
var o = { };
for(var k in obj) {
// k是属性名 obj[k]属性值
o[k] = obj[k];
}
console.log(o);
o.msg.age = 20; //会改变obj里面原有的值
console.log(obj);
Object.assign(o,obj); // es6新增
// 深拷贝
var obj = {
id:1,
name:'andy',
mag:{
age:18
}
};
var o = { };
// 利用递归,封装函数
function deepCopy(newobj,oldobj) {
for(var k in oldobj) {
// 判断属性值属于哪种数据类型
// 1.获取属性值 oldobj[k]
var item = oldobj[k];
// 2.判断这个值是否是数组
if(item instanceof Array) {
newobj[k] = [];
deepCopy(newobj[k],item)
}else if(item instanceof object) {
// 3.判断这个值是否是对象
newobj[k] = { };
deepCopy(newobj[k],item)
} else {
// 4.属于简单数据类型
newobj[k] = item;
}
}
}
deepCopy(o,obj);
console.log(o);