es6与Js的关系解析

ECMAscript 与 JavaScript关系

ECMA-262是第一版规则,其关系是前者是后者的规格,后者是前者的实现(这里我理解是一种标准类似于协议、规范等)

Babel 转码器

babel可以将es6转化为es5,不用担心环境支持
例如:

// 转码前
input.map(item => item + 1);

// 转码后
input.map(function (item) {
  return item + 1;
});

配置文件(.babelrc)
Babel 的配置文件是.babelrc,存放在项目的根目录下。使用 Babel 的第一步,就是配置这个文件。
该文件用来设置转码规则和插件,基本格式如下。
presets字段设定转码规则,官方提供以下的规则集,你可以根据需要安装。

最新转码规则

$ npm install --save-dev babel-preset-latest

react 转码规则

$ npm install --save-dev babel-preset-react

不同阶段语法提案的转码规则(共有4个阶段),选装一个

$ npm install --save-dev babel-preset-stage-0
$ npm install --save-dev babel-preset-stage-1
$ npm install --save-dev babel-preset-stage-2
$ npm install --save-dev babel-preset-stage-3

然后,将这些规则加入.babelrc。

{
"presets": [
"latest",
"react",
"stage-2"
],
"plugins": []
}

注意,以下所有 Babel工具和模块的使用,都必须先写好.babelrc
命令行转码器babel-cli
Babel提供了babbel-cli,用于命令行的转码

安装

$ npm install --global babel-cli
基本用法

转码结果输出到标准输出

$ babel example.js

转码结果写入一个文件

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

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

或者

$ babel example.js -o compiled.js

整个目录转码

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

$ babel src --out-dir lib

或者

$ babel src -d lib

-s 参数生成source map文件

$ babel src -d lib -s

let 和 const

let

和var类似用于声明变量,但是只在let命令的代码块中有用

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

a // ReferenceError: a is not defined.
b // 1
for循环的计数器更适合let
let不存在变量提升
var在声明前使用会出现undefined但是let为了避免这样操作,只能在声明后使用

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

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

暂时性死区

只要块级作用域内存在let命令,他所声明的变量就绑定这个区域,不再受外部的影响。

var tmp = 123;

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

上面代码中存在一个全局变量tmp=123,但是快级作用域内let又声明一个tmp='abc’变量,所以在let申明变量前,对tmp赋值就会报错。
ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

let不允许重复声明
let在相同作用域中重复申明同一个变量
// 报错

function () {
  let a = 10;
  var a = 1;
}

// 报错

function () {
  let a = 10;
  let a = 1;
}

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

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

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

块级作用域

在es5中只有全局作用域,函数作用域没有快级作用域,这带来很多不合理的场景。
第一:内层变量可能会嵌套外层变量

var tmp = new Date();

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

f(); // undefined

上面代码的原意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。
第二种场景,用来计数的循环变量泄露为全局变量。

var s = 'hello';

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

console.log(i); // 5

do 表达式
{
  let t = f();
  t = t * t + 1;
}

上面块级作用域将两个语句封装在一起。但是快级作用域,没有办法得到t的值,因为块级作用域不返回值,除非t是全局变量。
有一个提案,使得快级作用域可以变为表达式,也就是说是返回值,办法就是在作用域之前加上do,使他变为do表达式。

let x = do {
  let t = f();
  t * t + 1;
};

上面代码中,变量x会得到整个块级作用域的返回值。

const命令

基本
const声明一个只读常量,一旦声明常量的值就不能改变。
const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.
上面代码表明改变常量的值会报错
const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立刻初始化,不能留到最后。
const foo;
// SyntaxError: Missing initializer in const declaration
上面代码表示,对于const来说,只声明不赋值,就会报错。
const的作用域与let命令相同:只在声明所在的块级作用域内有效。

if (true) {
  const MAX = 5;
}
MAX // Uncaught ReferenceError: MAX is not defined

const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
声明方面const和let是一样的不可以重复。
本质
const是保证变量指向的那个内存地址不得改变,值保存在变量指向的那个内存地址,因此同等于常量对于复合类型数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指正是固定的,它的数据结构是否可变就不能控制了。
const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: “foo” is read-only

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

饭一口口吃

来杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值