前端面试知识整理——JS基础作用域和闭包
题目:
- this的不同应用场景,如何取值?
- 手写bind函数
- 实际开发中闭包的应用场景,举例说明
- 创建10个a标签,点击的时候弹出来对应的序号
知识点:
- 作用域和自由变量
- 闭包
- this
- 闭包隐藏数据,只提供API
作用域
- 全局作用域
- 函数作用域
- 块级作用域(ES6新增)let const
闭包
- 作用域应用的特殊情况,有两种表现:
- 函数作为参数被传递
- 函数作为返回值被返回
//函数作为返回值
function create() {
let a = 100
return function () {
console.log(a)
}
}
let fn = create()
let a = 200
fn() //100
//函数作为参数
function print(fn) {
let a = 200
fn()
}
let a = 100
function fn() {
console.log(a)
}
print(fn) //100
闭包:自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方。
this
this的值是在函数执行的时候确定的
- 在class方法中调用
- 箭头函数
function fn1() {
console.log(this)
}
fn1() //window
fn1.call({ x: 100 }) //{ x: 100 }
const fn2 = fn1.bind({ x: 200 }) //{ x: 200 }
fn2()
const zhangsan = {
name: 'zhangsan',
sayHi() {
console.log(this) //zhangsan
},
wait() {
setTimeout(function () {
console.log(this) //window
}, 1000)
},
}
// 箭头函数this值指向上级作用域
const lisi = {
name: 'lisi',
sayHi() {
console.log(this) //lisi
},
wait() {
setTimeout(() => {
console.log(this) // lisi
}, 1000)
},
}
class People {
constructor(name) {
this.name = name
}
sayHi() {
console.log(this)
}
}
const lisi = new People('lisi')
lisi.sayHi() //lisi
手写bind函数
Function.prototype.bind1 = function(){
//将参数转换为数组
const args = Array.prototype.slice.call(arguments)
//获取数组第一项即对象
const t = args.shift()
// fn1.bind(...) 中的 fn1
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.bind1({ x: 100 }, 10, 20, 30)
创建10个a标签,点击的时候弹出来对应的序号
let a
for (let 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)
}