您当前的位置: 首页 > 

知其黑、受其白

暂无认证

  • 4浏览

    0关注

    1250博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

JS基础 作用域与闭包

知其黑、受其白 发布时间:2022-01-28 11:26:24 ,浏览量:4

阅读目录
  • 作用域
    • 使用规范
    • let/const 将变量声明在块作用域中
  • 闭包使用
    • 基本示例
      • 使用闭包返回数组区间元素
      • 回调函数中使用闭包
    • 移动动画
    • 闭包排序
    • 闭包问题
      • 内存泄漏
      • this 指向

作用域

全局作用域只有一个,每个函数又都有作用域(环境)。

  • 编译器运行时会将变量定义在所在作用域
  • 使用变量时会从当前作用域开始向上查找变量
  • 作用域就像攀亲亲一样,晚辈总是可以向上辈要些东西
使用规范

作用域链只向上查找,找到全局window即终止,应该尽量不要在全局作用域中添加变量。

在这里插入图片描述

函数被执行后其环境变量将从内存中删除。 下面函数在每次执行后将删除函数内部的 total 变量。

function count() {
  let total = 0;
}
count();

函数每次调用都会创建一个新作用域

let site = 'wgchen';

function a() {
  let hd = 'blog';

  function b() {
    let cms = 'csdn';
    console.log(hd);    // blog
    console.log(site);  // wgchen
  }
  b();
}

a();

如果子函数被使用时父级环境将被保留

function hd() {
  let n = 1;

  return function() {
    let b = 1;

    return function() {
      console.log(++n);
      console.log(++b);
    };

  };

}

let a = hd()();

a(); 
a();

在这里插入图片描述 构造函数也是很好的环境例子,子函数被外部使用父级环境将被保留

function User() {
  let a = 1;
  this.show = function () {
    console.log(a++);
  };
}

let a = new User();

a.show(); //1
a.show(); //2

let b = new User();

b.show(); //1
let/const 将变量声明在块作用域中

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

{
	let a = 9;
}

console.log(a); //ReferenceError: a is not defined

if (true) {
	var i = 1;
}

console.log(i);// 1

也可以通过下面的定时器函数来体验

for (let i = 0; i  {
    console.log(i);
  }, 500);
}

在这里插入图片描述 在 for 循环中使用 let/const 会在每一次迭代中重新生成不同的变量

let arr = [];

for (let i = 0; i  i));
}

console.log(arr[3]()); //3 如果使用var声明将是10
console.log(arr);

在这里插入图片描述 在没有 let/const 的历史中使用以下方式产生作用域

//自行构建闭包
var arr = [];

for (var i = 0; i a);
  })(i);
}

console.log(arr[3]()); //3
闭包使用

闭包指子函数可以访问外部作用域变量的函数特性,即使在子函数作用域外也可以访问。 如果没有闭包那么在处理事件绑定,异步请求时都会变得困难。

  • JS中的所有函数都是闭包
  • 闭包一般在子函数本身作用域以外执行,即延伸作用域
基本示例

前面在讲作用域时已经在使用闭包特性了,下面再次重温一下闭包。

function hd() {
  let name = 'wgchen';
  return function () {
  	return name;
  }
}
let wgchen = hd();
console.log(wgchen()); // wgchen
使用闭包返回数组区间元素
let arr = [3, 2, 4, 1, 5, 6];

function between(a, b) {
  return function(v) {
    return v >= a && v  b[field] ? 1 : -1);
}

console.table(lessons.sort(order("price")));

在这里插入图片描述

闭包问题 内存泄漏

闭包特性中上级作用域会为函数保存数据,从而造成的如下所示的内存泄漏问题

在这里插入图片描述


  博客
  开源代码




  let divs = document.querySelectorAll("div");

  divs.forEach(function(item) {

    item.addEventListener("click", function() {
      console.log(item.getAttribute("desc"));
    });
    
  });


下面通过清除不需要的数据解决内存泄漏问题


  博客
  开源代码




let divs = document.querySelectorAll("div");

divs.forEach(function(item) {

  let desc = item.getAttribute("desc");

  item.addEventListener("click", function() {
    console.log(desc);
  });

  item = null;
  
});


this 指向

this 总是指向调用该函数的对象,即函数在搜索 this 时只会搜索到当前活动对象。

下面是函数因为是在全局环境下调用的,所以 this 指向 window,这不是我们想要的。

let hd = {
  user: "wgchen",
  get: function() {
    return function() {
      console.log(this);
      return this.user;
    };
  }
};

console.log(hd.get()()); //undefined

在这里插入图片描述 使用箭头函数解决这个问题

let hd = {
  user: "wgchen",
  get: function() {
    return () => this.user;
  }
};
console.log(hd.get()()); //wgchen
关注
打赏
1665558895
查看更多评论
立即登录/注册

微信扫码登录

0.0932s