作用域和闭包 | 青训营笔记

24 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第9天

名词解释

自由变量: 在当前作用域被使用但没被定义的变量

  • 其会向上级作用域一层一层寻找其定义,直至找到为止
function print(fn){
  const a = 200
  fn()
}
const a = 100
function fn(){
  console.log(a)
}
print(fn) // 100

自由变量的查找,是在函数定义的地方找,不是在函数执行的地方

作用域:分为全局作用域、函数作用域、块级作用域

  • var创建的变量会绑在window上,而let不会

闭包

定义:一个函数及这个函数绑定的上下文环境

产生条件:

  • 函数作为参数被传递
  • 函数作为返回值

目的: 隐藏变量/数据,防止污染作用域;可以代码封装成一个闭包形式,用特定的方法管理私有变量和私有方法,将变量的变化封装在安全的环境当中

缺点: 闭包内部资源无法自动释放,会造成一定的内存泄漏。

应用: 高阶函数、回调函数

this

普通函数的this取什么值,是在函数执行时确定的, 不是在函数定义时确定的

普通函数的this指向调用者或全局,箭头函数的this指向外层作用域的this

箭头函数不能改变this指向,只有普通函数可以

const globalThis = this // 全局
const test = {
  that: this, // 全局
  say(){
    return this // test对象
  },
  arrow(){
    setTimeout(()=>{
      console.log(this) // test对象
    })
  },
  normal(){
    setTimeout(function(){
      console.log(this) // 全局
    })
  },
}

> 三者的区别

call(this指向对象,参数1,参数2...)

bind(this指向对象,参数1,参数2...)()

apply(this指向对象,[参数1,参数2...])

手写bind函数

Function.prototype.myBind = function(obj,...rest){
  return ()=>{ // this为调用myBind的函数
    Object.prototype.temp = this
    obj.temp(...rest)
    delete Object.prototype.temp // 删除临时方法
  }
}
// 或者
Function.prototype.myBind = function(obj,...rest){
  return ()=>{ // this为调用myBind的函数
    obj.__proto__.temp = this
    obj.temp(...rest)
    delete obj.__proto__.temp // 删除临时方法
  }
}
fnA.myBind(fnB, args)() // === fnB.fnA(args)

更完整的写法