慕课网前端面试06--js基础-作用域和闭包

一、题目

  • this的不同应用场景,如何取值?
  • 手写bind函数?
  • 实际开发中闭包的应用场景,举例说明?

二、知识点

2.1作用域和自由变量

作用域
  • 全局作用域
  • 函数作用域
  • 块级作用域(ES6新增)

在这里插入图片描述

// ES6块级作用域
if (true) {
	let x = 100
}
console.log(x)  // 会报错,因为访问不到x
自由变量
  • 一个变量在当前作用域没有定义,但被使用了
  • 向上级作用域,一层一层依次寻找,直至找到为止
  • 如果到全局作用域都没找到,则报错 xx is not defined

2.2 闭包

  • 作用域应用的特殊情况,有两种表现:
  • 函数作为参数被传递
  • 函数作为返回值被返回

函数作为返回值被返回:

// 函数作为返回值
function create() {
  let a = 100
  return function () {
    // function()在这里被定义,此时a为100
    // 打印的a的值为被定义时的值
    console.log(a)
  }
}
let fn = create()
let a = 200
fn()  // 100

函数作为参数被传递:

// 函数作为参数被传递
function print(fn) {
  let a=200
  fn()
}

let a=100
function fn() {
  // 函数fn被定义时a的值是100
  // 所以打印的a的值为100
  console.log(a);
}

print(fn) // 100

2.3 this

  • 作为普通函数
  • 使用call apply bind
  • 作为对象方法被调用
  • 在class方法中调用
  • 箭头函数
    this取什么值是在函数执行时确定的,不是在函数定义的时候确定的。
function fn1(){
	console.log(this)
}
fn1() // window
fn1.call({ x : 100})  // {x : 100}
const fn2=fn1.bind({x : 200})
fn2() // {x : 200}

bind返回新的函数去执行,bind直接调用执行。

const zhangsan={
  name:'张三',
  sayHi(){ 
    // this 即当前对象
    console.log(this)
  },
  wait(){
    setTimeout(function(){
      // this===window
      console.log(this);
    })
  }
}

class中,this指向当前对象。

const zhangsan = {
  name: '张三',
  sayHi() {
    // this 即当前对象
    console.log(this)
  },
  waitAgain() {
    setTimeout(() => {
      // this 即当前对象
      console.log(this);
    })
  }
}

箭头函数中的this取它上级作用域的值。

class People {
  constructor(name) {
    this.name = name
    this.age = 20
  }
  sayHi() {
    console.log(this);
  }
}
const zhangsan = new People('张三');
zhangsan.sayHi() // zhangsan对象

在这里插入图片描述
class中的this指向这个类的实例对象。

// 创建10个`<a>`标签,点击的时候弹出来对应的序号
let i, a
for (i = 0; i < 10; i++) {
  a = document.createElement('a')
  a.innerHTML = i + '<br>'
  a.addEventListener('click', function (e) {
    e.preventDefault()
    alert(i)
  })
  document.body.appendChild(a)
}

点击任意<a>标签,alert出来的都是10,原因是因为i是全局变量。
在这里插入图片描述
修改代码:

// 创建10个`<a>`标签,点击的时候弹出来对应的序号
let a
for (let i = 0; i < 10; i++) {
  // 每一个i都有一个块级作用域
  a = document.createElement('a')
  a.innerHTML = i + '<br>'
  a.addEventListener('click', function (e) {
    e.preventDefault()
    alert(i)
  })
  document.body.appendChild(a)
}

在这里插入图片描述

2.4手写bind函数

bind函数具有:

  • 传入的this
  • 传入的参数
  • 返回值
// 模拟bind
Function.prototype.bind1 = function () {
  // 将参数拆解为数组
  const args = Array.prototype.slice.call(arguments)

  // 获取this(数组第一项)
  const t = args.shift()

  // fn1.bind(...)中的fn1,
  // this指向bind函数的调用者,赋值为self变量
  const self = this

  // 返回一个函数
  return function () {
    return self.apply(t, args)
  }
}

function fn1(a, b, c) {
  console.log('this', this)
  console.log(a, b, c)
  return 'this is fn1'
}

const fn2 = fn1.bind({ x: 100 }, 10, 20, 30)
const res = fn2()
console.log(res)

打印结果:
在这里插入图片描述

小结

  • 作用域和自由变量
  • 闭包:两种常见方式&自由变量查找规则
  • this
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值