作用域与闭包

一、作用域

全局作用域只有一个,每个函数有都有作用域(环境)。es6中新增了块级作用域。

在这里插入图片描述
函数被执行后其环境变量将从内存中删除,函数每次调用都会创建一个新的作用域。

如果子函数被使用时,父级环境将被保留。 ----闭包

使用let/const 可以将变量声明在块级作用域中,(放在新环境中,而不是全局中)

//块级作用域
使用let/const在块级作用域中定义变量,在全局中找不到该变量
{
	let a=1;
	const b=2;
}

二、闭包

闭包是函数运行的一种机制,函数执行会形成一个私有作用域(上下文),如果私有作用域的某些内容被私有作用域以外的一些事物(如:变量/事件绑定等)所占用,则当前私有作用域不能被出栈释放。

创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量。

闭包的优点:

  1. 保护私有上下文中的“私有变量”和外界互不影响
  2. 私有上下文中的“私有变量”和“值”都会被保存起来,可以供其下级上下文中使用

闭包的缺点:

  • 如果使用闭包,会导致栈内存太大,页面渲染变慢,性能收到影响,所以在项目中“合理使用闭包”。

闭包的使用

1、闭包的基本使用

//如果子函数被调用,则父函数不会被释放
    function fn(){
      let n=1;
      return function(){
        console.log(n++);
      }
    }
    let method=fn();
    method();
    method();
    method();
//手动释放
    method=null;

2、对数组对象进行排序:保存变量对象的属性名prop

    let phone = [
      {
        title: "手机1",
        click: 100,
        price: 3200
      },
      {
        title: "手机2",
        click: 110,
        price: 1200
      },
      {
        title: "手机3",
        click: 2100,
        price: 2000
      }
    ];

    function myOrder(prop, bool) {
      if(bool===undefined) bool=true;
      if(bool) return (a, b) => a[prop] - b[prop];
      else return (a, b) => b[prop] - a[prop];
    }
    phone.sort(myOrder('price',false));
    console.log(phone);

3、对列表元素绑定事件:保存变量li的索引i

for (var i = 0; i < liList.length; i++) {
	liList[i].onclick = (function (i) {
		return function () {
			console.log(`当前点击按钮的索引:${i}`)
		}
	})(i)
}

4、闭包实现模块化:保护私有变量

jQuery使用的就是闭包实现模块化

function(window){
	const jQuery={...};
	window.jQuery=window.$=jQuery;
}(window)

cmd和commonjs的实现

    const {getPhone,setPhone} = (function () {
      var phone = '1232131223'
      function getPhone() {
        return '我的电话号码:' + phone
      }
      function setPhone(phoneNum){
        phone = phoneNum
      }
      // 暴露到外部调用的方法
      return {
        getPhone,
        setPhone
      }
    })()
    setPhone('rrofo')
    console.log(getPhone())

三、惰性调用

利用闭包保存值的特性只完成一次判断,后续调用封装的函数不用再次判断来提高函数执行效率。

例如:
window.getComputedStyle(元素) 获取当前元素经过浏览器计算的样式,在ie6到8中,不兼容,需要使用 元素.currentStyle 来获取,可以利用闭包保存值的特性完成只要一次判断,后续调用封装的函数不用再次判断来提高函数执行效率。

function getStyle(el, attr) {
	// 判断当前属性是不是属于此对象
	if ('getComputedStyle' in window) {
		getStyle = function (el, attr) {
			return window.getComputedStyle(el)[attr]
		}
	} else {
		getStyle = function (el, attr) {
			return el.currentStyle[attr]
		}
	}
	return getStyle(el, attr)
}
getStyle (document.getElementById('box'), 'color')

四、函数柯里化

柯里化是一个预处理思想,使用闭包形成一个不被释放的上下文,把一些信息存储起来,以后基于作用域链,访问到事先存储的信息,然后进行先关处理,我们把这种模式称为柯里化函数。

//预处理变量n,子作用域能够访问到该变量
    function fn(n=10){
      return function(...args){
        return args.reduce((value,item) => value+item,n);
      }
    }

    let sum=fn();
    console.log(sum(1,2,3));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值