1、什么是作用域?什么是自由变量?
1.1、作用域有分为三种
1、函数作用域
2、块级作用域
- if(true){let x = 100};
- console.log(x)
- //会报错,因为用了let,用const也是会报错
3、全局作用域
作用域图示
1.2、自由变量
- 当一个变量在当前作用域使用了,但是没定义
- 会在自己的上一级作用域找
- 最后没找到就是xx is undefined
2、什么是闭包,闭包在哪里被使用?
闭包一般只有两种形式的使用
- 函数作为返回值*(例1)*
- 函数作为参数*(例2)*
//例1
function a(){
let num = 100;
return function b(){
console.log(num)
}
}
let num = 200;
let ok = a()
ok()//100
//第二张补充写法:有注意点
function a(){
let num = 100;
let res = function b(){
console.log(num)
}
num++;
//因为在return之前有了num++所以函数b在找num时会在return之前运算num
return res
}
let num = 200;
let ok = a()
ok()//100
//例2
function a(fn){
let num = 200;
fn()
}
let num = 100;
function fn(){
console.log(num)
}
a(fn)//100
所有自由变量的查找,不是在函数调用的地方找,而是在函数声明的地方向上查找
3、this 有几种赋值情况
this的好文章
3.1、this的指向
this的值是在函数调用的时候确定的
- 普通函数的this指向Window
- 箭头函数的this指向他的上一级
- 定时器那些的this指向window
- 一个构造函数里面的this指向这个实例对象*(例3)*
- 一个class的this指向这个实例对象*(例4)*
//例3
function a(){
this.kk =100
console.log(this)
}
let b = new a()
//{kk: 100}
//例4
class A {
constructor(){
this.a = 99
}
speak(){
console.log(this)
}
}
let b = new A()
b.speak()
//{a:99}
3.2、改变this的指向(3种办法)
- bind()
- call()
- apply()
这三个方法都在Function.prototype上
//...args是吧参数展开
function a(...args){
console.log(...args)
console.log(this)
}
let b = {}
a(1,2)//指向window,
a.call(b,1,2)//call可以改变this的指向为b,但是,参数必须一个一个写
a.apply(b,[1,2])//apply也可以改变this的指向为b,但是,他的参数要写在数组里
a.bind(b,1,2)()//bind的是es5新增的,有兼容性问题,而且,他不会立即执行,只会返回一个函数。这里在后面加了()是让他立即执行
4、作用域相关面试题
1、闭包的使用场景
传入一个函数或者返回一个函数
2、this的问题
this的值是在函数调用的时候确定的
- 普通函数里面的this指向Windows
- 箭头函数里面的this指向上一级
- 用call,apply,bind改变this的指向
- 定时器里面的this指向window
- 构造函数里面的this和class里面的this指向实例对象
3、手写一个bind函数
function a(...args){
console.log(...args)
console.log(this)
}
let b = {}
Function.prototype.bind1 = function(){
//这里的arguments是不是数组,所以这样操作,吧函数的参数放进数组
const arr = Array.prototype.slice.call(arguments)
//取出数组第一项
const first = arr.shift()
//这里的this就是函数a
const self = this
return function(){
//这里的this是window
return self.apply(first,arr)
}
}
a.bind1(b,1,2)()
5、实际开发中闭包的应用
可以隐藏数据,也可以防止数据被污染
手写一个cache的工具
//这样的话只露出两个api,别人就操作不了data了
function cache(){
let data = {}
return {
set(key,value){
data[key] = value
},
get(key){
return data[key]
}
}
}
const h = cache()
h.set('jj',1000)
console.log(h.get('jj'))