JS函数提升和变量提升
1.1什么是函数提升和变量的提升?
JS引擎在运行整个JS代码的过程中,分为俩步。
第一步是读取和解析JS代码,第二部是执行。
在引擎解析JS代码的时候,当解析器遇见变量声明(var 变量名)和函数声明
(function 函数名)的时候,会将这些声明提到各自作用域的最前面。
1.2 作用域
在ES6之前,JS是没有块级作用域的。只有2种作用域:
- 1.全局作用域
- 2.函数作用域
注:在其他语言中,{...}被称为代码块,所形成的作用域被称作块级作用域,如:
if(...){
var a = 1;
}
for(var i = 0;i<5;i++){
var b = 1;
}
console.log(a);
console.log(b);
console.log(i);
如果以上俩例子有块级作用域的话,a,b,i是不能被访问到的,但是
在JS中是可以的(ES6之前),所以没有块级作用域。
2.1 变量提升
2.1.1 声明变量
首先我们声明变量是通过var关键字,如果不用var直接赋值的话会被解析器
当作是全局变量。但是切记,变量的提升只限于用var声明的变量,没通过
var声明的变量将不会被提升。看下边的例子:
var a = 1;
console.log(a);// 1
// 输出的结果为1,没问题,因为代码在执行的时候是按顺序执行的。
// 解析的时候,经过变量提升后的结果如下:
var a;
a = 1;
console.log(a);// 1
console.log(a);// undefined
var a = 1;
// 这次的结果输出为undefined,我们都知道,当一个变量声明了却未赋值的时候就会出现undefined,
// 但是一个变量没有声明的话,就会输出 a is not defined,先看本例经变量提升后的结果:
var a ;
console.log(a);// undefined
a = 1;
// 所以由此可见,变量的提升只会提升变量的声明,而不会提升变量的赋值。
console.log(a);// a is not defined
a = 1;
// 当我们把var去掉的时候,结果变成了 a is not defined,很明显,没有var声明的变量,没有被提升至作用域的最前边,也就是变量提升只是对用var声明的变量而言的。
- 函数的内部也是如此
(function(){
console.log(a);//undefined
var a = 1;
})()
提升结果如下:
(function(){
var a
console.log(a);//undefined
a = 1;
})()
2.1.2 所以暂时我们可以总结一下变量提升:
- 只有用var声明的变量才存在变量提升这一说法
- 变量提升只提升变量的声明,不会提升赋值这一部分;
3.1 函数提升
3.1.1函数的声明
函数的声明有俩种方式,一种为:
function fn(){
}
//另一种为:
var fn = function(){
}
// 首先的我们得知道函数属于引用类型,函数名实际上相当于一个指针,保存的是函数体所在的地址,所以函数也可以通过函数表达式var fn来声明,但是同为函数,他们的提升结果却是不同的。
3.1.2 函数式声明
function fn(){
console.log('hello');
}
fn();// hello
// 结果输出为hello,这个不难理解,代码的顺序执行。函数提升后的结果还是这样。
fn();// hello
function fn() {
console.log('hello');
}
// 执行结果还是hello,因为函数在解析代码的时候,同样,函数的声明被提到了作用域的最前边,如下:
function fn(){
console.log('hello');
}
fn();// hello
// 需要注意的是整个function fn(){...}均为函数的定义(声明)。
var fn = function(){
console.log('hello');
}
fn();//hello
// 用var声明的函数同变量一样,先把定义提升至最前边,如下:
var fn;
fn = function(){
console.log('hello');
}
fn();//hello
fn();//fn is not a function
var fn = function(){
console.log('hello');
}
// 但是将用var声明的函数放在后边就不行了,因为这样声明的函数,提升后是下边这样的:
var fn;
fn();//fn is not a function
fn = function(){
console.log('hello');
}
// 同变量提升一样,提升的只是定义,并没有赋值。
4 综合运用
console.log(a);
function a() { //定义函数
}
console.log(a);
var a = 3; //变量
console.log(a);
运行结果如下:
function a() {
}
function a() {
}
3
console.log(a);
var a = 3;
console.log(a);
function a() {
}
console.log(a);
由此可见
俩次举例中,函数和变量是同名的,在代码未执行到变量赋值语句的时候,console打印出来的均为函数,变量赋值以后,打印的才是刚刚赋的值,所以由综合例子可以得出:
当变量和函数同名时,函数的优先级高!
总结
由以上的例子不难看出变量提升和函数提升的特点,可以总结如下:
- 所有的声明都会提升到各自作用域的最顶上去。
- 只有用var声明的变量才存在变量提升这一说法
- 变量提升只提升变量的声明,不会提升赋值这一部分;
- 同一个变量只会声明一次,其他的会被忽略掉。
- 函数声明的优先级高于变量声明的优先级
- 所有变量的声明,在函数内部第一行代码开始执行的时候就已经完成。
JS函数提升和变量提升的更多相关文章
- JS 函数作用域及变量提升那些事!
虽然看了多次js函数作用域及变量提升的理论知识,但小编也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷) ...
- JS _函数作用域及变量提升
虽然看了多次js函数作用域及变量提升的理论知识,但也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷)&g ...
- js 函数提升和变量提升
总结: 函数提升比变量提升优先级高! 词法分析 词法分析方法: js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 具体步骤如下: 函数在运行 ...
- js函数声明提升与变量提升
变量提升 变量提升: 在指定作用域里,从代码顺序上看是变量先使用后声明,但运行时变量的 “可访问性” 提升到当前作用域的顶部,其值为 undefined ,没有 “可用性”. alert(a); // ...
- 原型模式故事链(4)--JS执行上下文、变量提升、函数声明
上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...
- Javascript中函数提升和变量提升
词法分析 词法分析方法: js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 具体步骤如下: 函数在运行的瞬间,生成一个活动对象(Active ...
- JS中作用域和变量提升(hoisting)的深入理解
作用域(Scoping) javascript作用域之所以迷惑,是因为它程序语法本身长的像C家族的语言.我对作用域的理解是只会对某个范围产生作用,而不会对外产生影响的封闭空间.在这样的一些空间里,外部 ...
- js中的函数提升和变量提升
变量提升和函数提升: 就是将变量声明或者函数全部代码提升到当前作用域(全局作用域或函数作用域)最开始的部分. JavaScript中函数域为最小域范围:for循环.while循环.if语句.switc ...
- js笔记——js里var与变量提升
var是否可以省略 一般情况下,是可以省略var的,但有两点值得注意: 1.var a=1 与 a=1 ,这两条语句一般情况下作用是一样的.但是前者不能用delete删除.不过,绝大多数情况下,这种差 ...
随机推荐
- thymeleaf常用属性
转 作者:ITPSC 出处:http://www.cnblogs.com/hjwublog/ th:action 定义后台控制器路径,类似<form>标签的action属性. 例如: ...
- 前后端分离 之vue-cli 搭建项目mac 系统讲解
前端项目搭建必备技术 webpack nodejs 搭建 vue-cli 的安装 以上技术自行了解安装 一:创建前端项目 采用vue-cli 脚手架 1:终端执行如下命令 vue init webpa ...
- js实现字符串转JSON格式
在浏览器前端实现字符串转JSON格式,有多种方法,总结如下: 方法1. js函数,eval() 语法: var obj = eval ("(" + txt + ")&qu ...
- AI中台——智能聊天机器人平台的架构与应用(分享实录)
内容来源:宜信技术学院第3期技术沙龙-线上直播|AI中台——智能聊天机器人平台 主讲人:宜信科技中心AI中台团队负责人王东 导读:随着“中台”战略的提出,目前宜信中台建设在思想理念及架构设计上都已经取 ...
- PID算法资料【视频+PDF介绍】
最近一直有网友看到我的博客后,加我好友,问我能不能给发一些PID的资料,今天找了一些资料放到百度网盘上,给大家下载: 视频资料 链接:https://pan.baidu.com/s/12_IlLgBI ...
- maven的编译规范
maven的中央仓库上的jar的包名必须小写.否则maven编译不通过. 如:Memcached-Java-Client-3.0.2 的jar包. 目录如下: com.whalin.memcached ...
- H3C模拟器单臂路由配置实例
单臂路由:用802.1Q和子接口实现VLAN间路由 单臂路由利用trunk链路允许多个VLAN的数据帧通过而实现 网络拓扑图: RTA配置: SW1配置: PC1/2配置如图: 但是值得注意的是,在配 ...
- thinkphp3.2集成极光推送
项目中用到了给客户端的推送功能,选用了极光推送,下面演示一下在thinkphp中集成极光推送 1.下载极光推送的php类,可以从笔者的git下载 地址:https://git.oschina.net/ ...
- 1、大型项目的接口自动化实践记录--robotframework环境搭建
因为人力.团队技术问题,选用robotframework来做自动化,首先说下环境搭建 齐涛道长的入门教程非常棒:http://blog.csdn.net/tulituqi/article/detail ...
- js 双向绑定数据
let aaa = []; let bbb = [1,2,3]; let ccc = [0,9,8]; aaa = bbb; //此时aaa与bbb被绑定(aaa指向bbb的指向) ,若使用push则 ...