最近也是高考季了,首先在这里恭祝所有的高考学子一声--高考快乐。顺便也说一句过来人的忠告:高考只是决定你去哪个地方去打四年游戏罢了。考的好是幸运,考的不好也别气馁,就拿我们行业来说,学历并不能证明所有事情,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的解构赋值一共有如下几种:
自己写的一个百度脑图,每个都简单写一个例子
在es5中,我们知道如果命名的量比较多的时候我们一般都是一个一个来进行命名的。例如下面的:
{
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)"
五、说在最后:
image.png看到上面这个其实大家也就差不多懂了,嗯。我本来还想多写点。第一呢?是电脑没有什么电量了,当然也有自己最近失眠的特别严重。其实也是我心中的一个结。已经失眠了5年了,每年这个时间段都会失眠,也会变得很烦躁,只要过了高考就没事儿了,所以最近有一点比较堕落懒散并没有如期完成自己许下的承诺。幸好有很多人一直在简书上面关注我,所以谢谢大家了,我会做出更好的自己带来更好的文章的。谢谢,惯例洗澡去对抗失眠了。拜拜。
网友评论