深入理解 JS
作用域
静态作用域能够预测代码在执行过程中如何查找标识符
全局作用域
var a = 'a'
function fun()
{
console.log(a);
}
fun()
函数作用域
var a = 'a';
function fun()
{
a = 'b';
console.log(a);
}
fun()
块级作用域
{
const a = 'a';
console.log(1,a);
}
console.log(2,a);
var
提升地址
var company = undefined;
console.log(company);
company = "Bytedance";
函数
提升函数变量
showName()
function showName(){
console.log('zq'); //zq
}
以下方法会报错 func is not a function ,var提升变量func并赋值为undefined
func();
var func = showName;
function showName(){
console.log('zq')
}
总结:
- var 有变量提升
- let、const没有变量提升,提前访问会报错
- function 函数可以先调用再定义
- 赋值给变量的函数无法提前调用
执行上下文
所有通过var定义的全局变量和函数都会成为window对象的属性和方法。上下文在其所有代码都执行完毕后会被销毁,包括定义 在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)。
上下文中的代码在执行的时候,会创建变量对象的一个作用域链(scope chain)。这个作用域链决定 了各级上下文中的代码在访问变量和函数时的顺序。
每个上下文都可以 到上一级上下文中去搜索变量和函数,但任何上下文都不能到下一级上下文中去搜索。
闭包
闭包指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
简单理解:闭包 = 内层函数 + 引用的外层函数变量
满足闭包的 4 个条件:
- 有函数嵌套
- 内部函数引用外部作用域的变量参数
- 返回值是函数
- 创建一个对象函数,让其长期驻留
实现函数没调用一次变量减一
function fa(){
let a = 10;
function fb(){
a--;
console.log(a);
}
return fb;
}
var fm = fa();
fm = null;
this
-
普通函数的
this指向windowfunction showName(){ console.log(this); //window } -
对象调用指向对象。先赋值再调用,看调用的地方
const name = 11; const obj = { name:'zq', showName(){ console.log(this.name); //'zq' } } obj.showName();若想改变
this指向则使用apply或call或bindconst obj1 = { name:'zq', showName(){ console.log(this.name);//'zq' } } const obj1 = { name:'bytedance' } obj.showName.apply(obj1);//'bytedance'const personObj = { name:'zhangqi', dep:'边缘云', showName(){ console.log(this.name); } } personObj.showName(); //'zhangqi' const getName = personObj.showName getName()//undefined -
创建临时对象;将
this指向临时对象;执行构造函数;返回临时对象function ShowName(){ this.name = "zhangqi"; } const getName = new ShowName() console.log(getName);//ShowName{name:'zhangqi'}
宏任务、微任务
执行过程:
-
同步代码(JS执行栈/回调栈)
-
微任务的异步代码(JS引擎)
- process.nextTick(node)
- Promise.then() catch()
- Async/Await
- Object.observe
-
宏任务的异步代码(宿主环境)
- script(代码块)
- setTimeout/setInterval 定时器
- setImmedia 定时器