带你从ES6基础走向成熟-01

大家好,接下来就跟小克一起来练习ES6吧。一起学习一起进步。

提示 $ 符号代表命令行  #代表标题

一    命令行转码 babel-cli

       安装转码工具首先必须有Node环境相信很多小伙电脑上已经都装了,如果没有可以到http://nodejs.cn/这里下载安装,无脑安装就行

            安装好node环境接下来我们就来安装babel-cli吧

            # 安装命令   

                             npm install -g babel-cli     执行命令进行全局安装。

            # 转码结果输出

                            $ babel example.js

            # 转码结果写入一个文件

                            # --out-file 或 o 参数指定    参数指定输出文件

                            $    babel   example.js   --out-file   complide.js

                            #或者      

                            $    babel   example.js    -o complide.js

            # 整个目录转码

                            #     --out-dir 或 -d 参数指定输出目录

                            $      babel  src --out-dir  lib

                            #      或者

                            $      babel   src   -d   lib 

二        let和const命令 

           1.let 命令

                基本用法           

                            ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,

                            只在let命令所在的代码块有效。

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

上面代码在代码块之中,分别用letvar声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。

for循环计数器,就很适合使用let

for (let i = 0; i < 10; i++) {
  // ...
}

console.log(i);

上面代码中,计数器i只在for循环体内有效,在循环体外引用就会报错。


下面的代码如果使用var,最后输出的是10

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10

上面的代码中,变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生变化,而循环内被赋给数组a的函数内部的console.log(i),里面i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮i的值,也就是10.

如果使用let,声明的变量仅在块级作用域内有效,最后输出的是 6。

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每次循环的i其实都是一个新的变量,所以最后输出的是6,你可能会问,如果每一轮循环的变量i都是重新声明的,那么他怎么知道上一轮循环的值,从而计算出本轮循环的值呢?这是因为javascript引擎内部会记住上一次循环的值,初始化本轮的变量i时,就在上一次循环中进行计算了。

另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc

上面代码正确运行,输出3次abc。这表明函数内部的变量i与循环i变量的i不在同一个作用域。有自己单独的作用域。

不存在变量提升

var命令会发生“变量提升”现象,即变量在声明之前使用,值为nudefined。这中现象多多少少是有些奇怪的,按照一般逻辑,变量应该在声明语句之后才能使用。

为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明之后使用,否则会报错。

// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

上面代码中,变量foo用var声明变量,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar是用let声明的,不会发生变量提升,在声明之前调用它,会直接报错。

暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外界的影响。

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

上面的代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

不允许重复声明

let不允许在相同的作用域内,重复声明变量。

// 报错
function func() {
  let a = 10;
  var a = 1;
}

// 报错
function func() {
  let a = 10;
  let a = 1;
}

因此,不能在函数内部重新声明参数。

function func(arg) {
  let arg; // 报错
}

function func(arg) {
  {
    let arg; // 不报错
  }
}


2. 块级作用域

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

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

var tmp = new Date();

function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world';
  }
}

f(); // undefined

上面代码的愿意是,if代码块的外部使用外部的tmp变量,内部的使用内部层的tmp变量。

但是,函数执行后,输出结果为undefined,原因在于变量提升,导致内层的tpm变量覆盖了外层的tmp变量

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

var s = 'hello';

for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}

console.log(i); // 5

上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。


ES6的块级作用域

let实际上为javascript新增了块级作用域。

function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); // 5
}

上面的函数有两个代码块,都声明了变量n,运行后输出5。这表示外层代码块不受内层代码块的影响。如果

两次都使用var定义变量n,最后输出的值才是10。

ES6允许块级作用域的任意嵌套。

{{{{{let insane = 'Hello World'}}}}};

上面代码使用了五层块级作用域,外层作用域无法读取内层作用域的变量。

{{{{
  {let insane = 'Hello World'}
  console.log(insane); // 报错
}}}};

内层作用域可以定义外层作用域的同名变量。

{{{{
  let insane = 'Hello World';
  {let insane = 'Hello World'}
}}}};

块级作用域的出现,实际上使得获得广泛应用的立即执行(IIFE)不再必要了。

// IIFE 写法
(function () {
  var tmp = ...;
  ...
}());

// 块级作用域写法
{
  let tmp = ...;
  ...
}

块级作用域与函数声明

函数能不能在块级作用域中声明?这是一个相当令人混淆的问题。

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

// 情况一
if (true) {
  function f() {}
}

// 情况二
try {
  function f() {}
} catch(e) {
  // ...
}


3。cosnt命令

基本用法

const声明一个只读的常量。一旦声明,常量的值就不会改变。

PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.    

上面代码表明改变常量的值会报错。

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

const foo;
// SyntaxError: Missing initializer in const declaration

上面代码表示,对于const来说,只声明变量不赋值,就会报错。

cosnt的作用域与let命令相同:只在声明的所在的块级作用域内有效。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值