闭包(closure)
概念
闭包是(能够读取其他函数内部变量的)函数
特点
函数嵌套函数
内部函数持有外部函数的局部变量
内部函数就是闭包
看有没有形成闭包
控制台(打断点)
常见形式
形式一
function outer() {
var num = 10
function inner() {
console.log(num);
}
inner()
}
outer()
形式二
function outer() {
var num = 10
function inner() {
console.log(num);
}
return inner;
}
形式三
function outer() {
var num = 10
return function () {
console.log(num);
}
}
let x = outer(); // 函数调用后的结果是return后的结果
x()
形式四
function outer(num) { // 定义在函数内部或者函数的参数都属于局部变量
return function () {
console.log(num);
}
}
let x = outer(10); // 函数调用后的结果是return后的结果
x()
调用方式一
let x = outer(); // 返回存储空间的地址,这个存储空间需要调用一下
x(); // 找到这个地址,开辟指向空间,调用一下,执行函数体
调用方式二
outer()();
优缺点(作用)
优点(作用)
延长局部变量的生命周期,不会因为函数的调用就被销毁
让局部变量持久的保存在内存中
防止全局变量的污染
私有化变量
缺点
使用闭包过多,就会造成内存占用过大
存在内存泄漏
函数柯里化的形式
概念
是把接受多个参数的函数,变成接受一个单一参数的函数
返回结果是新函数的技术,新函数处理剩余的参数。
好处
函数式编程变得简洁
没有冗余
参数可以实现复用
形式
原函数
function getSum(a, b, c) {
return function () {
return function () {
return a + b + c;
};
}
}
console.log(getSum(10, 20, 30)()());
函数柯里化
function getSum(a) {
return function (b) {
return function (c) {
return a + b + c;
}
}
}
console.log(getSum(10)(20)(30));
递归
概念
在函数内部直接或者间接的调用函数本身
案例
求5的阶乘
function jieC(n){
if(n==1){
return 1
}
else{
return n*jieC(n-1)
}
}
jieC(5) === 5*jieC(4)
深浅拷贝(针对引用数据类型)
深拷贝
概念
赋值了一份值,相互之间不会受到影响
实现方案
JSON.parse(JSON.stringify(obj))
var obj = { name: 'zs', age: 13, wife: { name: "zs的妻子", obj: { city: "香港" } } };
var obj1 = JSON.parse(JSON.stringify(obj));
// 第一层 相互不影响
obj1.name = 'ls'; // 改的只是其中一个
console.log(obj1.name); // 'ls'
console.log(obj.name); // 'zs'
// 第二层 相互不影响
obj1.wife.name = 'ls的妻子'
console.log(obj1.wife.name); // 'ls的妻子'
console.log(obj.wife.name); // 'zs的妻子'
// 第三层 相互不影响
obj1.wife.obj.city = '深圳'
console.log(obj1.wife.obj.city );
console.log(obj.wife.obj.city );
for循环 + 递归
function copyObj(obj) {
var newobj = {};
for (var key in obj) {
if (typeof(obj[key]) == 'object') { // 如果你key对应的值是一个对象了,
newobj[key] = copyObj(obj[key]) ;// 重新调用函数
} else {
newobj[key] = obj[key]
}
}
return newobj;
}
var obj = { name: 'zs', wife: { name: "zs的妻子" } };
浅拷贝
概念
赋值了一份地址,相互直接会受到影响
实现方案
直接复制
var arr = [12, 34, 56, 67];
var arr1 = arr;// 直接复制
//改变其中一个,另一个也受到了影响
arr1[0] = 20;
console.log(arr1[0]); // 20
console.log(arr[0]); // 20
下面的四种只能实现:单层(第一层)相互不影响,内层相互之间会受到影响
slice(0)
var arr = [12,[12, 34, 56, 67],[12,34,65]];
var newarr = arr.slice(0);// [12,34,56,67]
// 第一层相互受不受影响
arr[0] = 10;
console.log(arr[0]); // 10
console.log(newarr[0]); // 12
// 第二层相互会受影响吗?受到了影响,说明这个slice只能让第一层实现相互不受影响
arr[1][0] = "新"
console.log(arr[1][0]); // "新"
console.log(newarr[1][0]); // "新"
展开运算符
var arr = [12,[12, 34, 56, 67],[12,34,65]];
var newarr = [...arr];
// 第一层是否相互影响?不影响
arr[0] = 10
console.log(arr[0]); // 10
console.log(newarr[0]); // 12
// 第二层相互受影响吗? 影响
arr[1][0] = '新'
console.log(arr[1][0]); // "新"
console.log(newarr[1][0]); // "新"
for循环遍历
var arr = [12, [12, 34, 56, 67], [12, 34, 65]];
var newarr = []
for (var i = 0; i < arr.length; i++) {
newarr.push(arr[i])
}
console.log(newarr); // 这个把arr拷贝过来了
// 改变其中一个另一个会受影响吗?
arr[0] = 10
console.log(arr[0]); // 10
console.log(newarr[0]); // 12
// 第二层相互受影响吗? 影响
arr[1][0] = '新'
console.log(arr[1][0]); // "新"
console.log(newarr[1][0]); // "新"