1.块级作用域
   什么是:
         在一个代码块(括在一对花括号中的一组语句)中定义的所需变量(与let配合使用)并在代码块的外部是不可见的。
   为什么:
         在ES6之前,函数只能在全局作用域和函数作用域中声明,不能在块级作用域中声明,造成诸多问题:
              1.内层变量会覆盖外层变量
              2.用来计数的循环变量泄漏变成全局变量
   何时:
         需要强化对变量生命周期的控制,避免全局污染出现错误
   优点:
         1.阻止变量泄漏变为全局变量,造成全局污染
         2.阻止变量提升覆盖
         3.内层作用域可以定义与外层作用域相同的变量名,但变量是独立的。
         4.允许任意嵌套,外层作用域无法读取内层作用域的变量
   块级作用域:
         {},if{},else{},while{},for{},swicth{}…

    //块级作用域{},与let配合使用
{
//大括号之间就是块级作用域
var num=1;//还是全局变量,可以被外部访问
let num=1;//局部变量,不可以被外部访问,块级作用域必须用let声明
}
console.log(num);//此时num已经不可以被访问,说明块级作用域生效 //内层作用域可以定义与外层作用域相同的变量名,允许任意嵌套
//但变量与变量之间是没有关系的,都是独立的个体。
{
let aa=1;
console.log(aa);//
{
let aa=11;
console.log(aa);//
{
let aa=111;
console.log(aa);//
}
}
}
console.log(aa);//此时是不能被访问的,防止aa泄露为全局变量 //防止变量提升造成覆盖
//虽然都是f,但是配合了let使用,{}内部变成了一个小个体,不会影响其他的f
var f=17;
{
let f=28;
console.log(f);
}
console.log(f); //for块级作用域
//计算1-100之间所有的整数的和,使用var声明
for (var i=1,sum=0;i<=100;i++){
sum+=i;
}
console.log(sum);//5050,可以访问
console.log(i);//101,可以访问 //使用let声明变量
for (let i=1,sum=0;i<=100;i++){
sum+=i;
}
console.log(i);//此时i是不能被访问的。
console.log(sum);//此时sum是不能被访问的。
//根据需求得知,最后需要访问的是sum,i需要释放
//所以把sum单独放在外面,sum就可以被访问,而i会被释放
var sum=0;
for (let i=1;i<=100;i++){
sum+=i;
}
console.log(sum);

2.let声明
   什么是:
         专门代替var来声明变量用的
   为什么:
         var的问题:
             1.声明提前
             2.没有块级作用域
             3.造成全局污染
   何时:
         只要声明变量都用let
   优点:
         1.阻止了声明提前
         2.添加了块级作用域
         3.成为局部变量,不会造成全局污染
   原理:
         let其实就是一个匿名函数自调用!
         且let为了双保险,其实在底层悄悄给变量改了名字,在变量前增加了_
   let的小脾气:
         1.在相同作用域/块内:禁止同时let两个同名的变量
         2.在let 变量 之前到当前作用域的顶部之间,不允许提前使用变量
         3.不可以在函数内部重复声明参数

    //1.简单了解let声明的变量
let a=2;
console.log(a);
let a=3;
console.log(a);//报错,a不能重复声明并赋值 //var声明的变量可以重复声明并重新赋值
var b=2;
console.log(b);//
var b=3;
console.log(b);// //在块级作用域内{}
{
var c=2;
let c=4;//在同一块级作用域内不允许重复声明变量
let d=3;
console.log(d);//只能在当前{}块级作用域内访问
}
console.log(c);//可以被外部访问的是var声明的c
console.log(d);//不可以被外部访问 //let不允许先调用,后声明
{
console.log(aaa);
let aaa=5;//报错Cannot access 'aaa' before initialization
}

把let放入实例中理解

        //let应用
//累加每个任务函数的时间
var t=0;
function task1(){
console.log(`任务1耗时3s`);
t+=0.3;
}
function task2(){
console.log(`任务二耗时8s`);
t+=0.8;
}
task1();
task2();
console.log(`共耗时${t}s`)
         以上是一个可以正常执行的代码,并且是正确的程序
         如果在task2内添加其他的功能,例如捕捉错误

        //累加每个任务函数的时间
var t=0;//声明变量t准备累加每个任务函数的时间
function task1(){
console.log(`任务1耗时3s`);
t+=3;
}
function task2(){
console.log(`任务二耗时8s`);
t+=8;
//模拟出错的变量,此段代码是不执行的
var err=false;
//如果出错
if(err==true){
//就获得出错时间
var t=new Date();
//并输出出错提示日志
console.log(`出错啦,at:${t.toLocaleDateString()}`);
};
}
task1();
task2();
console.log(`共耗时${t}s`)
         代码正常执行,if内代码是不执行的,但是结果却是错误的,少了8s,那么为什么少了8s呢?
         原来是因为var声明的变量是全局变量,而if{}不是作用域,没有实体墙,拦不住var,
         所以var声明的变量会提升到当前作用域task2的最前面。

        //累加每个任务函数的时间
var t=0;//全局t
function task1(){
console.log(`任务1耗时3s`);
t+=3;
}
function task2(){
//var t;//undefined,var声明的t提前到该作用域最前面,并且没有赋值
//如果task2()中已经有了局部变量t,就不会用全局的t了,只有在局部没有的t的时候才会调用全局的t
console.log(`任务二耗时8s`);
//这个8s没有加到全局t,而是加在局部t上,当函数调用后,局部的t就被释放了
t+=8;//task2中的局部变量t,加在这里
var err=false;//模拟出错的变量
//如果出错
if(err==true){//if else for while do whlie 等程序结构的{}不是作用域,不是实体墙,拦不住var
//就获得出错时间
var t=new Date();
//并输出出错提示日志
console.log(`出错啦,at:${t.toLocaleDateString()}`);
};
}
task1();
task2();
console.log(`共耗时${t}s`)//此处输出的是全局的t,所以没有那8s,
         那么鉴于这种明明没有执行的代码,却破坏了原本正确的代码,
         这就是没有块级作用域带来的危害,此时就需要使用let声明变量了,
         因为let会阻止声明提前,并会添加块级作用域

       //累加每个任务函数的时间
var t=0;//全局t
function task1(){
console.log(`任务1耗时3s`);
t+=3;
}
function task2(){
console.log(`任务二耗时8s`);
t+=8;//这个t还是会加到全局的t上,没有被影响
//模拟出错的变量
//var err=false;//代码不执行
var err=true;//代码执行
//如果出错
if(err==true){//let将if{}也变成了一级作用域,这个作用域是有实体墙的,是可以拦住let声明的变量的 //就获得出错时间
//let阻止了局部的t被声明提前
let t=new Date();//此时的t是在这个if块级作用域的函数内,不会存在提升
//并输出出错提示日志
console.log(`出错啦,at:${t.toLocaleDateString()}`);//所以此时输出的t也是if内的t
};
}
task1();
task2();
console.log(`共耗时${t}s`)//打印全局t
         let的原理,添加匿名函数自调用,并改变名字

        //累加每个任务函数的时间
var t=0;//全局t
function task1(){
console.log(`任务1耗时3s`);
t+=3;
}
function task2(){
console.log(`任务二耗时8s`);
t+=8;//这个t还是会加到全局的t上,没有被影响
//var err=false;
var err=true;//模拟出错的变量
//如果出错
if(err==true){//let将if{}也变成了一级作用域,这个作用域是有实体墙的,是可以拦住let声明的变量的
//(function(){//let自动添加的
//就获得出错时间
//let阻止了局部的t被声明提前
let t=new Date();//let悄悄改变了名字,变成了_t,此时的t是在这个if块级作用域的函数内,不会存在提升到
//并输出出错提示日志
console.log(`出错啦,at:${t.toLocaleDateString()}`);//_t,所以此时输出的t也是if内的t
//})();//let自动加的
};
}
task1();
task2();
console.log(`共耗时${t}s`)//打印全局t    

单词:
               declare——声明
               access——访问
               initialization——初始化——>第一次声明+赋值=初始化

01.JS块级作用域与let的更多相关文章

  1. 混合开发的大趋势之 一个Android程序员眼中的 React.js 块级作用域 和 let

    转载请注明出处:王亟亟的大牛之路 最近都有事干然后,快到月底了这个月给CSDN的博文也就两篇,想想也蛮多天没更了,那就来一篇. 老规矩,先安利:https://github.com/ddwhan012 ...

  2. ES6块级作用域

    块级作用域的优点 避免变量冲突,比如程序中加载了多个第三方库的时候,如果没有妥善地将内部私有函数或变量隐藏起来,就很容易引发变量冲突: 可以方便的进行模块管理: 利于内存回收:(块级作用域里声明的变量 ...

  3. 6个函数的output看JS的块级作用域

    1. var output = 0; (function() { output++; }()); console.log(output); 函数对全局的output进行操作,因为JS没有块级作用域,所 ...

  4. 可怜的js居然没有块级作用域

    js中在一个函数中定义一个for循环:for(var i=0;i<5;i++) 其中的i并不会随着for循环的结束就销毁,i会一直存在该函数中,这就是js和其他语言的区别,也就是js没有块级作用 ...

  5. 一个经典的js中关于块级作用域和声明提升的问题

    function functions(flag) { if (flag) { function getValue() { return 'a'; } } else { function getValu ...

  6. JS的块级作用域

    今天带来的是 "对<你不知道的js>中块级作用域的总结" 分享: 1)用with从对象中创建出来的作用域只在with声明中而非外部作用域有效,同时可以访问已有对象的属性 ...

  7. JavaScript的作用;JS常见的三种对话框;==和===的区别;函数内部参数数组arguments在函数内部打印实参;JS的误区:没有块级作用域

    JS:客户端(浏览器)脚本语言 弱类型 基于原型 事件驱动 不需要编译(直接运行)   JS的作用:表单验证,减轻服务端的压力 添加页面动画效果  动态更改页面内容  Ajax网络请求 (一)常见的对 ...

  8. 你不知道的JS之作用域和闭包(三)函数 vs. 块级作用域

      原文:你不知道的js系列 在第(二)节中提到的,标识符在作用域中声明,这些作用域就像是一个容器,一个嵌套一个,这个嵌套关系是在代码编写时定义的. 那么到底是什么产生了一个新的作用域,只有函数能做到 ...

  9. JS 模仿块级作用域

    function outputNumbers(count) { for (var i=0; i<count; i++) { console.log(i); } var i;  // 重新声明变量 ...

随机推荐

  1. 吴裕雄--天生自然 PYTHON3开发学习:OS 文件/目录方法

    import os, sys # 假定 /tmp/foo.txt 文件存在,并有读写权限 ret = os.access("/tmp/foo.txt", os.F_OK) prin ...

  2. vue路由的跳转-路由传参-cookies插件-axios插件-跨域问题-element-ui插件

    ---恢复内容开始--- 项目初始化 创建一个纯净的vue环境项目,手动书写全局的样式配置,全局的main,js配置 (1)如果vue项目在重构或者出错的时候,手动安装node_modules. 如果 ...

  3. 894A. QAQ#(暴力)

    题目出处:http://codeforces.com/problemset/problem/894/A 题目大意:计数依次出现QAQ的次数 #include<iostream> using ...

  4. windows 环境下Maven私服搭建

    使用Nexus.3.11在Windows环境上搭建1.下载nexus.3.11.zip包https://www.sonatype.com/download-oss-sonatype 下载下来之后,进行 ...

  5. mysql不常用查询

    --查看数据库版本 SELECT VERSION(); --查看字符编码与安装路径 SHOW VARIABLES LIKE '%char%';

  6. 在Linux中#!/usr/bin/python之后把后面的代码当成程序来执行。 但是在windows中用IDLE编程的话#后面的都是注释,之后的代码都被当成文本了。 该怎么样才能解决这个问题呢?

    本文转自:http://bbs.csdn.net/topics/392027744?locationNum=6&fps=1 这种问题是大神不屑于解答,小白又完全不懂的问题... 同遇到这个问题 ...

  7. Yii框架的学习指南(策码秀才篇)1-2 一步步学习yii framework

    我也是新手,不过之前学习了tp和ci框架,所以尝鲜想看看yii到底有多强大. 如何新建一个webapp(网站应用)呢,下面是2个步骤: 1. cmd 切换到htdocs下面的yii目录下的framew ...

  8. QT中的QQueue类、C++中的queue类

    C++中的queue 实现一种先进先出的数据结构,是一个模板类 头文件 #include<queue> queue<int> Q; //定义一个int型队列 Q.empty() ...

  9. abstract class

    在面向对象(OOP)语言中,一个类可以有一个或多个子类,而每个类都有至少一个公有方法作为外部代码访问的接口.而抽象方法就是为了方便继承而引入的,现在来看一下抽象类和抽象方法分别是如何定义以及他们的特点 ...

  10. Redis学习之热点key重建

    在Redis的生产环境中,大量客户端连接请求某一个key,但都需要从DB中获取数据,来回写数据库,如下图: <ignore_js_op> 造成的问题: 大量的线程请求数据库,造成数据库压力 ...