再说这个知识点前,我们先了解下javascript语言的本质。简单来说js是一个脚本语言,是介于标记语言(例html中使用的标签<.. /> 等是一种被动的,被用来浏览\显示的,无行动能力)与编程语言(具有逻辑性和行为能力,这是主动的)之间,特点是不需要编译,可以直接书写,但依赖解释器来负责解释执行。

js代码解析原则

js引擎首先在读取js代码时默认执行2个步骤:
1.解释(通篇扫描所有js代码,然后把所有声明(变量申明、函数声明)提升到对应作用域顶端)
2.执行(执行逻辑操作)


下面还是通过代码实例来看,运行本质吧:

变量提升

例1.
console.log(b)
b=2; //输出 ReferenceError: b is not defined
例2.
console.log(b)
var b=2; //输出 undefined
----------
可以直观的发现例1、例2区别就是因为一个没有用var申明变量,导致不同的输出。
js引擎在解释的时候,例2相当于:var b;console.log(b);//由于未赋值 输出undefined b=2;
而针对例1而言,不会改变代码顺序,遇到b时,b还没被申明,只能输出b is not defined。

函数提升

首先要知道函数定义有两种方式的,一种是函数定义表达式,一种是函数声明语句。
//函数定义表达式
var f = function (){
...
};
//函数声明语句
function f(){ ...
}
重点:函数提升针对是函数声明语句而言,其次变量提升只提升变量名而函数提升会提升整个函数体。
----------
例1.
f();
function f(){console.log("fffff");
}
//输出 fffff
例2.
f();
var f=function(){console.log("fffff");
}
//输出 TypeError f is not a function
----------
为什么例1正确执行呢,其原因就是函数提升,在js引擎解释的时,相当于:
function f(){console.log("fffff");
}
f();//正确执行函数,输出fffff
而例2则相当于:
var f;
console.log(f); //undefined
f();//f不是一个函数 f is not a function
f=function(){console.log("fffff");
}
----------
再来看看例3
console.log(f);
var f=10;
console.log(f);
function f(){console.log('fff');}
console.log(f);
输出:
ƒ f(){console.log('fff');}
10
10
这个例子就考察了一个优先级问题,函数提升会在变量提升的上面,在js引擎解释的时候就相当于:
function f(){console.log('fff');}var f;console.log(f);//ƒ f(){console.log('fff');
f=10
console.log(f);// 10
console.log(f);// 10

作用域

es5中只有全局作用域和函数作用域,es6新增了块级作用域。
var v = "hello";
if(true){console.log(v);var v = "world";
}
//输出 hello 说明es5是没有块级作用域
es6对块级作用域的支持
let n = 5;
if (true) {let n = 10;}
console.log(n); // 5
----------
es5中:
var v = "hello";
(function(){console.log(v);var v= "world";
})()
//输出 undefined
原因函数作用域变量v遮盖了上层作用域变量v,再加上变量提升,相当于:
var v = "hello";
(function(){var v;console.log(v);// undefinedv = "world";
})()
----------
es6允许块级作用域的任意嵌套。外层作用域无法读取内层作用域的变量。内层作用域可以定义外层作用域的同名变量。
{{{let insane = 'Hello World'}console.log(insane); //ReferenceError: insane is not defined
}};
{{let insane = 'Hello World';{let insane = 'Hello World';}
}};
----------
es6也规定,函数本身的作用域,在其所在的块级作用域之内。
function f() { console.log('I am outside!'); }
(function () {if(false) {// 重复声明一次函数ffunction f() { console.log('I am inside!'); }}f();
}())
上面代码在es5中运行,输出 I am inside!,但是在es6中运行,会输出I am outside!。这是因为es5存在函数提升,不管会不会进入 if代码块,函数声明都会提升到当前作用域的顶部,得到执行;而es6支持块级作用域,不管会不会进入if代码块作用域,其内部声明的函数皆不会影响到作用域的外部。
----------
块级作用域外部,无法调用块级作用域内部定义的函数。
if(1==2){let a = 'secret';function f() {return a;}
}
f()//TypeError: f is not a function
----------
块级作用域内let和const命令所声明的变量,只在命令所在的代码块内有效。
if(true){let a = 10;var b = 1;
}
console.log(a)//ReferenceError: a is not defined.
console.log(b)// 1

js 变量提升 函数提升 作用域相关推荐

  1. js 变量、函数提升

    js 变量.函数提升 先简单理解下作用域的概念,方便对变量与函数提升的概念的理解 function foo() {var x = 1;if (x) {var x = 2;}console.log(x) ...

  2. 关于JavaScript的变量和函数提升

    第一种理解方式:let和const不能被使用,直到他们被声明 对于var定义的变量,解析器会提升其到作用域顶部. // Outputs: undefined console.log(x);var x ...

  3. js 变量、函数重复声明和变量提升浅析

    第一阶段:看山是山,看水是水 先从简单的例子开始 // 示例1 var a = 1 console.log(a) // 1 var a = 2 console.log(a) // 2 通过两个var声 ...

  4. javascript变量提升/函数提升

    首先 javascript 是一种弱类型.动态的.解释型的脚本语言. 弱类型:类型检查不严格,偏向于容忍隐式类型转换. 强类型:类型检查严格,偏向于不容忍隐式类型转换. 动态类型:运行的时候执行类型检 ...

  5. JS 总结之函数、作用域链

    在 JavaScript 中,函数实际上是一个对象. ? 声明 JavaScript 用 function 关键字来声明一个函数: function fn () {} 复制代码 变体:函数表达式: v ...

  6. PHP基础班初学心得:脑洞实验-JS变量存储函数与return的一些问题

    本人刚参加PHP基础班培训第一天,由于之前毫无基础,分享的心得可能不规范,方法也许也"旁门左道",不能保证质量,只作自己总结学习,也希望能帮助到同样是初学者的朋友们,共同进步. 在 ...

  7. 深入理解js的变量提升和函数提升

    一.变量提升 在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分.上个简历的例子如: ...

  8. Js 变量声明提升和函数声明提升

    Js代码分为两个阶段:编译阶段和执行阶段 Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容 包括变量声明(var a)和函数声明(function a(){ ...

  9. JS函数简单的底层原理 -变量重复声明无效,隐式申明,变量提升,函数提升,以及堆栈内存的变化

    JS函数简单的底层原理 (个人理解): 1. 已经使用var申明且赋值,若再次申明,则第二次申明(不赋值)无效. 2.在同一个作用域下,只要是发生了同名,且变量完成赋值,后者会覆盖前者.存在两个相同的 ...

最新文章

  1. k8s service type_k8s重器之Service
  2. VC2005与IE8的冲突解决
  3. Lucene+Tika 文件索引的创建与搜索
  4. BZOJ 4212: 神牛的养成计划
  5. parquet文件格式——本质上是将多个rows作为一个chunk,同一个chunk里每一个单独的column使用列存储格式,这样获取某一row数据时候不需要跨机器获取...
  6. d3.js 封装一个方法更新柱状图,运用数据模板
  7. STM32 HAL库--串口的DMA(发送、接收)和esp8266 wifi模组发送和接收封装函数
  8. Scala操作外部数据
  9. 3des java ecb_PHP 3DES加密 与JAVA通用 加密模式:ECB
  10. SAP License管理
  11. 13_短信发送器_问题说明
  12. 在服务器上打包部署springboot+vue的项目(一)启动tomcat后打开浏览器点击登录无反应 页面空白问题
  13. 虚拟机克隆Linux操作系统后解决MAC地址冲突
  14. [jQuery] jQuery的属性拷贝(extend)的实现原理是什么,如何实现深拷贝?
  15. Python2.7.16安装(Ubuntu16.04)
  16. NDoc使用简要手册的补充
  17. gzdeflate函数_PHP中的gzcompress、gzdeflate、gzencode函数详解_php实例
  18. 洛谷P3048 [USACO12FEB]牛的IDCow IDs
  19. EF ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象...
  20. [转载]ASPNET MVC表格呈现利器:MvcContrib.UI.Grid

热门文章

  1. Knife4j文件上传不显示上传选择文本域
  2. 安装transmission实现下载功能
  3. 如何寻找免费好用的的内盘期货跟单软件
  4. 【Python学习】买苹果简单案例
  5. 微信小程序拍照上传图片
  6. HDU 3068 最长回文 manacher算法
  7. authenticator_如何将Microsoft Authenticator移至新手机
  8. 数据结构实验1《基于线性表的图书管理系统》
  9. 宋鸿兵:新货币战争打响 美元体系迟早崩溃
  10. TestStand用户界面语言本地化