mis-lab / Front-End-Question-Discussion

前端基础问题 每日一题
1 stars 0 forks source link

闭包相关 / 手写闭包 / 闭包用途 #20

Open Reaper622 opened 4 years ago

Reaper622 commented 4 years ago

当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。

function fn1() {
  let name = 'reaper'
  function fn2() {
    console.log(name)
  }
    return fn2
}

let fn3 = fn1()
fn3()

根据引用的关系,fn3和fn2都指向的是堆中同一个函数,执行fn3能够输出name 证明fn2成功记住并访问了它所在的词法作用域,并且此时fn3在全局环境下执行,已经在fn2函数运行的词法作用域之外。

闭包的一些应用

for 循环 与 setTimeout 问题(输出多次最后的结果) 可以通过闭包解决「也可以通过let解决」,即每次都在内部生成一个私有作用域

for(var i = 1; i <= 10; i++) {
  (function (j) {
    setTimeout(function () {
      console.log(j)
    }, 1000)
  })(i)
}

闭包的作用:

let singleton = (function () {
    let age = 22
    let speak = function () {
        console.log('speaking')
    }

    return {
        name: 'reaper',
        getAge: function () {
            return age;
        }
    }
    })()

singleton.age //undefined
singleton.getAge() // 22 

或者直接在参数中定义私有变量

function Person(name) {
    this.getName = function () {
        return name;
    }
    this.setName = function (value) {
        name = value;
    }
}

let person = new Person('reaper');
person.name; // undefined 此处无法获取name属性
person.getName(); //'reaper'
person.setName('changed');
person.getName(); // 'changed'