JS面试思考:4作用域闭包执行上下文
从题目入手、思考,寻找知识点最后解答
- 说一下对变量提升的理解
- 说明this几种不同的使用场景
- 创建10个
<a>标签,点击时弹出对应的序号 - 如何理解作用域
- 实际开发中闭包的应用
知识点
执行上下文
js
console.log(a) // undefined
var a = 100
fn('zhangsan') // 'zhangsan' 20
function fn(name) {
age = 20
console.log(name, age)
var age
}范围:一段<script>或者一个函数 全局:变量定义、函数声明 函数:变量定义、函数声明、this、arguments
this
要在执行时才能确认值,定义时无法确认
js
var a = {
name: 'A',
fn: function() {
console.log(this.name)
}
}
a.fn() // 'A' this === a
a.fn.call({name: 'B'}) // this === {name: 'B'}
var fn1 = a.fn
fn1() // undefined this === window- 作为构造函数执行
- 作为普通属性执行
- 作为普通函数执行
- call apply bind
- es6箭头函数
作用域
es5及以前是没有块级作用域的(所以我们一般用IIFE来模拟)
作用域链
js
/* 例1 */
var a = 100
function fn() {
var b = 200
// 当前作用域没有定义的变量,即“自由变量”
console.log(a)
console.log(b)
}
fn()
/* 例2 */
var a = 100
function f1() {
function f2() {
var c = 300
console.log(a) // a是自由变量
console.log(b) // b是自由变量
console.log(c)
}
f2()
}
f1()作用域链就是 … (我理解的)这层作用域找不到的向父级找,父级找不到继续往上直到顶层作用域(window或global)
闭包
闭包的使用场景:
- 函数作为返回值
- 函数作为参数传递
js
/* 1 函数作为返回值 */
function f1() {
var a = 100
// 返回一个函数,函数作为返回值
return function() {
console.log(a) // 自由变量,父作用域寻找
}
}
// f1得到一个函数
var f2 = f1()
var a = 200
f1() // 100
/* 2 函数作为参数传递 */
function Fn1() {
var a = 100
return function() {
console.log(a) // 自由变量,父作用域寻找
}
}
var fn1 = Fn1()
function Fn2(fn) {
var a = 200
fn()
}
Fn2(f1) // 100解题
说一下对变量提升的理解 - 见上文
说明this几种不同的使用场景 - 见上文
创建10个
<a>标签,点击时弹出对应的序号
js
for (var i = 0; i < 10; i++) {
(function(i) {
var el = document.createElement('a');
el.innerHTML = i + '<br>';
el.addEventListener('click', function(e) {
e.preventDefault()
console.log(i)
})
document.body.appendChild(el);
})(i)
}- 如何理解作用域
自由变量、作用域链(自由变量查找机制)、闭包的使用场景
- 实际开发中闭包的应用
js
// 闭包实际应用中主要用于封装变量,收敛权限
function isFirstLoad() {
// _作为私有变量、方法的前缀,这算是一个约定
var _list = []
return function(id) {
if (_list.indexOf(id) >= 0) {
return false
} else {
_list.push(id)
return true
}
}
}
// 使用
var firstLoad = isFirstLoad()
firstLoad(10) // true
firstLoad(10) // false
firstLoad(20) // true