变量提升机制

变量提升,即程序在自上而下执行之前,在本作用域内,由varfunction声明的变量或函数,会被提升到最顶端,之后才开始按代码自上而下的顺序执行。变量的默认初始值为undefined,而函数则是函数声明的字符串。如下所示:

console.log(a);
console.log(fn);

var a = 10;
 function fn() {
    console.log(fn);
 }

结果如下:
undefined
ƒ fn() {
   console.log(fn);
}

示例一:

console.log(a);
console.log(b);

var a = b = 10;  // 相当于var a=10;b=10;

结果如下:
undefined
Uncaught ReferenceError: b is not defined

这里的 b 并不是用 var 声明的,所以没有被提升。

示例二:

console.log(a);
console.log(b);

var a , b = 10;

结果如下:
undefined
undefined

这里的 b 相当于使用var声明

示例三:

console.log(a);
console.log(b);

let a , b = 10;

结果如下:
Uncaught ReferenceError: a is not defined

let const class都不会有变量提升

示例四:

console.log(a);
console.log(b);

let a = b = 10;

结果如下:
Uncaught ReferenceError: a is not defined

由于let没有变量提升,所以报错--未被定义

示例五:

console.log(a);
console.log(b);

var a = 10;
b = 10;

结果如下:
undefined
Uncaught ReferenceError: b is not defined

这里的b没有使用var声明,所以没有变量提升

示例六:

console.log(a);
console.log(window.b);

var a = 10;
b = 10;

结果如下:
undefined
undefined

这里b并没有使用 var声明,但是由于调用的是window.b,相当于调用一个对象的属性,属性不存在,返回undefined,因此不会报错。

示例七:

console.log(a, b); // 变量提升,默认值为 undefined

var a = 10, b = 10;
function fn() {
    console.log(a, b); // 由于下一行的 a 使用 var 声明,变量提升,默认值 undefined
                       // b 不是 var 声明的,不存在变量提升,
                       // 所以根据作用域链,向上查找,即为全局声明的 b
    var a = b = 11;
    console.log(a, b);
 }
fn();
console.log(a, b); // 在函数中改变了全局变量 b 的值

结果如下:
undefined undefined
undefined 10
11 11
10 11

示例八:

function fn(a) {
   n = a;
   console.log(a);
   console.log(n);
   console.log('a' in window);
   console.log('n' in window);
}
fn(11);
// console.log(a); // 报错 Uncaught ReferenceError: a is not defined
console.log(n);

结果如下:
11
11
false
true
11

在函数体内,不使用var声明的变量(参数是局部变量),会被视为全局变量,假如全局作用域中不存在此变量,则在函数执行时被创建。

示例九:

console.log(fn); // typeof fn ===> undefined
fn();
var fn = () => console.log(11); // typeof fn ===> function

结果如下:
undefined
Uncaught TypeError: fn is not a function

示例中是给使用var声明的变量赋值一个匿名函数,所以,fn作为变量,默认值是undefined,在赋值之前执行fn(),相当于执行一个变量,所以产生类型错误。

通过之前,和之后的 typeof可以看出,赋值之前,把fn作为一个变量,之后把fn作为一个函数。

示例十:

console.log(a);
if (false) {
  var a = 10;
}
console.log(a);

结果如下:
undefined
undefined

由于var没有块级作用域,所以声明的a是全局变量,变量提升默认值是undefined,由于if条件为false,所以不执行赋值操作,最后的值还是undefined。假如if条件为true,则会执行赋值操作。

示例十一:

console.log(f);
// typeof f ===> undefined
if (f()) {
   function f() {
       return true;
    }
}

结果如下:
undefined
Uncaught TypeError: f is not a function

一般情况下,function声明的函数,可以在声明之前调用执行如:

f();
function f(){return true};

然而,在if语句块中(低版本浏览器除外),使用function声明的函数和var声明变量一样,都只是先声明,然后变量提升,只有执行到的时候才会赋值,在if条件中的f现在还是undefined,因此,调用f()会出现语法错误。

示例十二:

console.log(f);

if (true) {
    console.log(f);

    function f() {
        return true;
    }
}

结果如下:
undefined
ƒ f() {
  return true;
}

注意:if条件体内的第一句中f并不是一个变量,假如是var声明的变量,值是undefined,但它是function声明的函数,所以值是函数声明的字符串。

示例十三:

    console.log(a);
    var a = 1
    function a() {
      console.log(1);
    }
    console.log(a);

    // a(); // 这里 a=1 调用变量报错
    function a() {
      console.log(2);
    }
    // a(); // 这里 a=2 调用变量报错
    var a = 2;
    function a() {
      console.log(3);
    }
    var a = () => { }; // 这里的 a 同样只是变量赋值
    var a;
    function a() {
      console.log(4);
    }
    console.log(a);

结果如下:
ƒ a() {
  console.log(4);
}
1
() => { }

在程序执行之前,先要考虑变量提升(除了在函数体内,先形参赋值,再变量提升),开始时使用var声明的变量提升,默认值是undefined,之后再使用var声明同名的变量,并不会有变量提升,只是相当于赋值操作;而function声明同名的函数,每次都会变量提升并覆盖初始值,即最后一次的function声明为默认值。之后,程序开始自上而下执行,越过函数体部分,只有函数再调用时才会进入函数体。

假如没有对a重新赋值,不管在哪里调用都是对最后一次声明的函数的调用。在调用之前,如果对a重新赋值(不包括赋值一个匿名函数),a成为了一个变量,调用变量即会报错。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容