Javascript核心重点——闭包

前言

闭包在项目和工作中几乎无处不在,同时也作为面试官的高频考点,下面是我在学习闭包中的一些看法与总结,希望能帮助一些小伙伴学习;

什么是闭包

闭包就是能够读取其他函数内部变量的函数,一个函数和它周围作用域引用所形成的组合,就称为闭包;
那么什么是作用域呢?我们先来了解一下

作用域

当我们运行JavaScript代码时就会生成执行上下文,执行上下文决定了代码的作用域,作用域相当于一个封闭的盒子,给代码划清了界限,JavaScript作用域主要分为三种:

  • 全局作用域(在任何位置都能找到,比如window内置对象属相)
  • 函数作用域(只在函数体内才能被访问到,私有作用域)
  • 块作用域 (使用let或const定义,任何一个{}中的语句集合都属于一个块,在里面定义的所有变量外部都是不可见的)
// 全局作用域
console.log(window.Array); //全局作用域,任何位置都可以访问

// 函数作用域
function fn() {
  var a = 1;// 具有函数作用域,无法访问
}
fn()
console.log(a); //Uncaught ReferenceError: a is not defined
//块作用域
{
  var b = 2 ;//不具备块级作用域,可以访问
  const c = 3; // 具备块级作用域,不可以返回
}
console.log(b); // 2
console.log(c); //Uncaught ReferenceError: c is not defined

作用域继承

作用域继承,就如同盒子嵌套,比如一个大盒子作为一个父级作用域,大盒子里面可以放一个小盒子作为子作用域,小盒子可以从大盒子获取东西,但是大盒子不能获取小盒子中的东西,就称为作用域继承

function show() {
 var a = 1;
  return function() {
    console.log(a) // 1
  }
}
show()()

函数执行,形成一个独立作用域,保护里边的私有变量不受外界的干扰,除了保护私有变量外,还可以存储一些内容,这样的模式叫做闭包。

闭包实现

产生一个闭包创建闭包最常见方式,就是在一个函数内部创建另一个函数。

function show() {
 var a = 1;
  return function() {
    console.log(a) // 1
  }
}
show()()

闭包中的this

在闭包中使用this会让代码变得复杂,如果内部函数没有使用箭头函数,则this对象会在运行时绑定到执行函数的上下文。如果在全局函数中被调用,this非严格模式下指向window

window.a = 1
var obj = {
  a: 2,
  show() {
  	return function() {
  	  return this.a;
  	}
  }
}
console.log(obj.show()()) //1

可以通过把this保存在闭包中进行访问this

window.a = 1
var obj = {
  a: 2,
  show() {
    var that = this;
  	return function() {
  	  return that.a
  	}
  }
}
console.log(obj.show()()) //2

注意 this和arguments都是不能直接在内部函数中访问的。如果想访问包含作用域中的arguments对象,同样需要将其保存在闭包的能访问对象中;

但在一些特殊情况下,this的和我们想象的不一样:例如

window.a = 1;
const obj = {
  a: 2,
  show() {
    return this.a
  },
};
const s = obj.show
console.log(s()) //1

该例子执行了一次赋值,调用赋值后的结果,由于赋值表达式的值是函数本身,this值不再与任何对象绑定,返回的就是1

更改this

当然我们可以通过更改this指向来达到我们想要的结果

  • bind() 里面传递的是对应指向的对象
  • call() 里面传递的是指向的对象和参数(会自动调用)
  • apply() 里面传递时指向的对象及参数数组(会自动调用)

闭包特点

  1. 闭包拥有全局变量的不被释放的特点
  2. 局部变量不被外部访问到的特点

闭包优点

  1. 可以让变量长期不被垃圾回收机制回收,不让局部变量使用后立即释放
  2. 避免全局变量的污染,和全局变量不同,闭包中的变量无法被外部使用
  3. 私有成员变量,无法被外部调用,只能直接内部调用

闭包可能造成的问题

  1. 闭包会保留他们包含的作用域,所以比其它函数更加占内存,过度使用闭包会导致内存过度占用,建议仅在十分必要时使用闭包;或者在退出函数之前,将不使用的局部变量全部删除。
  2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值