资讯专栏INFORMATION COLUMN

ECMAScript6(1):块级作用域

KoreyLee / 1916人阅读

摘要:和块级作用域块级作用于对于强类型语言经验的人应该非常好理解一言以蔽之对变量作用于分隔使用了函数词法作用域而使用花括号块作用域。但是花括号对于没有声明直接定义以及用声明的变量没有影响这些变量依然遵守词法作用域规则。

let、const和块级作用域

块级作用于对于强类型语言经验的人应该非常好理解, 一言以蔽之:ES5对变量作用于分隔使用了函数(词法作用域), 而ES6使用花括号(块作用域)。
对于词法作用域在 javascript函数、作用域链与闭包 中有详细的解释。对于let 和 const声明的变量在花括号的分割下同样会形成作用于链(内部访问外部的, 但外部不能访问内部)。但是花括号对于没有声明直接定义以及用 var 声明的变量没有影响, 这些变量依然遵守词法作用域规则。

对于let 和 const 最大的好处就是避免了可能的运行时错误, 不过也有直观的好处:

用块(Blocks)替换立即执行函数(IIFEs)

定义循环变量不会外泄

循环定义函数可以不用闭包了

可以放心的在 if 等条件中定义函数

//用块(Blocks)替换立即执行函数(IIFEs)
//ES5
(function () {
  var food = "Meow Mix";
}());
console.log(food); // Reference Error

//ES6
{
  let food = "Meow Mix";
}
console.log(food); // Reference Error
var a = [];
for(let i = 0; i < 10; i++){
  a[i] = function(){
    console.log(i);
  }
}
a[6]();       //这里输出6, 在var定义i的for循环中输出 10
console.log(i);    //ReferenceError
function b(){console.log("outside");}
function f(){
  if(false){
    function b(){console.log("inside");}
  }
  b();
}
f();   // ES5 中报错:"TypeError:b is not a function" 而 ES6 中输出"outside"

由此例可以看出 function 定义函数不具有块级作用域。

但我们需要注意的一下几点:

let 和 const 声明的变量不在 window 的属性中

var a = 10;
let b = 20;
const c = 30;

console.log(window.a);    //10
console.log(window.b);    //undedined
console.log(window.c);    //undedined

let 和 const 声明的变量没有声明提前, 所以在作用域内存在暂时性死区

var temp = 20;
(function area(){
  console.log(temp);  //undefined
  var temp = 30;      //声明提前
}());
if(true){
  console.log(temp);  //ReferenceError   但是 babel 会得到 undefined
  let temp = 20;
}
//一个隐蔽的死区
function bar(x = y, y = 2){
  console.log(x, y);
}
bar();    //报错, 因为定义 x 的时候, y 还没有定义 (babel 中不报错,得到 undefined 2)
function par(x = 2, y = x){
  console.log(x, y);
}
par();    //22

let 和 const 声明变量在当前作用域(不包括作用域链)上不能重复。const声明的变量必须初始化, 且不能修改:

let a = 10;
var b = 20;
const c = 30;

let a = 4;    //报错
const b = 3;  //报错
c = 20;   //报错, c是只读的

不可以连续定义变量

let a=b=3;     //报错 b 未定义
const c=d=2;   //报错 d 未定义

技巧:ES6 中, 在块作用于外调用内部函数

var f;
{
  f = function(){
    console.log("inside");
  }
}
f();

const 声明的基本变量不可改变, 但复杂变量可以改变其内容

const 这个特性和底层的 c++ 一致, 在 c++ 中 const 相当于常指针 int * const p, 也就是其指向的数据所在内存区域可读可写, 但是指针的值初始后就不能改。

const a = 10;
const b = {
  num: 20
};
b.num = 30;
console.log(b.num);   //30
a = 20;         //TypeError
b = {
  num: 90
};              //TypeError

如果想让非基本变量内部也不可改变, 需要使用 Object.freeze() 方法。可以参考:javascript对象、类与原型链

跨模块常量

对于跨模块的常量, 可以这样写:

// const.js module
export const A = 1;
export const B = 2;

// test.js 文件
import * as constants from "./const";
console.log(constants.A);   //1
console.log(constants.B);   //2
//or
import {A, B} from "./const";
console.log(A);   //1
console.log(B);   //2

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97426.html

相关文章

  • ECMAScript6 新特性——“let和const命令”

    摘要:基本用法所声明的变量,只在命令所在的代码块内有效。在循环中适合使用不存在变量提升不像那样会发生变量提升现象暂时性死区只要块级作用域内存在命令,它所声明的变量就绑定这个区域,不再受外部的影响。块级作用域实际上为新增了块级作用域。 1 let 基本用法 所声明的变量,只在let命令所在的代码块内有效。 { let b = 100; console.log(b); //100...

    PascalXie 评论0 收藏0
  • 常用ECMAScript6语法归纳

    摘要:对象的解构赋值函数执行后,返回的是一个对象。分别取出对象中属性为和的值,根据解构赋值的规则,在左侧声明变量,放在大括号中,变量名要和属性名保持一致。箭头函数在中,箭头函数就是函数的一种简写形式允许使用箭头定义函数。 原文博客地址,欢迎学习交流:点击预览 声明变量 可以使用let、const关键字声明变量,而不推荐使用var声明变量 var声明变量的问题: 可以多次重复声明同一个变量...

    raledong 评论0 收藏0
  • ECMAScript6标准入门(一)新增变量与数据结构

    摘要:一简介与的关系是的规格,是的一种实现另外的方言还有和转码器命令行环境安装直接运行代码命令将转换成命令浏览器环境加入,代码用环境安装,,根目录建立文件加载为的一个钩子设置完文件后,在应用入口加入若有使用,等全局对象及上方法安装 一、ECMAScript6 简介 (1) 与JavaScript的关系 ES是JS的规格,JS是ES的一种实现(另外的ECMAScript方言还有Jscript和...

    Tangpj 评论0 收藏0
  • ES6学习摘要(01)(新人学习)

    摘要:入门一前言由于最近本人在学习,做一些笔记能够更好的熟悉,就趁此机会来写一篇关于的新人学习摘要吧。的作用域与命令相同只在声明所在的块级作用域内有效。块级作用域新增方式和实际上为新增了块级作用域。同时,函数声明还会提升到所在的块级作用域的头部。 ECMAScript6/ES6 入门 一、前言 由于最近本人在学习ES6,做一些笔记能够更好的熟悉,就趁此机会来写一篇关于ES6的新人学习摘要吧。...

    dmlllll 评论0 收藏0
  • 深入理解ES6 - var-let-const

    摘要:声明变量不存在变量提升。临时死区,而且不能在声明之前访问它。禁止重复声明相同的变量,否则报错。不存在变量提升,一旦执行快外就会立即销毁。声明不允许修改绑定,但允许修改值,也就是说用创建对象后,可以修改该对象的属性值。 知识点 var 声明变量: 1、存在变量提升,实际上var无论在哪里声明,都会被当做当前的作用域顶部声明变量。 2、可以重复声明,后声明的变量会覆盖前声明的变量。 let...

    alexnevsky 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<