Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

day2 #2

Open
elegantYU opened this issue Mar 25, 2021 · 3 comments
Open

day2 #2

elegantYU opened this issue Mar 25, 2021 · 3 comments

Comments

@elegantYU
Copy link
Owner

知识点

编程题

算法

@elegantYU
Copy link
Owner Author

elegantYU commented Mar 26, 2021

闭包老题目了

for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i)
  }, 1000)
}
// 如何输出 0 1 2 
  1. 闭包解法
for (var i = 0; i < 3; i++) {
  (function (idx) {
     setTimeout(function() {
      console.log(idx)
    }, 1000)
   })(i)
}

好说明下为什么,闭包直接的解释是能访问外部变量的函数,但是为什么函数能访问外部变量呢?都是输出i,上面全是3,下面会按序输出?
这里要说下作用域链的概念了,函数在创建的时候,会把自身变量对象和上层上下文、上层的上层直至全局上下文形成一条作用域链,加入函数中。这样setTimeout中的函数在查找i变量时,按照题目里的写法,作用域链如下

Scope: [AO, globalContext.VO]

自身变量对象找不到后,会去全局作用域找,此时全局作用域的i为3,所以每次都会输出3
若使用闭包的解法,则作用域链如下

Scope: [AO, 匿名函数Context.VO, globalContext.VO]

输出的idx是AO中的形参变量,变量由匿名函数作用域传入,此时匿名函数Context.VO分别有 0,1,2的值。
所以闭包的原理主要是作用域链可保存上下文,利用这点可实现逐个输出。

  1. let解法
for (let i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i)
  }, 1000)
}

var换let就可以了?why
因为let会创建一个作用域,导致函数的作用域链如下

Scope: [AO, for循环Context.VO, globalContext.VO]

原理也和上面一样。

@elegantYU
Copy link
Owner Author

this指向老题目

var value = 1

var foo = function () {
  console.log(this.value)
}
var obj = {
    value: 2,
    foo,
    bar: () => {
        console.log(this.value)
    }
}

输出 foo() obj.foo() obj.bar()是否一样,为什么

简单来说,js普通函数里的this,是动态的,会根据调用环境有不同指向。
其底层是通过Reference解析出当前环境的base value,在判断base value是对象还是全局环境。
箭头函数不会创建this,它只会从自身作用域链的上层继承this。

var age = 12

var obj = {
  age: 20,
  foo: function () {
    this.age = 30
    return () => {
       console.log(this.age)
    }
  }
}

obj.foo()() // 30

@elegantYU
Copy link
Owner Author

节流函数 throttle

function throttle(fn, delay) {
  var timer 
  return function () {
    var that = this
    var args = arguments
    timer = setTimeout(() => {
      fn.apply(that, args)
      timer = null
    }, delay)
  }
}

在delay时间内,无论触发多少次事件,只会按照间隔执行一次

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant