0 / 变量晋升解决机制

变量晋升:在以后上下文中(全局/公有/块级),JS代码自上而下执行之前,浏览器会解决一些事件(能够了解为词法解析的一个环节,词法解析肯定是产生在代码执行之前的):

会把以后上下文中所有带var/function关键字的进行提前申明或者定义

var a = 10;

① 申明 declare:var a;

② 定义 defined:a = 10;

带VAR的只提前申明

带FUNCTION的会提前申明+定义

函数名就是变量名,函数是对象数据类型的须要堆内存存储

当初代码根本都用ES6语法的let/const写了,所以var的变量晋升会少很多。申明函数也尽量应用函数表达式来写,这样能够躲避掉间接应用function申明函数的而产生的变量晋升

1 / 练习题目

(1)var的变量晋升
/*EC(G) 全局执行上下文VO(G) 变量对象     var a;  默认值是undefined ----- 代码执行: */console.log(a); //=> undefinedvar a = 12; //=> 创立12,a=12 赋值(申明在变量晋升阶段实现了,浏览器懒得不会做反复的事件)a = 11; //=> 全局变量 a = 11;console.log(a); //=> 11

△ 变量晋升

数据类型:

① 根本数据类型(string/number/boolean/null/undefined/symbol/bigin)

② 对象数据类型(object/functioin)

① 根本数据类型值:间接存储在栈内存中

② 对象数据类型值:因为数据类型比较复杂,存储在堆内存中,把堆内存的16进制地址放到栈内存中与变量关联起来

(2)function 的变量晋升
/*EC(G) 全局执行上下文VO(G) 变量对象       fn = 0x000001堆内存地址[申明+定义] ----- 代码执行: */fn(); //=> 函数执行的后果:输入"hello"function fn(){    var a = 12;    console.log('hello');}

△ 函数

我的项目开发中举荐:函数表达式 var fn = function (){};

这样,在变量晋升阶段只会申明变量,不会赋值

函数表达式
fn(); //=> Uncaught TypeError: fn is not a function// 报错前面的代码就不执行了var fn = function (){    // 函数表达式:在变量晋升阶段只会申明fn,不会赋值了    console.log('hello');};fn();

△ 函数表达式

匿名函数具名化
var fn = function AA(){    console.log('hello');};AA(); //=> Uncaught ReferenceError: AA is not defined

△ 匿名函数具名化

var fn = function AA(){    console.log('hello');    console.log(AA); //=> 输入以后函数体};fn();

△ 匿名函数具名化

把本来作为值的函数表达式的匿名函数“具名化”:

① 这个名字不能在函数体内部拜访,也就是不会呈现在以后上下文中

② 函数执行时,造成公有上下文,会把这个“具名化”的名字作为该上下文中的公有变量(它的值就是这个函数体)来解决

③ 在函数体外部不能批改这个名字的值,除非是从新申明这个变量

(3)不带var的
/*EC(G) 全局执行上下文VO(G) 变量对象-----代码执行: */console.log('ok'); //=> 'ok'//=> 没有写VAR/FUNCTION的,不能在定义前应用console.log(a); //=> Uncaught ReferenceError: a is not defineda=12;console.log(a);

△ 不带var的

(4)带let的
/*EC(G) 全局执行上下文VO(G) 变量对象-----代码执行: */console.log('ok'); //=> 'ok'//=>LET/CONST 没有变量晋升console.log(a); //=> Uncaught ReferenceError: a is not definedlet a = 12;a = 13;console.log(a);

△ 带LET的

(5)在全局上下文的映射

基于VAR/FUNCTION在 <u>全局上下文EC(G)</u> 中申明的变量(全局变量)会“<u>映射</u>”到 <u>GO(window 全局对象)</u> 上一份,作为它的属性;而且一个批改另外一个也会跟着批改

var a = 12;console.log(a); //=> 12 全局变量console.log(window.a); //=> 12 映射到GO上的属性window.a = 11;console.log(a); //=> 11 映射机制:一个批改另一个也会批改

△ 全局上下文的映射机制

2 / 变量晋升的题目

fn(); function fn(){ console.log(1); } fn();function fn(){ console.log(2); }fn();var fn = function(){ console.log(3); }fn();function fn(){ console.log(4); }fn();function fn(){ console.log(5); }fn();

△ 答案是?

/**  * EC(G)全局执行上下文 * VO(G) 变量对象 *     fn = 0x0000001=>log1 *         = 0x0000002=>log2 *       = 0x0000003=>log4 *         = 0x0000004=>log5 *  【var fn; 变量曾经申明过了,不会再反复执行了】 * -------- * 代码执行: */fn(); //=>5function fn(){ console.log(1); }  //=>不再解决,变量晋升阶段搞过了fn(); //=>5function fn(){ console.log(2); }fn(); //=>5var fn = function(){ console.log(3); }  //=>var fn不必在解决了,然而赋值在变量晋升阶段没解决过,此处须要解决  fn=window.fn=>3fn(); //=>3function fn(){ console.log(4); }fn(); //=>3function fn(){ console.log(5); }fn(); //=>3

△ 变量晋升

var foo = 1;function bar() {    if (!foo) {        var foo = 10;    }    console.log(foo);}bar();

△ 答案是?

△ 图1.1_不管判断条件是否成立:var都会变量晋升;function的要简单一些,前面再说~

- end -