JS//作用域和闭包

在这里插入图片描述

JS——作用域和闭包

1 知识点

1.1 执行上下文

  • 执行上下文的范围:① 一段script(全局); ② 一个函数
  • 在 “全局” or “函数” 范围内,以下变量会提升
    全局:变量定义、函数声明
    函数:变量定义、函数声明、this、arguments
    (PS:注意“函数声明”和“函数表达式”的区别)
    在这里插入图片描述

1.2 this

this 要在执行时才能确认值,定义时无法确认。
————————————————
*作为构造函数执行
*作为对象属性执行
*作为普通函数执行
*call apply bind(区别?
在这里插入图片描述
在这里插入图片描述

1.3 作用域

作用域特点:
*没有块级作用域
*只有函数和全局作用域

// 无块级作用域 
if (true) {
    
    
    var name = 'zhangsan'
}
console.log(name) // zhangsan

// 函数和全局作用域
var a = 100;
function fn() {
    
    
    var a = 200;
    console.log('fn',a)
}
console.log('global', a)  // global 100
fn()  // fn 200

1.4 作用域链

自由变量:当前作用域没有定义的变量
作用域链——当前作用域找不到的变量定义会往父级作用域找

1.5 闭包

如何实现闭包?
*函数作为返回值
*函数作为参数传递
在这里插入图片描述

2 问答

题目:
*说一下对变量提升的理解
*说明 this 几种不同的使用场景
小延伸:call、apply、this的区别?使用场景?
*创建10 个 a 标签,点击的时候弹出来对应的序号
*如何理解作用域
*实际开发中闭包的应用

2.1 说一下对 变量提升 的理解

以下2者在执行时会提前先执行
*变量定义
*函数声明(注意和 函数表达式 的区别)

2.2 说明 this 几种不同的使用场景

this 表示 当前对象,this的指向 是根据 调用的上下文 决定的。
调用的上下文 包括 全局&局部。

  • 全局环境——指向window对象
  • 局部环境——
    ① (普通函数)全局环境直接调用函数,this 指向 window
    ② (对象函数)对象函数调用,哪个函数调用 this 就指向哪个对象
    ③ (构造函数)使用 new 实例化对象,在构造函数中的 this 指向实例化对象
    ④ (call、apply)使用 call 或 apply 改变 this 的指向

小延伸:call、apply、this的区别?使用场景?

  • 区别
    1)相同:
    call、apply、bind可以将某个函数的this指向修改为传入这三个方法中的第一个参数,
    2)不同:
    其中call、apply会立即执行,bind返回的是一个函数,需调用后执行。
    第二个参数是传入要执行的方法中的参数,call、bind是独立传递参数,apply是以数组传递参数的

  • 应用场景
    1、需要改变某个函数的this指向时
    2、当参数较少时可以使用call,参数较多可以使用apply以数组的方式传递
    3、当需要重复调用时,可以使用bind新定义一个方法

    var obj={
    
    
      name:'Li lei',
      intr:function( age, city ){
    
    
        console.log(`我叫${
      
      this.name},我${
      
      age}岁,我来自${
      
      city}`);
      }
    }

    var obj2={
    
    
      name:'Han meimei',
      intr:function( age, city ){
    
    
        console.log(`I'm ${
      
      this.name},I'm ${
      
      age} years old,I'm from ${
      
      city}`);
      }
    }

    obj.intr.call( obj2, 20, '中国' );       //我叫Han meimei,我20岁,我来自中国
    obj.intr.apply( obj2, [ 20, '中国' ] );  //我叫Han meimei,我20岁,我来自中国
    obj.intr.bind( obj2, 20, '中国' )();       //我叫Han meimei,我20岁,我来自中国

2.3 创建10 个 a 标签,点击的时候弹出来对应的序号

var i
for (i=0; i<10; i++) {
    
    
    (function (i) {
    
    
            var a = document.createElement('a')
            a.innerHTML = i + '<br>'
            a.addEventListener('click', function(e) {
    
    
                    e.preventDefault( )
                    alert(i)
            })
            document.body.appendChild(a)
    }) (i)
}

在这里插入图片描述

2.4 如何理解作用域

自由变量:当前作用域没有定义的变量
当前作用域找不到的变量定义会往父级作用域找
作用域链——自由变量向上寻找的过程

2.5 实际开发中闭包的应用

  • isFirstLoad 例子(判断一个值是否第一次出现)
    在这里插入图片描述
  • 闭包的作用
    1、保护对象内的属性不被外部修改。
    函数a中只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。
    2、在内存里维持某些变量。不会再f1调用后被自动清除。
  • 什么是闭包
    能够读取其他函数内部变量的函数,就是闭包。
    闭包是将函数内部和函数外部连接起来的桥梁
  • 闭包缺点
    滥用闭包会造成内存泄露,因为闭包中引用到的包裹函数中定义的变量都永远不会被释放,
    所以我们应该在必要的时候,及时释放这个闭包函数。
  • 解决方法
obj = new Fname();
obj=null;  //清空对象

clearInterval(timer)  //清除计时器

dom.οnclick=null  //指定为null

dom.addEventListener('click',fn,!1)  //绑定方法
dom.removeEventListener('click',fn,!1) //尽量不要用匿名函数绑定,我们解绑事件时也好处理 

dom.attachEvent ('onclick',fn); //绑定
dom.detachEvent('onclick',fn); //解除绑定

猜你喜欢

转载自blog.csdn.net/weixin_37877794/article/details/114197202