Hi!请登陆

阿里,华为虐哭前端99.99%面试者的“变量提升”问题

2021-3-5 24 3/5

* 回答面试题的套路

1、先说这个点的明确定义,或者是特性;

2、再说具体的应用场景;

3、说说自己的看法、观点;

4、可以稍微举一反三,说说同类特性,或者类似的框架,更好的方案。

????代码实例一:

var x=1;

function func(x,y=function{x=2}){

x=3;

y;

console.log(x); // 2

}

func(5);

console.log(x); // 1

画图分析:( 有图有真相 )

????代码实例二:

var x=1;

function func(x,y=function{x=2}){

var x=3;

y;

console.log(x); // 3

}

func(5);

console.log(x); // 1

????代码实例三:

var x=1;

function func(x,y=function{x=2}){

var x=3;

var y=function{x=4};

y;

console.log(x); // 4

}

func(5);

console.log(x); // 1

解析说明:

是否设置了形参默认值 (如果没有设置,和正常函数执行一样),如果设置了,则有特殊处理:

1)看函数体中是否存在基于 var/let/const 声明的变量。var/let/const 声明的变量和形参一样,则报错(重复声明)。

2)如果有声明变量,则除了形成的这个私有向下文,还会把函数体中的声明单独列为一个独立的私有的私有上下文 (块上下文)

只要符合以下条件:

1)形参赋值默认值

2)函数体中声明过变量 (var/let/const )

特殊,函数体中用function声明的变量必须和形参中的某一个变量名字一致,才会有下述的机制。

就会触发一个全新的“变态机制”。

1)函数执行不仅形成了一个私有的上下文,而且会把函数体当作一个块级私有上下文。

2)如果块级私有上下文中声明的变量,也出现在函数的形参变量中,则也会默认的把私有上下文中的形参变量值赋值给块级上下文文中同名的变量一份。

* 延展:对 ECStack/ EC/ AO/ VO/ GO 理解...

名词解释:

ECStack (Execution Context Stack) 执行环境栈,栈内存;

EC (Execution Context) 执行上下文;

AO (Active Object) 私有对象;

VO (Variable Object) 变量对象;

GO (Global Object) 全局对象;

* ????基本数据类型 ( 例子一分析)

var a = 12;

var b = a;

b = 13;

console.log(a); // 结果: 12

画图分析:( 有图有真相 )

执行过程:(重要)

* 供代码运行环境,栈内存 ECStack (执行环境栈) => 执行上下文 EC => 进栈的过程 => 形成全局执行上下文EC(G) => 变量对象 VO => 词法解析/变量提升 =>代码执行。

扩展内容:

1、供代码运行环境,栈内存 ECStack (执行环境栈)。

2、执行上下文 EC (区分代码执行分为:全局代码(ECG)、函数中代码,私有块中代码)各自区域。

3、全局的执行上下文中有一个VO(GLOBAL)全局变量对象,可以把接下来定义的变量和对应的值储存到这里面。( VO对象是放在栈内存中的 )

* ????引用数据类型 ( 例子二分析)

var a = {n: 12};

var b = a;

b['n'] = 13;

console.log(a.n); //结果: 13

console.log(b.n); //结果: 13

画图分析:( 有图有真相 )

如果是引用数据类型的值:

1)不会直接存在栈内存中,他会开辟一个堆内存(也是计算机内存中分配的一个空间),用来存储自己的键值对,每一个堆内存都有一个16进制的地址。

2)在堆内存中分别存储键值对。

3)把16进制的地址放到栈中,供变量调用。

* ????引用数据类型 ( 例子三分析)

var a = {n: 12};

var b = a;

b = {n: 13};

console.log(a.n); // 结果:12

画图分析:( 有图有真相 )

说明:基本数据类型是按值操作;引用数据类型都是按照地址来操作。

Null 是基本类型;

闭包形成的变量是保存在栈;

如果对前端这方面感兴趣的 可以一起交流 需要相关的资料可以私信我或评论

相关推荐