[JavaScript初级面试]4. JS基础-作用域和闭包
题目
- this的不同使用场景,如何取值
- 手写bind函数
- 闭包在开发中的使用场景,举例说明
- 创建10个
<a>
标签,点击的时候弹出对应的序号
作用域
全局作用域
函数作用域
块级作用域
代码块中{}
自由变量
产生:使用了一个在当前作用域没有定义的变量A
;
一个变量A
在当前作用域没有定义,但被使用了;
这个变量A
就是自由变量
确认自由变量的值,需要在当前作用域向上级作用域,一层一层寻找,直到找到为止;如果到了全局作用域,还没有找到,则报错xx is not defined
最内层的框中a
,a1
,a2
都是自由变量
闭包
有两种情况:
- 函数作为函数参数
- 函数作为函数返回值
核心点:
- 因为函数拥有自己的作用域,使用函数的位置,如果与函数定义的位置不同,并且函数内部还存在自由变量, 则产生闭包(包住一个不属于当前作用域的变量)
- 作用域链形成时,函数作用域的
父级作用域
不是调用函数时所在的作用域
,而是在定义函数时所在的作用域
- 在查找
自由变量
的值时,应该在函数定义
所在的作用域为起始点查找;而不是在函数被调用
的地方所在的作用域查找(沿着函数作用域链查找)
this
this的取值,不是在定义时确定的,而是在调用时确定的。(自由变量的值是在定义时
确定的)
- 构造函数中
创建空对象{},this变量;this变量指向空对象;给this添加属性(构造赋值过程);返回this - class
- bind, apply, call
func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])
func.bind(this) // bind 返回新函数
- 普通函数
- 箭头函数
箭头函数中this永远绑定定义箭头函数时所在作用域的this。很直观
解答
手写bind函数
函数实例的隐式原型就是Function的显式原型
Function.prototype.bind = function(){
// 把参数拆解为数组
const args = Array.prototype.slice.call(arguments)
// 获取this,数组第一项; 在参数数组中剔除this
const t = args.shift()
// this 是 fn1.bind()里的fn1
const self = this
// bind会返回一个函数
return function(){
return self.apply(t, args)
}
}
闭包应用举例
隐藏数据,只提供API
function createCache(){
const data = {} //闭包中的自由变量,被隐藏,外界无法访问
return {
set: function(key, val){
data[key] = val
},
get: function(key){
return data[key]
}
}
}
创建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)
}
方法二:
let i, a
for(i=0; i<10; i++){
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', (e) => {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}
本文来自博客园,作者:Max力出奇迹,转载请注明原文链接:https://www.cnblogs.com/welody/p/15214484.html
如果觉得文章不错,欢迎点击推荐