-
2018-08-06 18:16:42
1. 函数声明提升
func() function func () { }
上例不会报错,正是因为 ‘函数声明提升’,即将函数声明提升(整体)到作用域顶部(注意是函数声明,不包括函数表达式),实际提升后结果同下:
// 函数声明提升 function func () { } func()
2. 变量声明提升(只有var声明的变量才有变量提升,let、const无;变量赋值无提升)
1. console.log(num) var num = 10 2. console.log(func) var func = function () { }
上两例均会打印出 'undefined',变量声明提升会将变量声明提升到作用域顶部,但只会提升声明部分,不会提升赋值部分,实际提升后结果如下:
1. var num console.log(num) num = 10 2. var func console.log(func) func = function () { }
3. 进阶举例(两者优先顺序、局部与全局变量):
①
var func = 10 console.log(func && typeof(func)) function func () { } ----- console.log(func && typeof(func)) function func () { } var func = 10
上两例将分别输出 ‘number’、'function',原因是 函数声明提升优先于变量提升,函数声明会被变量赋值影响,但不会被变量声明影响,实际提升后结果如下:
function func () { } var func = 10 console.log(func && typeof(func)) ----- function func () { } var func console.log(func && typeof(func)) func = 10
②
num = 10 function func () { window.num = 5 console.log(num) var num console.log(window.num) } func()
上例将会分别打印出 'undefined'、'5',第一处为局部变量,第二处为全局变量,实际提升后结果如下:
function func () { var num window.num = 5 console.log(num) console.log(window.num) } var num num = 10 func()
欢迎关注、点赞
更多相关内容 -
JavaScript中Hoisting详解 (变量提升与函数声明提升)
2021-01-19 18:47:19本文主要给大家介绍了关于JavaScript中Hoisting(变量提升与函数声明提升)的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 如何将 函数声明 / 变量 “移动” 到作用域的顶部。 术语 ... -
js函数声明提升
2021-11-15 21:49:05函数声明提升 //定义函数 function demo(num){ console.log(111,num) //111 f num(){ console.log(1111) } //定义变量 var num = 20; console.log(222,num) ///222 20 //声明一个函数 function num(){ ...函数声明提升
- 1.变量只提升声明,不提升赋值
- 2.函数表达式不提升赋值
- 3.函数声明提升
- 顺序:形参 变量 函数
//定义函数 function demo(num){ console.log(111,num) //111 f num(){ console.log(1111) } //定义变量 var num = 20; console.log(222,num) ///222 20 //声明一个函数 function num(){ console.log(111) } console.log(333,num) ///333 20 } //执行函数 ickt(10);
首先,形参提升(形成AO属性),变量提升(提升声明,不提升赋值,第一个打印后被变量赋值,所以第二个第三个都打印20),函数提升(num被覆盖,所以第一个打印的是个函数)
-
跟我学习javascript的var预解析与函数声明提升
2020-10-23 07:49:39跟我学习javascript的var预解析与函数声明提升,小编对var预解析与函数声明提升知识点也不甚了解,和大家一起学习本篇文章。 -
浅谈JavaScript中变量和函数声明的提升
2020-12-09 12:44:36函数声明提升高于变量声明 //同时声明变量a和函数a var a; function a() {} alert(typeof a); //显示的是"function",初步证明function的优先级高于var。 //先声明函数后声明变量,证明上边的例子不是... -
JavaScript 预编译:函数声明提升,变量声明提升
2018-06-21 20:45:17我们都知道 js 中函数声明会提升,变量声明会提升(赋值不提升)。那为什么会这样呢,这就涉及到 js 预编译。 js 运行三部曲 语法解析——检查有无语法错误; 预编译; 解释运行——将 js 翻译成计算机识别的...我们都知道 js 中函数声明会提升,变量声明会提升(赋值不提升)。那为什么会这样呢,这就涉及到 js 预编译。
js 运行三部曲
- 语法解析——检查有无语法错误;
- 预编译;
- 解释运行——将 js 翻译成计算机识别的语言(0 和 1组成的),翻译一行执行一行。
预编译什么时候发生
- 预编译不仅发生在函数体内,还发生在全局;
- 预编译发生在函数或代码执行前一刻。
说预编译之前有两点需要我们记住
-
暗示全局变量(imply golbal):任何变量未经声明(没有用 var 关键字声明)就赋值,此变量就为全局变量所有;
a = 123; // a 是全局变量 var a = b = 123; // b 是全局变量。赋值一定是从右向左的
-
一切声明的全局变量都是 window 的属性(window 就是全局)。
预编译的步骤
函数:
- 创建 AO( Activation Object ) 对象(执行期上下文);
- 找形参和变量声明,将形参和变量名作为 AO 对象的属性名,值为 undefined(有重复的名称只写一个即可);
- 将形参与实参值统一(用实参的值替换 undefined);
- 在函数体中找函数声明,将函数名添加到 AO 对象的属性中,值为函数体(如属性名重复,则覆盖前面的)。
最后得到一个 AO 对象,代码运行时按照 AO 对象来。例如:
function fn(a) { console.log(a); var a = 123; console.log(a); function a() {} console.log(a); var b = function() {} console.log(b); function d() {} console.log(d); } fn(1);
以上代码按照前面的四个步骤:
1、创建 AO 对象 AO = {} 2、找形参和变量声明,将形参和变量名作为 AO 对象的属性名,值为 undefined AO = { a: undefined, b: undefined } 3、将形参与实参值统一 AO = { a: 1, b: undefined } 4、在函数体中找函数声明,将函数名添加到 AO 对象的属性中,值为函数体。 AO = { a: function a() {}, b: undefined, d: function d() {} } 预编译完成后得到的 AO 对象
预编译完成后运行代码:
function fn(a) { console.log(a); // function a() {} var a = 123; console.log(a); // 123 这时的 AO 对象变成 AO = { a: 123, b: undefined, d: function d() {} } function a() {} console.log(a); // 123 var b = function() {} // 这时的 AO 对象变成 AO = { a: 123, b: function() {}, d: function d() {} } console.log(b); // function() {} function d() {} console.log(d); // function d() {} } fn(1);
全局:
- 创建 GO( Global Object ) 对象;
- 找变量声明;
- 找函数声明。
全局变量也是一样的:
console.log(a); var a = 123; function a() {} console.log(a); 第一步:创建 GO( Global Object ) 对象 GO = {} 第二步:找变量声明 GO = { a: undefined, } 第三步:找函数声明 GO = { a: function a() {}, } 预编译完成后得到的 GO 对象 函数运行结果: console.log(a); // function a() {} var a = 123; function a() {} console.log(a); // 123
再看几个例子
console.log(test); function test(test) { console.log(test); var test = 321; console.log(test); function test() {} } test(1); var test = 123; console.log(test);
按照以上的步骤得到的两个对象分别是:
GO = { test: function test(test) { console.log(test); var test = 321; console.log(test); function test() {} } } AO = { test: function test() {} }
执行结果:
function test(test) { console.log(test); var test = 321; console.log(test); function test() {} } function test() {} 321 123
global = 100; function fn4() { console.log(global); global = 200; console.log(global); var global = 300; } fn4(); var global;
两个对象:
GO = { global: 100 } AO = { global: undefined }
执行结果:
undefined 200
function fn5() { console.log(b); if(a) { var b = 100; } c = 234; console.log(c); } var a; fn5(); a = 10; console.log(c);
两个对象:
GO = { a: undefined, fn5: function fn5() { console.log(b); if(a) { var b = 100; } c = 234; console.log(c); }, c: undefined // 变量 c 未经声明(没有用 var 关键字声明)就赋值,此变量就为全局变量所有,所以添加到 GO 对象中 } AO = { b: undefined }
对于函数体内变量的值(如此例中的 c),AO对象中有就用AO对象中的值,AO对象中没有就用GO对象中的值
运行结果:
undefined 234 234
总结
综上,所以有我们都知道的:
- 函数声明提升
- 变量声明提升(赋值不提升)
-
深入理解变量声明提升和函数声明提升
2016-03-05 20:51:02变量声明提升 1、变量定义 可以使用var定义变量,变量如果没有赋值,那变量的初始值为undefined。 2、变量作用域 变量作用域指变量起作用的范围。变量分为全局变量和局部变量。全局变量在全局都拥有定义;而...变量声明提升
1、变量定义
可以使用var定义变量,变量如果没有赋值,那变量的初始值为
undefined
。2、变量作用域
变量作用域指变量起作用的范围。变量分为全局变量和局部变量。全局变量在全局都拥有定义;而局部变量只能在函数内有效。
在函数体内,同名的局部变量或者参数的优先级会高于全局变量。也就是说,如果函数内存在和全局变量同名的局部变量或者参数,那么全局变量将会被局部变量覆盖。
所有不使用var定义的变量都视为全局变量3、函数作用域和声明提前
JavaScript的函数作用是指在函数内声明的所有变量在函数体内始终是有定义的,也就是说变量在声明之前已经可用,所有这特性称为
声明提前(hoisting)
,即JavaScript函数里的所有声明(只是声明,但不涉及赋值)都被提前到函数体的顶部,而变量赋值操作留在原来的位置。如下面例子:
注释:声明提前
是在JavaScript引擎的预编译时进行,是在代码开始运行之前。var scope = 'global'; function f(){ console.log(scope); var scope = 'local'; console.log(scope); }
由于函数内声明提升,所以上面的代码实际上是这样的
var scope = 'global'; function f(){ var scope; //变量声明提升到函数顶部 console.log(scope); scope = 'local'; //变量初始化依然保留在原来的位置 console.log(scope); }
经过这样变形之后,答案就就非常明显了。由于scope在第一个console.log(scope)语句之前就已经定义了,但是并没有赋值,因此此时scope的指是
undefined
.第二个console.log(scope)语句之前,scope已经完成赋值为’local’,所以输出的结果是local
。函数声明提升
1、函数的两种创建方式
- 函数声明
- 函数表达式
函数声明语法
f('superman'); function f(name){ console.log(name); }
运行上面的程序,控制台能打印出
supemran
。
函数表达式语法f('superman'); var f= function(name){ console.log(name); }
运行上面的代码,会报错
Uncaught ReferenceError: f is not defined(…)
,错误信息显示说f没有被定义。
为什么同样的代码,函数声明和函数表达式存在着差异呢?
这是因为,函数声明有一个非常重要的特征:函数声明提升
,函数声明语句将会被提升到外部脚本或者外部函数作用域的顶部(是不是跟变量提升非常类似)。正是因为这个特征,所以可以把函数声明放在调用它的语句后面。如下面例子,最终的输出结果应该是什么?:var getName = function(){ console.log(2); } function getName (){ console.log(1); } getName();
可能会有人觉得最后输出的结果是
1
。让我们来分析一下,这个例子涉及到了变量声明提升
和函数声明提升
。正如前面说到的函数声明提升,函数声明function getName(){}
的声明会被提前到顶部。而函数表达式var getName = function(){}
则表现出变量声明提升。因此在这种情况下,getName也是一个变量,因此这个变量的声明也将提升到底部,而变量的赋值依然保留在原来的位置。需要注意的是,函数优先,虽然函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量。因此上面的函数可以转换成下面的样子:function getName(){ //函数声明提升到顶部 console.log(1); } var getName; //变量声明提升 getName = function(){ //变量赋值依然保留在原来的位置 console.log(2); } getName(); // 最终输出:2
所以最终的输出结果是:
2
。在原来的例子中,函数声明虽然是在函数表达式后面,但由于函数声明提升到顶部,因此后面getName又被函数表达式的赋值操作给覆盖了,所以输出2
。 -
深入理解JS中的函数声明提升和变量声明提升
2018-07-22 12:15:12简介:本文先从函数的声明方式说起,介绍不同函数的声明方式在函数声明提升上的不同。然后根据具体的例子比较变量声明提升和函数声明提升的不同。 第一部分:函数的声明方式 函数声明有三种方式:函数声明,函数... -
Javascript 变量声明提升和函数声明提升
2022-03-26 21:13:421、变量声明提升 在C++、java中必须先声明变量才能在后面使用这个变量,但是在JS中,无论在该作用域中的哪个位置声明变量,都会被提升到顶部,但是变量定义不会跟着提升; console.log(person1)//undefined变量... -
JS的变量提升和函数声明提升顺序以及覆盖规则
2019-12-10 00:41:12《你不知道的Javascript》里面说是函数声明提升优先 代码1 foo(); //输出1 var foo = function(){ console.log(2) } function foo(){ console.log(1) } 会被解释为这样?为什么undefined的变量foo不会导致foo... -
JS中的变量声明提升与函数声明提升优先级
2018-09-06 23:01:42今天在群里看到了一道题,如下。问输出什么? var c = 1; function c(c) { console.log(c); var c = 2;...看到的第一眼,第一想法就是这题考察的是变量提升,唔,应该是输出undefined。...函数声明---->变量声... -
js函数声明提升优先级与变量声明提升优先级的关系
2019-08-11 18:15:19js中函数声明先提升还是变量先提升 根据官方书籍《你不知道的javascript》(上卷)中写道: “函数会首先被提升,然后才是变量”。 例子: console.log(foo); function foo(){ console.log("函数声明"); } ... -
函数声明的提升和变量声明的提升
2018-07-23 20:45:02函数的执行顺序(声明式函数、赋值型函数、匿名函数、自执行函数) ... //函数声明 a();//a function a() { console.log("a"); } //函数赋值 b();//Uncaught TypeError: b is not a f... -
全面了解函数声明与函数表达式、变量提升
2020-12-11 19:08:53// 函数声明 var foo = function(){}; // 函数表达式 不同之处 1、函数表达式后面加括号可以直接执行 2、函数声明会提前预解析 预解析 让我们先看一个例子: foo(); // 函数声明 foo_later(); // foo_later is not... -
js中是函数声明先提升还是变量先提升
2022-01-27 22:06:03console.log(typeof a) // ...函数声明提升先于变量声明提升 只提升了声明,没有提升赋值 function a() {} var a//a重复声明而不予理会,所以a的类型在输出时依旧为function console.log(typeof a) a = 1 ... -
函数声明与函数表达式的提升问题
2019-03-29 16:59:51函数a是函数声明,执行的是函数提升,实际效果是 function a() { console.log(1); } a(); 即会把整个函数声明提到作用域顶端 而函数b是函数表达式,执行的是变量提升,实际效果是 var b; b(); b = function() {} ... -
js中函数声明提升理解
2017-05-18 16:04:47js函数的定义两种方式:函数声明和函数表达式 函数声明 函数调用可以在函数声明之前 test(); function test(){ alert("this is a test funciton"); } 这是因为js在代码执行之前会先加载函数声明 函数表达式 test()... -
[JavaScript,ES6]函数声明提升和预解析的总结和试验
2017-12-09 18:42:314. 在块中定义的函数声明或函数表达式,只会提升其声明部分,也就是只提升变量名,不提升函数的定义哦。不要在块中声明函数! 5.如果在提升的时候发生重命名了怎么办? 首先还是都会提升(函数声明整个“被提前”,... -
相关面试题:函数、变量声明提升,类是否存在声明提升?
2022-03-23 09:18:28函数、变量声明提升,类是否存在声明提升? -
浅析函数声明和函数表达式——函数声明的声明提前
2020-11-23 14:55:53前两天班级聚会,除了吃喝玩乐就是睡觉扯淡,...注:有的地方也叫函数声明提升。翻译的不一样,意思一样,大家理解就行。理解万岁! 在聊函数声明的声明提前之前,有必要介绍下函数定义的几种方法,大部分小伙伴们应该 -
JavaScript中变量提升和函数提升的详解
2020-11-19 23:17:09通常JS引擎会在正式执行之前先进行一次预编译,在这个过程中,首先将变量声明及函数声明提升至当前作用域的顶端,然后进行接下来的处理。(注:当前流行的JS引擎大都对源码进行了编译,由于引擎的不同,编译形式也会... -
为什么 javascript 函数声明会提升 而 函数表达式不会
2018-04-26 15:28:36Js代码分为两个阶段:编译阶段和执行阶段我们习惯将var a = 2;看作一个声明,而实际上JavaScript引擎并不这么...可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程... -
js在if语句中的函数声明会不会得到函数提升?
2021-03-16 18:06:54如果程序中遇见if语句的情况,且程序内恰好包含函数声明的情况(一般我们不会写出这样的代码,但是容易出现在面试题中) 首先看mdn的解释 一个被函数声明创建的函数是一个 Function 对象,具有 Function 对象的所有... -
js中函数声明与函数表达式
2020-12-08 21:03:43目前为止,我们一直没有对函数声明和函数表达式加以区别。... 以上代码完全可以正确执行,因为在代码开始执行之前,解析器就已经通过一个名为函数声明提升(function declaration hoisting)的过程 -
javascript函数声明与函数表达式的区别:函数声明提升
2015-12-01 14:30:102、上述两种方式除了定义的语法不同之外,最主要的区别是函数声明具有【函数声明提升】的特点,将函数声明提升到作用域顶端,意思是在执行代码之前会先读取函数声明,也就是说可以把函数声明放在函数调用的后面。...