所有es6知识点都参照 阮一峰
let和const
1、let和const所声明的变量只在let和const命令所在的代码块内有效
2、for循环的计数器,就很适合使用let和const命令var a = [];for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); };}a[6](); // 10
var a = [];for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); };}a[6](); // 6
上面代码中,变量i是let声明的,当前的i只在本轮循环中有效,所有内一次循环的i其实都是一个新的变量,因为JavaScript引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算
3、不存在变量生命提升
4、暂时性死区
只要在块级作用域内存在let命令,它所声明的变量就会binding这个区域,不再受外部的影响var a = 123;if (true) { a = 'abc'; // ReferenceError let a;}
上面代码中,存在全局变量a,但是块级作用域内let又声明了一个局部变量a,导致后者绑定这个块级作用域,所以在let声明变量前,对a赋值会报错。
如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。5、不允许重复声明
块级作用域
1、可以防止内层变量覆盖外层变量
2、可以防止用来计数的循环变量泄露为全局变量var s = 'hello';for (var i = 0; i < s.length; i++) { console.log(s[i]);}console.log(i); // 5
上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。
块级作用域的出现,实际上使得立即执行函数表达式不在必要了块级作用域与函数声明
- 允许在块级作用域内声明函数。
- 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
- 同时,函数声明还会提升到所在的块级作用域的头部。
- 要避免在块级作用域内声明函数。如果有需要也应该写成函数表达式,而不是函数声明语句。
// 函数声明语句{ let a = 'secret'; function f() { return a; }}// 函数表达式{ let a = 'secret'; let f = function () { return a; };}
const声明一个只读的常量。一旦声明,常量的值就不能改变。
变量的解构赋值
变量的解构赋值用途有很多
1、交换变量的值let a = 1;let b = 3;[a, b] = [b, a]
上面的代码交换a,b的值
2、从函数中返回多个值 函数只能返回一个值,如果要返回多个值,只能将他们放在数组或对象中返回。//返回一个数组function a(){ return [1,2,3];}let [l, m, n] = a();//返回一个对象function b(){ return { foo: 1, bar: 2 }}let {foo, bar} = b();
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, 5309]};let { id, status, data: number } = jsonData;console.log(id, status, number);// 42, "OK", [867, 5309]
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结构const map = new Map();map.set('first', 'hello');map.set('second', 'world');for (let [key, value] of map) { console.log(key + " is " + value);}// first is hello// second is world
7、输入模块的指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");
字符串的扩展
1、字符的 Unicode 表示法
先来了解一下Unicode是什么- Unicode源于一个想法:将全世界所有的字符包含在一个集合里,计算机只要支持这一个字符集,就能显示所有的字符,再也不会有乱码 它从0开始,为每个符号指定一个编号,这叫做"码点"(code point)。比如,码点0的符号就是null(表示所有二进制位都是0)。 2、字符串的遍历接口
for (let codePoint of 'foo') { console.log(codePoint)}// "f"// "o"// "o"
es5对字符串对象提供了charAt方法,返回字符串给定位置的字符。
'abc'.charAt(0) // "a"
es6提供了at()
'abc'.at(0) // "a"
3、includes(),startsWith(), endsWith()
es5中indexOf方法可以用来确定一个字符是否包含在另一个字符串中。es6又提供了三种新方法- includes(): 返回布尔值,表示是否找到了参数字符串
- startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
- endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
let s = 'Hello world!';s.startsWith('Hello') // trues.endsWith('!') // trues.includes('o') // true
这三个方法都支持第二个参数,表示开始搜索的位置。
let s = 'Hello world!';s.startsWith('world', 6) // trues.endsWith('Hello', 5) // trues.includes('Hello', 6) // false
上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。
4、repeat() reat方法返回一个新字符串,表示将原字符串重复n次 参数如果是小数会被取整 如果是负数或者infinity,会报错 但是,如果参数是 0 到-1 之间的小数,则等同于 0,这是因为会先进行取整运算。0 到-1 之间的小数,取整以后等于-0,repeat视同为 0。 参数NaN等同于 0。 如果repeat的参数是字符串,则会先转换成数字。'hello'.repeat(2) // "hellohello"'na'.repeat(0) // ""
5、padStart(),padEnd()
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。padStart和padEnd一共接受两个参数,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串。如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。如果用来补全的字符串与原字符串,两者的长度之和超过了指定的最小长度,则会截去超出位数的补全字符串。如果省略第二个参数,默认使用空格补全长度。padStart的常见用途是为数值补全指定位数。下面代码生成 10 位的数值字符串。'123456'.padStart(10, '0') // "0000123456"
另一个用途是提示字符串格式。
'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
6、字符串模板
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。// 普通字符串`In JavaScript '\n' is a line-feed.`// 多行字符串`In JavaScript this is not legal.`console.log(`string text line 1string text line 2`);// 字符串中嵌入变量 模板字符串中嵌入变量,需要将变量名写在${}之中。let name = "Bob", time = "today";`Hello ${name}, how are you ${time}?`
上面代码中的模板字符串,都是用反引号表示。如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。
let greeting = `\`Yo\` World!`;
大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。还能调用函数。
let x = 1;let y = 2;`${x} + ${y} = ${x + y}`// "1 + 2 = 3"`${x} + ${y * 2} = ${x + y * 2}`// "1 + 4 = 5"let obj = {x: 1, y: 2};`${obj.x + obj.y}`function fn() { return "Hello World";}`foo ${fn()} bar`// foo Hello World bar
模板字符串的变量之中,又嵌入了另一个模板字符串
const tmpl = addrs => `
${addr.first} |
${addr.last} |
|
Bond |
Lars |
|
如果需要引用模板字符串本身,在需要时执行,可以像下面这样写。
// 写法一let str = 'return ' + '`Hello ${name}!`';let func = new Function('name', str);func('Jack') // "Hello Jack!"// 写法二let str = '(name) => `Hello ${name}!`';let func=eval.call(null, str);func('Jack') // "Hello Jack!"
模板编译待了解。。。。。。。。
7、标签模板模板字符串的功能,不仅仅是上面这些。它可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。这被称为“标签模板”功能(tagged template)。
alert`123`// 等同于alert(123)
标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。
但是,如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。
但是,如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。let a = 5;let b = 10;tag`Hello ${ a + b } world ${ a * b }`;// 等同于tag(['Hello ', ' world ', ''], 15, 50);
上面代码中,模板字符串前面有一个标识名tag,它是一个函数。整个表达式的返回值,就是tag函数处理模板字符串后的返回值。
“标签模板”的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容。 标签模板的另一个应用,就是多语言转换(国际化处理)。 (不太理解) 模板处理函数的第一个参数(模板字符串数组),还有一个raw属性。console.log`123`// ["123", raw: Array[1]]
上面代码中,console.log接受的参数,实际上是一个数组。该数组有一个raw属性,保存的是转义后的原字符串。
tag`First line\nSecond line`function tag(strings) { console.log(strings.raw[0]); // strings.raw[0] 为 "First line\\nSecond line" // 打印输出 "First line\nSecond line"}
上面代码中,tag函数的第一个参数strings,有一个raw属性,也指向一个数组。该数组的成员与strings数组完全一致。比如,strings数组是["First line\nSecond line"],那么strings.raw数组就是["First line\nSecond line"]。两者唯一的区别,就是字符串里面的斜杠都被转义了。比如,strings.raw 数组会将\n视为\和n两个字符,而不是换行符。这是为了方便取得转义之前的原始模板而设计的。
未完。。。。。。。。。。。 待了解正则表达式