2020年6月1日 星期一
Being a kid is a wonderful thing. Second it is over, you start wishing you could have it back again.
戊戌年, 丁巳月 甲子日,儿童节,首先祝愿忙着生活的大朋友,童心不泯,祝愿没有长大的小朋友喜乐无忧,致我们逝去的童年!!🌹🌹🌹六一儿童节快乐。
今天呢主要深入学习了闭包和this的指向问题给大家分享一下学习心得。
闭包
我们知道在前端开发中闭包是一个很重要的知识点,就算是在面试中呢也是问道的高频面试题,之前我对‘闭包’的理解呢就是:函数嵌套函数,在函数外部可以访问函数内部的变量;对闭包呢也是用的比较少,就算是自己写过闭包也不清楚;所以呢今天也是想深入的学习一下闭包。
闭包的定义:
闭包是一个函数与作用域环境(即** 词法环境 **)形成的闭包
闭包的理解:
广义的闭包:
1.他是一个函数
2.这个函数能访问到函数外部的状态(也称函数外部的变量)
狭义的闭包:
函数嵌套函数,并且内部函数通过return返回到外部,外部可以访问内部函数的变量
<script>
// 自由变量: 自由变量:就是在函数外部定义的,并且在函数内部可以访问到的变量就叫自由变量
var index = 1;
// 闭包的实际应用举例
function getIndex()
{
console.log(index);
}
getIndex();
</script>
闭包的特点:
1、当函数在定义时的词法作用域以外调用时,闭包使得函数可以继续访问其定义时的词法作用域
2、闭包中自由变量长期驻留内存,长期驻留内存中的变量如果处理不当,会导致内存泄露,不用的
话要将闭包置为null
可以隔离作用域,模拟块级作用域
3、闭包可以阻止内存空间的回收
4、只要使用了回调函数,实际上就在使用闭包
闭包的实际应用举例
- 作用域链:通过在当前函数内部查找要访问的变量,如果有则访问,没有则向上一级查找此变量,上级有则访问之,没有再再往上上一级查找,以此类推,直到找到全部window下有没有,有则访问,没有些报错。
是否有点像原型链的查找呢????非常像
闭包应用举例: 计数器 改变页面字号 定时器累加
/** 计数器 */
//功能:递增,递减,获取递增或递减之后的值
var Counter=function() {
//私有变量
var num=0;
//私有函数
var changeValue=function(n) {
return num+=n;
}
return {
//增
increment:function() {
changeValue(1)
},
//减
decrement:function() {
changeValue(-1)
},
//获取值
getValue:function() {
return num;
}
}
}
/** 改变页面字 */
function setSize(size) {
return function() {
document.body.style.fontSize=size+'px'
}
}
var size12=setSize(12);
var size40=setSize(40)
var size50=setSize(50);
/** 定时器累加 */
//要求每隔1秒打印1,2,3,.....10
//setTimeout是异步执行的,异步队列
/*
for(var i=1;i<=10;i++) {
(function(j) {
setTimeout(function() {
console.log('i=j的值:',j)
},2000*j)
})(i)
}
console.log('最后打印:',i)
*/
for(let i=1;i<=10;i++) {
setTimeout(function() {
console.log('i的值:',i)
},1000*i)
}
this指向
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,
实际上this的最终指向的是那个调用它的对象
难道这句话真的正确吗?????
网上是这么说得但实际上还是不准确得;
我们接下来讨论一下这个话题
在js中直接输出this
console.log(this); // Window
这个this是在全局中环境中得
在DOM中的this
<button class="btn">改变当前按钮背景色</button>
<script>
var btn=document.querySelector('.btn')
btn.onclick=function() {
console.log(this===btn)
this.style.background='#f00'
}
</script>
定时器中的this
<script>
var value='React'
var obj={
value:'vuejs',
getValue:function() {
// var _this=this;
setTimeout(()=>{
console.log(this)
console.log(this.value)
},2000)
}
}
obj.getValue()
</script>
JS中的this--在对象内
<script>
var value='React'
var obj={
value:'vuejs',
getValue:function() {
//this
//console.log('this===obj:',this===obj)
var that=this;
function getValue2() {
console.log('obj内部this:',this.value)
}
getValue2()
return this.value;
}
}
obj.getValue()
</script>
JS中的this--在构造函数内
<script>
function Fn(name='张三',age=0) {
this.name=name
this.age=age
//指向实现化的对象,分别:this===f1 //true
console.log('this:',this)
}
var f1=new Fn('薰悟空',20)
var f2=new Fn('小猪猪',18)
console.log('f1:',f1.name)
console.log('f1:',f1.age)
console.log('f2:',f2.name)
console.log('f3:',f2.age)
</script>
this和作用域不一样,作用域是声明的时候就定下来了,this是在调用的时候才确定下来
1、默认绑定
function test() {
console.log(this) //this指向window
}
(自己执行自己)fn() (默认情况下的隐式执行) this指向window
(严格模式下指向undefined,不指向)window
2、隐式绑定,谁调用指向谁
const obj = {
name:'joy',
getName(){
console.log(this); //this指向obj
console.log(this.name); //joy
}
};
obj.getName();
当然也可以通过call,apply,bind来改变this指向问题
现在也不会去考虑this问题,因为ES6出了一个箭头函数,调用前this是什么函数里面的this就是什么,常用的就是箭头函数
3、显示执行:
(函数的方法执行)
function fn(){
console.log(this.a)
}
var a = 10;
var obj = {
a : 20,
b : fn,
}
obj.b();// 返回值20;this指向的是fn引用的地址
//fn作为一个函数本身是一个对象,在内存中所占据的空间依然是一个地址,
//在用obj.b(),执行这个函数时执行的是一个引用,函数本身就是一个引用,
//当把fn复制给obj中的b时,复制的是一个引用地址=》浅拷贝,当我早使用obj.b()
//执行函数,用obj找到那个引用位置,这个时候,函数引用的位置被obj所找到,被obj
//执行,那么此时函数里的this就指向找到我位置的那个对象,也就是fn被哪个对象所
//执行,此时,fn就指向谁
先天高手:谁执行了this所在的函数,this就是谁
后天高手:就是通过call,apply,bind改变了this的指向