Day02-JS高级编程
一、闭包(扩展)
概念:闭包指的就是在子函数中,可以访问父级函数中的变量。闭包形成的条件,需要在一个函数中嵌套一个子函数,内部函数访问外部函数的变量。
案例1-闭包的基础
/**
* 函数声明
*/
function fun(){
var name = "hello"
return function(){
console.log(name);
}
}
//外部函数调用,外部函数执行完后,函数的代码会从栈内存中销毁
let fun2 = fun()
// console.log(fun2);
//调用子函数
fun2()
fun()调用完成后,fun这个函数会从内存中清除。
变量name会存放在闭包空间里面。
当调用内部函数fun2(),name使用完,闭包空间里面对应name消失
案例2
如下代码输出的结果都是一样的
<script>
/**
* 页面打开,for循环会立马执行,会创建5个延时器
* 延时器在定时时间到了才会执行
*
* 循环执行完后,i的值已经是5了,又过了5秒延时器开始执行,延时器要输出变量i,会输出变量i的最终结果
*/
for(var i=0;i<5;i++){
setTimeout(() => {
console.log("-------",i);
}, 5000);
}
</script>
使用闭包解决这个问题
<script>
/**
* 页面打开,for循环会立马执行,会创建5个延时器
* 延时器在定时时间到了才会执行
*
* 循环执行完后,i的值已经是5了,又过了5秒延时器开始执行,延时器要输出变量i,会输出变量i的最终结果
*/
for(var i=0;i<5;i++){
//立即执行函数作为父级函数,index是父级函数的变量
(function(index){
//延时器中的函数作为子函数,
setTimeout(() => {
console.log("-------",index);
}, 5000);
})(i)
}
</script>
案例3
如下代码输出的结果都是一样的
<script>
//数组里面可以存储任何数据,包括对象,函数等
var arr = []
for(var j=0;j<5;j++){
arr.push(function(){
console.log(j);
})
}
arr[0]()
arr[1]()
arr[2]()
arr[3]()
arr[4]()
</script>
使用闭包解决这个问题
<script>
//数组里面可以存储任何数据,包括对象,函数等
var arr = []
for(var j=0;j<5;j++){
(function(index){
arr.push(function(){
console.log(index);
})
})(j)
}
arr[0]()
arr[1]()
arr[2]()
arr[3]()
arr[4]()
</script>
总结
闭包属于了解性知识点
在ES5中闭包用的比较多,在ES6中使用let创建变量来代替闭包这个知识
二、内存空间讲解
基本数据类型: 字符串 数字 布尔 undefined null
引用数据类型: 数组 对象 函数
案例1
<script>
/**
* 基本数据类型
*/
let a1 = 100
let a2 = a1
//修改变量a1的值为200
a1 = 200
console.log("a1=",a1);
console.log("a2=",a2);
console.log("-------------------");
/**
* 引用数据类型
*/
let arr1 = [1,2,3]
let arr2 = arr1
//修改数组arr1中下标为0的元素,修改成300
arr1[0] = 300
console.log("arr1=",arr1);
console.log("arr2=",arr2);
</script>
案例2
上下文
代码在执行过程中会有两种上下文对象
- 全局上下文:打开浏览器时,内存里面就有产生一个全局上下文(window),当浏览器关闭,全局上下文就销毁。
- 函数上下文:当函数被调用的时候,产生一个函数上下文对象,函数调用结束,这个函数上下文对象就会消失。
三、对象的拷贝
对象拷贝:将程序中的对象,克隆一份新的(一模一样的)出来。
分类:
- 浅拷贝:浅拷贝指的就是在拷贝对象的时候,只考虑最外层的地址。不考虑对象内部还有对象这种情况
- 深拷贝:一个复杂对象,都要产生一个新的。
浅拷贝
1 拷贝数组
let arr1 = [1,2,3]
let arr2 = [...arr1] // 会得到一个新的数组,跟原数组的数据一模一样
2 拷贝对象
let obj1 = {name:"赵日天",age:200}
let obj2 = {...obj1} // 会得到一个新的镀锌,跟原对象的数据一模一样
注意:
扩展运算符可以直接扩展数组,但是不能直接扩展对象
使用扩展运算符扩展对象的时候,必须使用{}包裹
深拷贝
<script>
let obj1 = {
name:"李杀神",
age:20,
school:{name:"华师一附中",className:"一年级一班"},
hobby:["琴","琪","诗","画"]
}
/**
* 对象的深拷贝
* 1.把被拷贝的对象转成json字符串
* 2.把json字符串再转成js对象
*/
let obj2 = JSON.parse(JSON.stringify(obj1))
//修改obj1
obj1.name = "王诛魔"
obj1.school.name="武汉第一中学"
obj1.hobby[2] = "书"
//通过比较内存地址,判断obj1跟obj2是否是同一个对象
console.log(obj1 == obj2);
console.log(obj1);
console.log(obj2);
</script>
四、函数柯里化
基础概念
概念:将多个参数的函数变成单一参数的函数,嵌套返回所有的参数运算后的最终结果.
简单来说:柯里化就是一个函数变化的过程,指的是将一个函数fn(a,b,c)
变成fn(a)(b)(c)
,
累加的一个案例:
function sum1(a,b,c){
return a + b + c
}
let r1 = sum1(1,2,3)
console.log(r1);
函数柯里化后结果
function sum2(a){
return function(b){
return function(c){
return a+b+c
}
}
}
// let fun1 = sum2(1)
// let fun2 = fun1(2)
// let result = fun2(3)
// console.log(result);
let result = sum2(1)(2)(3)
console.log(result);
总结:函数柯里化并没有引入新的内容,只是在原来函数基础上针对多参数变成单个参数.