Q首先一道题

if(false){
var a = 1;
}
console.log(a); //undefined //我以为输出ReferenceError: aa is not defined
//但是实际输出undefined
//因为js没有块级作用域,所以最后代码就成了这样 var a;
if(false){
a = 1;
}
console.log(a);

上面是一个引子 js没有块级作用域

《1》  let和const声明的变量只在let命令所在的代码块内有效

在代码块外引用let和const声明的变量 无效 

// ReferenceError: i is not defined

《2》const let命令改变了语法行为,它所声明的变量一定要在声明后使用

原因是存在暂死区

if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError let tmp; // TDZ结束
console.log(tmp); // undefined tmp = 123;
console.log(tmp); //
}

《3》不允许重复声明,同一块级作用域中

《4》const声明一个只读的常量。一旦声明,常量的值就不能改变

这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

对于const来说,只声明不赋值,就会报错。

块级作用域解析

ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景

第一种场景,内层变量可能会覆盖外层变量。

第二种场景,用来计数的循环变量泄露为全局变量

ES6 中let 和const  带来了块级作用域(匿名立即执行函数不再那么必要)

块级作用域与函数声明

《1》ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。

浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数

《2》ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部
// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
} f();
}());
// Uncaught TypeError: f is not a function
// ES5 环境
function f() { console.log('I am outside!'); } (function () {
function f() { console.log('I am inside!'); }
if (false) {
}
f();
}()); // I am inside! // ES6 环境
function f() { console.log('I am outside!'); } (function () {
function f() { console.log('I am inside!'); }
if (false) {
}
f();
}()); // I am outside!


1.var 和function 的声明提升可以在函数内return 后面仍然见效(因为js预解析)

var a = 1;
function b() {
a = 120;
return;
function a() {}
}
b();
alert(a); //1; //实际
var a = 1;
function b() {
var a; //此处为函数
a = 120;
return;
function a() {}
}
b();
alert(a);

在创建这个函数的时候,这个函数的作用域就已经决定了,而是不是在调用的时候,

高级js 变量提升以及自由变量的更多相关文章

  1. js 变量提升+方法提升

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  2. JS 变量提升与函数提升

    JS 变量提升与函数提升 JS变量提升 变量提升是指:使用var声明变量时,JS会将变量提升到所处作用域的顶部.举个简单的例子: 示例1 console.log(foo); // undefined ...

  3. js变量提升与函数提升的详细过程

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  4. JS变量提升和作用域

    一.JS变量提升 1.当浏览器引擎解析js代码时,将js中的所有一开始就是var声明的和function声明的都提升到全局.此时又叫全局作用域 console.log(aa); console.log ...

  5. js变量提升的坑

    关于js变量提升 变量提升 在js函数内部是可以直接修改全局的变量的,个人感觉是不好的设计, 但是确实存在这个概念 原理: 先查看有没有函数变量bb 查看形参有没有bb 查看全局有没有bb 报错, 找 ...

  6. js高级-函数变量提升

    var a = 10; function f1(){ console.log(a) //undefined  函数变量提升了 函数执行之前想创建了函数的EC 把函数里面声明的变量初始化undefine ...

  7. JS高级_变量提升和函数提升

    先执行变量提升,后执行函数提升 function a(){} var a console.log(typeof a)//function

  8. js 变量提升和函数提升原理

    关于js的变量,开始的时候我们都会被告知,变量声明应该在引用该变量之前.关于为什么要这样做呢,开始的时候本着会用就行的目的,也没去深究.不过后来经常会发现一些让人很费解的..姑且称为现象吧.先看一段代 ...

  9. 关于JS变量提升的一些坑

    function log(str) { // 本篇文章所有的打印都将调用此方法 console.log(str); } 函数声明和变量声明总是会被解释器悄悄地被“提升”到方法体的最顶部 变量声明.命名 ...

随机推荐

  1. Celery的常用知识

    什么是Clelery   Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统.专注于实时处理的异步任务队列.同时也支持任务调度. Celery的架构由三部分组成,消息中间件(message ...

  2. 自动PC端显示 手机端隐藏CSS代码判断实现

    实现场景描述: 有些内容部署在PC端但是有不适合在手机端显示(比如盒子过大,遮挡内容)或者手机端显示毫无意义等.我们可以使用下面的代码来实现:电脑端显示,手机端隐藏 实现方法: CSS控制判断 @me ...

  3. Lamda简单使用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. java有参

    一.带参数的方法 语法: 访问修饰符  方法返回值类型   方法名称 (参数列表){ // 方法体 注意:每个参数之间用","分割 二.形参和实参 形参:在方法定义时指定的参数 实 ...

  5. 苹果vs中国竞争者:瘦死的骆驼比马大?

    前不久,苹果调整2019年第一财季的营收指引,预计第一季度毛利率为38%,相关收入大约为55亿美元,全年总体营收约为840亿美元,运营开支约为87亿美元.针对2019年的运营状况,库克亲自给投资者写了 ...

  6. python 字符串实例:检查并判断密码字符串的安全强度

    检查并判断密码字符串的安全强度 import string def check(pwd): #密码必须至少包含六个字符 if not isinstance(pwd,str) or len(pwd)&l ...

  7. MFC 状态栏的使用 CstatusBar

    你在源文件头文件声明一下 CStatusBar   zhuangtailan; 然后在窗口初始化添加以下代码 zhuangtailan.Create(this);//意思是在本窗口创建 UINT id ...

  8. sql 报错问题

    SQLServer数据库密码已过期问题 处理

  9. Arch系Linux中安装Docker

    Arch系Linux中安装Docker 1. 下载最新版docker $ sudo pacman -Syu docker 2. 免sudo执行docker $ sudo gpasswd -a ${US ...

  10. 【剑指Offer】面试题32 - I. 从上到下打印二叉树

    题目 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回: [3 ...