高阶函数
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出
闭包(closure)----有权访问另一个函数作用域中变量的函数
<script>
// 闭包: 我们fun 这个函数作用域 访问了另外一个函数 fn 里面的局部变量 num
function fn() {
var num = 10;
function fun() {
console.log(num);
}
fun();
}
fn();
</script>
闭包的主要作用----延伸了变量的作用范围
<script>
// 闭包指一个作用域可以访问另外一个函数的局部变量
// 我们fn 外面的作用域可以访问fn 内部的局部变量
// 闭包的主要作用: 延伸了变量的作用范围
function fn() {
var num = 10;
return function() {
console.log(num);
}
}
var f = fn();
f();
// 类似于
// var f = function() {
// console.log(num);
// }
</script>
应用
<script>
// 闭包应用-点击li输出当前li的索引号
// 1. 我们可以利用动态添加属性的方式
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);
};
}
// 2. 利用闭包的方式得到当前小li 的索引号
// 利用for循环创建了4个立即执行函数
// 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
for (var i = 0; i < lis.length; i++) {
(function (i) {
lis[i].onclick = function () {
console.log(i);
};
})(i);
}
</script>
<script>
// 闭包应用-计算打车价格
// 打车起步价13(3公里内), 之后每多一公里增加 5块钱. 用户输入公里数就可以计算打车价格
// 如果有拥堵情况,总价格多收取10块钱拥堵费
var car = (function() {
var start = 13; // 起步价 局部变量
var total = 0; // 总价 局部变量
return {
// 正常的总价
price: function(n) {
if (n <= 3) {
total = start;
} else {
total = start + (n - 3) * 5
}
return total;
},
// 拥堵之后的费用
yd: function(flag) {
return flag ? total + 10 : total;
}
}
})();
console.log(car.price(5)); // 23
console.log(car.yd(true)); // 33
console.log(car.price(1)); // 13
console.log(car.yd(false)); // 13
</script>
<script>
// 思考题 1:
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name;
};
}
};
//相当于一个立即执行函数(function(){this}()) this指向window 没有闭包产生
console.log(object.getNameFunc()())//The Window
// 类似于
var f = function() {
return this.name;
}
f();
// 思考题 2:
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
var that = this;
return function () {
return that.name;
};
},
};
//这里this指向 My Object 此时有闭包产生
console.log(object.getNameFunc()());//--My Object
</script>
递归函数----函数内部自己调用自己
递归的作用和循环一样,由于很容易发生‘栈溢出’错误(stack overflow),所以必须要加退出条件return
应用
//应用1----求1~n的阶乘
function fn(n) {
if (n == 1) {
return 1;
}
return n * fn(n - 1);
}
console.log(fn(3));
//应用2----求斐波那契数列 1、1、2、3、5、8、13...
function fn(n) {
if (n == 1 || n == 2) {
return 1;
}
return fn(n - 1) + fn(n - 2);
}
console.log(fn(6));
<script>
var data = [
{
id: 1,
name: "家电",
goods: [
{
id: 11,
gname: "冰箱",
goods: [
{
id: 111,
gname: "海尔",
},
{
id: 112,
gname: "美的",
},
],
},
{
id: 12,
gname: "洗衣机",
},
],
},
{
id: 2,
name: "服饰",
},
];
// 1.利用foreach 去遍历里面的每一个对象
function getId(json, id) {
var o = {};
json.forEach(function (item) {
if (item.id == id) {
o = item;
return item;
//2. 通过递归函数得到里层的数据 , if(里面有goods这个数组且长度部位0)
} else if (item.goods && item.goods.length > 0) {
o = getId(item.goods, id);
}
});
return o; //返回对象o 里面保存的是筛选完的数据
}
console.log(getId(data, 1));
console.log(getId(data, 11));
console.log(getId(data, 111));
</script>
浅拷贝和深拷贝
浅拷贝只是拷贝一层, 更深层次对象级别的只拷贝引用.
深拷贝拷贝多层, 每一级别的数据都会拷贝.