了解了JS之后 就要开始ES6的学习了。http://es6.ruanyifeng.com/#docs/let
- JavaScript与ES6之间的关系
JavaScript 一种通用目的的脚本语言,遵循 ECMAScript 规范。 它是 ECMAScript 语言的一个分支版本。(Ecma International 一个为科学技术制定标准的组织。) - ECMAScript 6
它是 ECMA-262 标准的第六个版本,其特点是对 ECMAScript 规范有着显著的变化和改进。
同义词:ES6、ES2015 和 ECMAScript 2015
敲不下去还是看看就完了…… 敲麻烦
在线转换
Babel 提供一个REPL 在线编译器,可以在线将 ES6 代码转为 ES5 代码。转换后的代码,可以直接作为 ES5 代码插入网页运行。
作者写了一个工具ES-Checker,用来检查各种运行环境对 ES6 的支持情况。访问ruanyf.github.io/es-checker,可以看到您的浏览器支持 ES6 的程度。运行下面的命令,可以查看你正在使用的 Node 环境对 ES6 的支持程度。
敲敲更深刻
二、 let和const命令
- 1.let
ES6新增 let命令,用来声明变量,它的用法类似var
let声明的变量只能在let命令所在的代码块内有效
{
let a = 10;
var b = 1;
}
a // 代码块之外let变量报错 ReferenceError: a is not defined.
b //1
看到了 console.log 依旧不知道什么意思 这篇文章写的好清楚,等什么时候顿悟了再看
https://segmentfault.com/a/1190000012957199
console.error('这里头是提示错误信息文本');
console.error('这里头是提示错误信息文本');
console.warn('这里头是警告信息文本');
console.warn('这里头是警告信息文本');
看不懂接着看吧先
变量提升
var变量可以在声明之前使用,值为undefined。
let改变了这个语法行为,一定要先声明后使用
暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
“暂时性死区”也意味着typeof不再是一个百分之百安全的操作。
typeof x; // ReferenceError
let x;
如果一个变量根本没有被声明,使用typeof反而不会报错。
typeof undeclared_variable // "undefined"
function func(arg) {
let arg; // 报错
}
function func(arg) {
{
let arg; // 不报错
}
}
总之变量先声明再使用就对了……
- 块级作用域
其实这些都跟OC一样,一个大括号内不能重复命名,相同的变量名字大括号内优先于大括号外,大括号外头访问到的是大括号外头的那个变量,是访问不到大括号里头的变量的
- const命令
const声明一个只读的常量。一旦声明,常量的值就不能改变,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
- const命令
const PI = 3.1415926;
PI=3;//就会报错
const的作用域与let命令相同:只在声明所在的块级作用域内有效。
本质:const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
const a = [];
a.push('Hello'); // 可执行
a.length = 0; // 可执行
a = ['Dave']; // 报错
如果真的想将对象冻结,应该使用Object.freeze方法。
如果真的想将对象冻结,应该使用Object.freeze方法。
const foo = Object.freeze({});
// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;
上面代码中,常量foo指向一个冻结的对象,所以添加新属性不起作用,严格模式时还会报错。
除了将对象本身冻结,对象的属性也应该冻结。下面是一个将对象彻底冻结的函数。
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, i) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
ES6声明变量的六种方法
ES5只有两种声明变量的方法var和function。
ES6添加了 let、const、import、class
- 4.顶层对象的属性
浏览器环境顶层对象指的是window对象,顶层对象的属性与全局变量是等价的,顶层对象的属性与全局变量挂钩,被认为是 JavaScript 语言最大的设计败笔之一 未知错误运行起来才知道啥的
ES6改进这一点,为了兼容性,var命令和function命令声明全局变量,依旧是顶层对象的属性 另一方面 let、const、class不属于顶层对象。ES6开始 全局变量将逐步与顶层对象的属性脱钩
var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b // undefined
上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。let声明的不是全局变量 window这个顶层对象是获取不到的
三、变量的解构赋值
- 1.数组的解构赋值
ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这就被称为解构。
let a = 1;
let b = 2;
let c = 3;
ES6允许写成这样
let [a,b,c] = [1,2,3];
可以从代码中提取值,按照对应位置,对变量赋值。
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋值对应的值,
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
let [x, , y] = [1, 2, 3];
x // 1
y // 3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
let [foo] = [];
let [bar, foo] = [1];
以上两种情况都属于解构不成功,foo的值都会等于undefined。
不完全解构,右边的值只能能对应上左边一部分,包含,能对上哪个哪个就有值……
let [x, y] = [1, 2, 3];
x // 1
y // 2
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4
如果数组对应的右边值不是可以遍历的解构 那就就报错
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
- 2 对象的解构赋值
对象的属性没有次序,变量必须与属性同名,才能取到正确的值
let{bar,foo} = {foo:"aaa",bar: "bbb"};
foo //"aaa"
bar //"bbb"
let {baz} = { foo:"aaa",bar:"bbb"};
baz //undefined
let {foo:foo}={foo:"aaa"};
let {foo:baz} = {foo:"aaa"}
baz //"aaa"
foo //error:foo is not define
上面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo
let {foo:{bar}} = {baz:'baz'};
foo对象有个子对象{bar},foo没有对应的值是undefined,那么bar肯定也就更没有了,对空取值 那就报错了
let _tmp = {baz:'baz'};
_tmp.foo.bar //报错
对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。
let { log, sin, cos } = Math;
- 3.字符串的解构赋值
字符串被转换成了一个类似的数组对象
数组的对象都有一个length属性,因此还可以对某种对象的属性结构赋值
let {length:len} ='hello';
len // 5
- 4.数值和布尔值的解构赋值
等号右边是数值和布尔值,则会先转为对象
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
上面代码中,数值和布尔值的包装对象都有toString属性,因此变量s都能取到值。
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
- 函数参数的解构赋值
function add ([x,y]){
return x+y;
}
add([1,2]);//3
上面代码中,函数add的参数是个数组,但传入参数在内部就会被解构成变量 x 和 y。
不能使用圆括号的情况
(1)变量声明
(2)函数的参数
(3)赋值语句 ([a])= [5];//报错
可以使用圆括号的情况
赋值语句的非模式部分
[(b)] = [3]; //取得数组第一个成员,跟圆括号无关
({p:(d)}) = {}); //模式是p
[(parseInt.prop)] = [3]; //
- 7 用途
(1)交换变量的值
let x = 1;
let y = 2;
[x,y] = [y,x];
(2)从函数返回多个值
将他们放在数组或者对象中返回
//返回一个数组
function example () {
return [1,2,3];
}
//返回一个对象
function example () {
return{foo:1,bar:2};
}
let {foo,bar} = example();
(3)函数参数的定义方便将一组参数与变量名对应取来
// 参数是一组有序的值
function f ([ x , y , z]){……}
f([1 , 2 , 3]);
//参数是一组无次序的值
function f ({x , y , z}){……}
f ({z : 3, y : 2 , x = 1});
(4)提取 JSON 数据
let jsonData = {
id : 42,
status : "OK",
data : [867,590];
};
let {id , status,data:number} = jsonData;
(5)函数参数的默认值
jQuery.ajax = function( url , {
async = true,
beforeSend = function(){},
cache = true,
complete = function (){},
crossDomain = false,
global = true,
// more config
} = {}){
// do stuff
};
指定参数的默认值,就避免了在函数体内部再写 var foo = config.foo || 'default foo';
(6)遍历Map结构 Map 是个键值对的结构 字典??
const map = new Map();
map.set('first','hello');// 添加一对键值对,(key,value)
map.set('second','world');
for (let [key , value] of map){
console.log( key + "is" + value);
}
// first is hello
// second is world
只想获取键名,或者只想获取键值
// 获取键名
for (let [key] of map){
}
// 获取键值
for (let [ ,value] of map){
}
(7)输入模块的指定方法
const {sourceMapConsumer,SourceNode } = require("source-map");
四、字符串的扩展
- 字符的Unicode表示法
JavaScript 允许采用\uxxxx表示一个字符,其中xxxx表示字符的Unicode码点
- 字符的Unicode表示法
"\u0061" //"a"
但,这种表示法只限于码点在\u0000 ~ \uFFFF之间的字符。超过这个范围,必须用两个双字节的形式表示
"\uD842\uDFB7" // "𠮷"
"\u20BB7" //超过了0xFFFF的数值 JS理解成\u20BB+7
//由于\u20BB是个不可打印的字符,所以只会显示一个空格 跟一个7
// 7
ES6对这一点做出了改进,只要将码点放入大括号,就能正确解读该字符
"\u{20BB7}" // "𠮷"
"\u{41}\u{42}\u{43}" //"ABC"
let hello = 123;
hell\u{6F} // 123
'\u{1F680}' === '\uD83D\uDE80'
// true
- codePointAt()
var s = "𠮷";// 码点为 0x20BB7 UTF-16编码为0xD842 0xDFB7 (十进制为55362 57271 ) 四个字节
s.length // 2
s.charAt(0) // ' '
s.chatAt(1) // ' '
s.charCodeAt(0) //55362
s.charCodeAt(1) //57271
ES6 提供了codePointAt方法,能够正确处理 4 个字节储存的字符,返回一个字符的码点。
let s = '𠮷a';
s.codePointAt(0) // 134071
s.codePointAt(1) // 57271
s.codePointAt(2) // 97
codePointAt 方法返回的是码点的十进制值,如果想要十六进制的值,可以使用toString方法转换一下。
let s = '𠮷a';
s.codePointAt(0).toString(16) // "20bb7"
s.codePointAt(2).toString(16) // "61"
字符串可以被for...of循环遍历。
模板字符串中嵌入变量,需要将变量名写在${}之中。
function fn() {
return "Hello World";
}
`foo ${fn()} bar`
// foo Hello World bar
如果大括号中的值不是字符串,将按照一般的规则转为字符串。比如,大括号中是一个对象,将默认调用对象的toString方法。
网友评论