一、作用域:
是编程语言中,规定变量储存和访问的规则。
js中作用域有三种: 全局作用域、函数作用域、块级作用域(es6新增)。
内层作用域可以访问到外层作用域的变量,以此形成的作用域层级引用关系就是作用域链,如果在全局作用域也没找到一个变量,js引擎会抛出错误。
二、闭包
引用着另一个函数作用域中变量的函数,就叫闭包;通俗理解就像在外太空穿着太空服的宇航员,需要一个生存环境,闭包就是绑定了执行环境的函数。
自由变量访问:访问本作用域外的变量,在函数定义处查找,不是在调用的地方。
关于闭包的经典考题:
(1)将内部函数返回到全局作用域
function create(){
let a = 100;
return function(){
console.log(a)
}
}
let a = 300;
let outterCreate = create();
outterCreate()
(2)将函数作为参数,传入函数内部执行
function myFoo(){
console.log(a)
}
let a = 100;
function foo(fn){
let a = 200;
fn()
}
foo(myFoo)
闭包应用场景:
数据缓存,将缓存数据隐藏在函数内部,向外界提供储存和访问数据的方法。
function myCache(){
let cache = {};
return {
set(key, val){
data[key] = val
},
get(key){
return data[key]
}
}
}
let cacheTool = myCache()
三,this指向
普通函数的this指向是在执行时绑定,箭头函数的this指向取外层作用域的this。
(1)作为普通函数直接调用,函数内部this指向window
(2)作为对象的方法调用,指向该对象
(3)setTimeout的回调函数中,普通函数内部的this指向window,箭头函数定义时绑定外层作用域this。
(4)call、apply和bind,可以直接改变this
(5)class类中,this指向实例对象
(6)dom事件触发函数中,this指向事件dom节点
四、bind函数手写
Function.prototype.myBind = function () {
let thisArg = arguments[0],
originArg = this,
thisArgObj = Object(thisArg),
outterParameters =
arguments.length > 1 ? [...arguments].slice(1) : [],
myBindFuncitonName = symbol("myBind");
thisArgObj[myBindFuncitonName] = this;
return function () {
let innerParameters = [...arguments],
allParameters = [...outterParameters, ...innerParameters];
return thisArgObj[myBindFuncitonName](allParameters);
};
};
let fn2 = fn1.bind(obj, 1);
fn2(2, 3);