最近也是高考季了,首先在这里恭祝所有的高考学子一声--高考快乐。顺便也说一句过来人的忠告:高考只是决定你去哪个地方去打四年游戏罢了。考的好是幸运,考的不好也别气馁,就拿我们行业来说,学历并不能证明所有事情,batj又不是只招985,211。总之,恭祝所有进入高考的小朋友吧。 嗯,切入今天的主题吧。我大概写前端也有很长时间了,我觉得我也不能总是依附在转型中。所以我新开了一个专题,专门来研究一波es6。
##一、块级作用域 如果有一定的es5基础的小伙伴都知道,es5只有全局作用域和函数作用域,没有所谓的块级作用域。这里可能会带来一定的不便,有的时候出现一些小 bug 都不知道为什么。 例如(例子取自阮一峰老师的ES6入门): 1、 内层变量可能会覆盖外层变量
var temp = 1;
function test01(){
console.log(temp);
if(false){
var temp = "hello world"
}
}
test01(); // 运行结果:undefined
复制代码
2、 用来计数的循环变量泄露为全局变量
var name = "klivitam"; // length = 7
for (var i= 0; i < name.length; i++) {
console.log(name[i]);
}
console.log(i) // 运行结果:8
复制代码
不知道是不是因为这些bug导致设计师设计出了let和块级作用域。 ##二、let,const,块级作用域。
1、let:
我们前面说过let可以解决前面var带来的一个尴尬之处,那我就实践一下是否能解决: 实践1:
// 注意,按照我自己的理解方法,我认为在es6中“{}”就是一个块级作用域
{ // 块级作用域
var test01 = 0;
let test02 = 0;
}
console.log(test01); // 0
console.log(test02); // ReferenceError: test02 is not defined
复制代码
这里我们可以清楚的看到,let定义只存在块级作用域下面。出了块级作用域之后就会报错。这里注意一下,在es6环境下面,默认打开严格模式,所以这里会直接报错。es6环境下相当于默认开启了
//相当于es5下面的前面添加这个.
"use strict"
复制代码
实践2:
{ //域1
let test01 = "klivitam"
{ //域2
// console.log(test01) // ReferenceError: test01 is not defined
let test01 = "wawawawawawa"
console.log(test01) // 运行结果:wawawawawawa
}
}
复制代码
这里我们看到在域2中打印的时候会报错undefined,其实这是我在写这篇文章的时候才知道的。这里好像如果在同一个作用域下面同时命名两次,如下所示:
{
let test01 = "hhh"
let test01 = "kkk" // 报错: Identifier 'test01' has already been declared
}
复制代码
2、const:
其实读过前面的文章的小伙伴都知道,我也是一个Android开发者,这个const我类似java中的
//java es 6
private const final <===> const
复制代码
好了,当然这这里可能很多人都不知道前面的这个是什么,ok,直接用代码解释一下。
{
const PI = "3.1415926"
console.log(PI)
PI = "i dont know" //运行结果:TypeError: Assignment to constant variable.
}
复制代码
由上面的结果可以知道:const定义的常量是不能进行修改的。但是可能存在这么一种情况:
{
const student = {
name: "klivitam"
}
student.age = 23
console.log(student) // 运行结果:{ name: 'klivitam', age: 23 }
}
复制代码
这里我们知道const定义的对象是引用类型,指针指向的是对象的地址,我们在进行添加属性的时候地址是没有改变的,所以能够添加成功。如果是这样就会报错:
{
const student = {
name:"klivitam"
}
student.name = "liuyifei"
console.log(student) //运行结果:{ name: 'liuyifei' }
student = {
name: "liuyifei"
} // 运行结果:TypeError: Assignment to constant variable.
}
复制代码
三、解构赋值:
es6的解构赋值一共有如下几种:
{
let a = 0;
let b = 1;
let c = 2;
// define....
}
复制代码
但是在es6中我们可以直接进行操作
{
let [a,b,c] = [0,1,2]
console.log("a",a) // a 0
console.log("b",b) // b 1
console.log("c",c) // c 2
}
复制代码
当然这里只是数组的解构,我们也可以用对象进行解构操作:
{
let {a,b,c} = {a:0,b:1,c:2};
console.log("a",a) // a 0
console.log("b",b) // b 1
console.log("c",c) // c 2
}
复制代码
当然其他的我就不一一赘述了,因为明天还要上班呢????我在这里就主要介绍一下用法吧。如果还存在疑惑,自己拿出笔记本敲一下就懂了,我就简单的来介绍一下用法吧: 用法1:数值变换:
{
// es5用法
let a = 1;
let b = 2;
let c= a;
a = b;
b = c;
console.log("a",a) // a 2
console.log("b",b) // b 1
// es6
let a1 = 1 ,b1 = 2;
[a1,b1] = [b1,a1];
console.log("a1",a1) // a1 2
console.log("b1",b1) // b1 1
}
复制代码
用法2:函数返回值
{
function f(){
return [1,2];
}
let [a,b] = f();
console.log("a",a) // a 1
console.log("b",b) // b 2
function f1(){
return [1,2,3,4,5];
}
let [c,...d] = f1();
/* 选择返回一个数组加上一个数值 */
console.log("c",c) // c 1
console.log("d",d) // d [ 2, 3, 4, 5 ]
/* 选择返回部分数据 */
let [e,,,,g] = f1();
console.log("e",e) // e 1
console.log("g",g) // g 5
/* 传值部分初始化 */
function f2(a1,b2 = 5){
return [a1,b2];
}
let m = f2(1,2)
let h = f2(1)
let t = f2()
console.log("m",m) // m [ 1, 2 ] 当传b1进去的时候,覆盖原有的b1
console.log("h",h) // h [ 1, 5 ] 当没传b1进去的时候,取原有值
console.log("t",t) // t [ undefined, 5 ] 当没有传a1的时候,默认认为为undefined
}
复制代码
解构赋值这个呢?暂时能想到的用法就是这些了,我遇到的也就是这些了。至于其他的解构方式其实大同小异,多敲代码,要大胆得用最新的代码去最新的代码里面。
四、字符串扩展:
####1、字符的码点表示 javaScript 允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。就比如:
"\u0061"
// "a"
复制代码
但是,这种表示法只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。如下图所示:如果直接在\u后面跟上超过0xFFFF的数值(比如\u20BB7),JavaScript 会理解成\u20BB+7。就会显示乱码加上7,但是es6中对这个进行了改进,只要将字符放进大括号内就可以直接读出来了。
// es5
let a = "\uD842\uDFB7"
let b= "\u20BB7"
console.log(a) // ?
console.log(b) // ₻7
// es6
let c = "\u{20BB7}"
console.log(c) // ?
console.log(a ===c) // true
复制代码
从最后一句话里面我们就可以知道了:大括号表示法与四字节的 UTF-16 编码是等价的。 那么此时例如z就有了如下几种写法:
'\z' === 'z' // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true
复制代码
####2、es6对字符码点的改进 JavaScript 内部,字符以 UTF-16 的格式储存,每个字符固定为2个字节。对于那些需要4个字节储存的字符(Unicode 码点大于0xFFFF的字符),JavaScript 会认为它们是两个字符。这里我们来用代码体验一下es6的改进吧。
{
let name = "\u{20BB7}7"
// es5
console.log(name.charAt(0)) //�
console.log(name.charCodeAt(0)) //55362
console.log(name.charAt(1)) //�
console.log(name.charCodeAt(1)) // 57271
console.log(name.charAt(2)) //7
console.log(name.charCodeAt(2)) // 55
// es6
console.log(name.codePointAt(0).toString(16)) // 20bb7
console.log(name.codePointAt(1)) // 57271
console.log(name.codePointAt(2)) // 55
}
复制代码
####3、es6对码点解码的改进 codePointAt方法的参数,是字符在字符串中的位置(从 0 开始)。上面代码中,JavaScript 将“\u{20BB7}a”视为三个字符,codePointAt 方法在第一个字符上,正确地识别了“\u{20BB7}”,返回了它的16进制码点 20bb7。在第二个字符(即“?”的后两个字节)和第三个字符“7”上,codePointAt方法的结果与charCodeAt方法相同。
总之,codePointAt方法会正确返回 32 位的 UTF-16 字符的码点。对于那些两个字节储存的常规字符,它的返回结果与charCodeAt方法相同。
{
// es5
console.log("a",String.fromCharCode(0x61)) // a a
console.log("?",String.fromCharCode(0x20BB7)) // b ஷ
//es6
String.fromCodePoint(0x20BB7)
console.log("?",String.fromCodePoint(0x20BB7)) // b ?
}
复制代码
ES5 提供String.fromCharCode方法,用于从码点返回对应字符,但是这个方法不能识别 32 位的 UTF-16 字符(Unicode 编号大于0xFFFF)。此时就需要用到es6里面的fromCodePoint方法了。
####4、es6常用的方法: 1、 字符遍历:
{
let name = "\u{20BB7}7"
// es5
for(let i = 0;i< name.length;i++){
console.log(name[i]) // � � 7
}
// es6
for(let i of name){
console.log(i) // ? 7
}
}
复制代码
2、 判断包含:
{ // 终于不需要用index了。但是我在做微信支付的时候,发现没有作用.
let str = "string";
console.log(str.includes("str")) // true
console.log(str.includes("k")) // false
}
复制代码
3、 判断字符结尾/开头:
let s = 'Hello world!';
s.startsWith('Hello') // true
s.endsWith('!') // true
复制代码
4、 重复:
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
复制代码
5、 模版字符串:
{
let name = "klivitam"
let age = "29"
console.log(`my name is ${name},${age} years old.`) // my name is klivitam,29 years old.
}
复制代码
6、 padStart/padEnd
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
复制代码
7、 “/”不生效:
{
let name = "klivitam"
console.log(String.raw`hi/n${name}`)
}
复制代码
7、 标签模版
let total = 30;
let msg = passthru`The total is ${total} (${total*1.05} with tax)`;
function passthru(literals) {
let result = '';
let i = 0;
while (i < literals.length) {
result += literals[i++];
if (i < arguments.length) {
result += arguments[i];
}
}
return result;
}
msg // "The total is 30 (31.5 with tax)"
复制代码