JS执行顺序-函数声明提升、匿名函数、函数表达式
大方向上: JS 是按照 代码块 进行 编译、执行 的。
学习至:
- 1.变量声明提升
- 2.新唐的博客
- 3.js中匿名函数的创建与调用方法分析
- 4.前端圣经 - 《高程三》
- 5.深入理解变量声明提升和函数声明提升
因为没有好好地分类。可能会比较杂。为了系统地学习,先了解几个概念。
一. <script> 区分的代码块。
JS是按照代码块 编译 和 执行的。代码块间 相互独立,但是 变量和方法 共享。
<script>
alert('代码块一');
</script>
<script>
alert('代码块二');
</script>
<script>
var a = 3;
</script>
<script>
console.log(a); // 3
</script>
二. 关于函数(声明式函数、赋值型函数、匿名函数、自执行函数)
声明式函数 和 赋值型函数
声明函数与赋值函数的区别在于: 在 JS 的预编译期间,声明式函数会被先提取出来,然后才按照顺序执行 JS代码。
- 声明式同学:
A(); // 'A '
function A() {
console.log('A');
}
- 赋值型选手:
B(); // error, B is not a function
var B = function() {
console.log('B');
}
什么是匿名函数?
没有名字的函数就是匿名函数(突然有点想笑)。
function() {} // 匿名函数
什么是自执行函数
(function() {
console.log(3);
})();
需要注意,下面这样的写法会报错
function() {
console.log(3);
}();
原因解析如下:
function {}()其实这是一个函数声明。
- JS运行的时候,会对函数声明进行预编译,然后在执行其他语句。
- 也就是说
function(){}先被预编译了。然后JS看见了()。JS一脸懵逼,这不得报错吗。
- 也就是说
- 而匿名函数实际上是一个语句,正常执行。
还需要知道的是,自执行函数的标识可以是
!function(){}()
(function(){})()
~function(){}()
void function(){}()
自执行函数是可以带参数的,格式是这样的!
function(num){
console.log(num);
}(3); // 3
三. 预编译期 和 执行期
事实上,JS的解析分为两个阶段:预编译 和 执行期。
预编译期间:对本
代码块中的所有 声明变量 和 函数进行处理(类似于 C语言的编译) ,但需要注意,1.此时处理函数的只是声明式函数2.变量也只是进行了声明但是没有进行初始化和赋值编译期间:从上到下 编译 代码块。
接下来,我们分别结合上面的 第一点(代码块) 和 第二点(函数) 食用一下。
f(); // 我是函数声明2
function f() {
console.log('我是函数声明1');
}
function f() {
console.log('我是函数声明2');
}
结论1:都是函数声明的情况下,后来居上的规则 没有变。
f(); // 我是函数声明
function f() {
console.log('我是函数声明');
}
var f = function() {
console.log('我是赋值型函数');
}
结论2:函数声明 提前于 赋值函数。
console.log(a);
var a; // undefined
console.log(b); // 程序直接报错,不往下进行
结论3:变量声明 处于 预编译阶段。证明了我们上面的正确性。
函数下方声明了 a,被提前(提升)了。函数下方没有声明 b(之前也没有),直接报错。
<script>
f(); // f is not defined.
</script>
<script>
function f(){};
</script>
结论4:JS引擎是按照代码块的顺序来执行的。!!!对于还未加载的代码,是没有办法进行预处理的。这也是编译核心所在。
console.log(f); // Function
function f() {
console.log(1);
}
var f = 3;
结论5:函数声明提升优先级大于 变量声明,函数声明覆盖 变量声明
<script>
console.log(a);
</script>
<script>
console.log(3);
</script>
结论6:代码块之间如果报错,其他的代码块如果正确依旧能够正确执行。
四. 开战!!! 五是总结和整理,不想看题目的可以直接跳至 五。
代码一:
f();
var scope = 'out';
function f() {
console.log(scope); // undefined
var scope = 'in';
console.log(scope); // 'in'
}
- 变量覆盖,后面定义声明的会覆盖前面的。
- 函数内部:先进行变量声明。
实际运行过程:
var scope = 'out';
function f() {
var scope; // 覆盖了外部的。
console.log(scope);
scope = 'in';
console.log(scope);
}
f();
代码二:
var getName = function(){
console.log(2);
}
function getName (){
console.log(1);
}
getName();
答案是 2. 这题看懂了前面的话很容易:
- 函数声明被放在了预编译阶段。
- 后来的会覆盖前面的。
实际运行过程
function getName (){
console.log(1);
}
var getName = function(){
console.log(2);
}
getName(); // 2
代码三:
getName(); // 1
function getName() {
console.log(1);
}
var getName = function() {
console.log(2);
}
依旧很容易,不解释。变量赋值来得太慢,不像龙卷风。
五. 总结和整理
JS的执行顺序如下:
- 1.读入第一个代码块
- 2.做语法分析,有错则报语法错误,并跳转到 5
- 3.对var变量和function做 预编译(永远不会报错,因为只解析正确的)
- 4.执行代码块,有错则报错
- 5.如果还有下一个代码块,则读入下一个代码端,重复 2
- 6.结束
六. 想了想,是不是没有提到变量提升?这个其实是 JS的一个 乌龙。
ES之前,JS没有变量作用域。只有 函数作用域 和 全局作用域。
{
var a = 3; // 我们以为它只是个局域变量
}
console.log(a); // 3 -- 没想到它在全局中打印出来了,(手动笑哭)
使用了 ES6 的 let 之后, {} 内即为一个 变量作用域。
{
let a = 3;
}
console.log(a); // error
变量提升 完。
complete.
JS执行顺序-函数声明提升、匿名函数、函数表达式的更多相关文章
- 原型模式故事链(4)--JS执行上下文、变量提升、函数声明
上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...
- Js 变量声明提升和函数声明提升
Js代码分为两个阶段:编译阶段和执行阶段 Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容 包括变量声明(var a)和函数声明(function a(){ ...
- js函数声明提升与变量提升
变量提升 变量提升: 在指定作用域里,从代码顺序上看是变量先使用后声明,但运行时变量的 “可访问性” 提升到当前作用域的顶部,其值为 undefined ,没有 “可用性”. alert(a); // ...
- JS变量声明提升和函数声明提升
JS代码在执行的时候会先找出执行代码中定义的变量和函数,对其进行声明. 例1:console.log(a); var a = 4; 此时输出undefined.a变量在执行console.log(a) ...
- 变量声明提升 Vs. 函数声明提升
1. 变量声明提升 先看以下代码: 1)var in_window = "a" in window; console.log(in_window); 2)var in_window ...
- JavaScript函数声明提升
首先,JavaScript中函数有两种创建方式,即函数声明.函数表达式两种. 1.函数声明. function boo(){ console.log(123); } boo() 2.函数表达式. va ...
- 你不知道的JavaScript--Item6 var预解析与函数声明提升(hoist )
1.var 变量预编译 JavaScript 的语法和 C .Java.C# 类似,统称为 C 类语法.有过 C 或 Java 编程经验的同学应该对"先声明.后使用"的规则很熟悉, ...
- JavaScript 函数声明与函数表达式的区别 函数声明提升(function declaration hoisting)
解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁.解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问).至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真的被 ...
- 浅谈JS变量声明和函数声明提升
先来两个问题 很多时候,在直觉上,我们都会认为JS代码在执行时都是自上而下一行一行执行的,但是实际上,有一种情况会导致这个假设是错误的. a = 2; var a; console.log(a); 按 ...
随机推荐
- django的render的说明
return render(request,"homesite.html",locals()) homesite.html页面中的所有内容都可以被渲染,不论是标签还是js代码,包括 ...
- Hash函数和消息摘要算法
一.Hash函数 哈希函数就是能将任意长度的数据映射为固定长度的数据的函数.哈希函数返回的值被叫做哈希值.哈希码.散列,或者直接叫做哈希. 二.消息摘要 将长度不固定的消息(message)作为输 ...
- jquery-messager-消息提示
一.页面引入 jquery.js 下载地址问度娘 jquery-message.js 下载地址:jquery-message.js 二.页面使用 //ajax轮询检查新的订单 function che ...
- Oracle pl/sql 显示游标和隐式游标
显示游标 一.定义语法: CURSOR <游标名> IS <SELECT 语句> [FOR UPDATE | FOR UPDATE ...
- php二维数组排序方法(array_multisort,usort)
一维数组排序可以使用asort.ksort等一些方法进程排序,相对来说比较简单.二维数组的排序怎么实现呢?使用array_multisort和usort可以实现 例如像下面的数组: $users = ...
- [poj1410]Intersection
题目大意:求线段与实心矩形是否相交. 解题关键:转化为线段与线段相交的判断. #include<cstdio> #include<cstring> #include<al ...
- 【总结整理】WebGIS学习-thinkGIS(三):关于影像金字塔、瓦片行列号、分辨率resolution
http://www.thinkgis.cn/topic/541a5206da8db186fd0673ba 1.前言 在上一节中我们知道了屏幕上一像素等于实际中多少单位长度(米或经纬度)的换算方法,而 ...
- PCL—关键点检测(Harris)低层次点云处理
博客转载自:http://www.cnblogs.com/ironstark/p/5064848.html 除去NARF这种和特征检测联系比较紧密的方法外,一般来说特征检测都会对曲率变化比较剧烈的点更 ...
- aspose ppt转图片
如果直接转图片,会很模糊采用先将ppt转pdf,在通过pdf转图片,这样出来的结果就非常清晰 var pptFileName = "公司网络及计算机使用与要求.pptx"; Pre ...
- Windows Live Writer 使用指南
一.简介 Windows Live Writer 是一个强大的离线博客编辑工具,通过它可以离线编辑内容丰富的博文,除了自身强大的编辑功能之外,还提供了接口,让其它开发人员通过插件提供工具自身没有提供的 ...