ES6学习笔记(let、const、变量的解构赋值、字符串扩展)
2017-05-16 16:37
543 查看
一、let命令
1.
let命令所在的代码块内有效,
var声明的在全局范围内都有效
2.
for循环的计数器,就很合适使用
let命令
3.let声明的内部变量
i和外部变量
i是分离的
4.
var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为
undefined
let命令不会发生“变量提升”现象,它所声明的变量一定要在声明后使用,否则报错
5.
let不允许在相同作用域内,重复声明同一个变量
6.let会导致暂时性死区,在代码块内,使用
let命令声明变量之前,该变量都是不可用的
let实际上为 JavaScript 新增了块级作用域
1.外层作用域无法读取内层作用域的变量
2.内层作用域可以定义外层作用域的同名变量
二、const命令
1.
const声明一个只读的常量。一旦声明,常量的值就不能改变
2.
const一旦声明变量,就必须立即初始化,不能留到以后赋值
3.
const的作用域与
let命令相同:只在声明所在的块级作用域内有效
4.
const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用
5.
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,
const只能保证这个指针是固定的,至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心
var命令和
function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,
let命令、
const命令、
class命令声明的全局变量,不属于顶层对象的属性
二、变量的解构赋值
1.完全解构
let [a, b, c] = [1, 2, 3];//a=1,b=2,c=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 // [][/code]
如果解构不成功,变量的值就等于undefined。
let [foo] = [];
let [bar, foo] = [1];
以上两种情况都属于解构不成功,
foo的值都会等于
undefined。
2.不完全解构
let [x, y] = [1, 2, 3];
x // 1
y // 2
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4
3.如果等号的右边不是数组(或者严格地说,不是可遍历的结构,参见《Iterator》一章),那么将会报错
4.对于 Set 结构,也可以使用数组的解构赋值
let [x, y, z] = new Set(['a', 'b', 'c']);
x // "a"
字符串的扩展
三、
1.字符串的Unicode表示法
JavaScript 允许采用
\uxxxx形式表示一个字符,其中
xxxx表示字符的 Unicode 码点
这种表示法只限于码点在
\u0000~
\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示
2.codePointAt
ES6提供了
codePointAt方法,能够正确处理4个字节储存的字符,返回一个字符的码点
var s = '𠮷a';
s.codePointAt(0) // 134071
s.codePointAt(1) // 57271 s.codePointAt(2) // 97
codePointAt方法返回的是码点的十进制值,如果想要十六进制的值,可以使用
toString方法转换一下
[/code]
var s = '𠮷a';
s.codePointAt(0).toString(16) // "20bb7"
s.codePointAt(2).toString(16) // "61"
你可能注意到了,在字符串codePointAt方法的参数,仍然是不正确的。比如,上面代码中,字符[code]a
s的正确位置序号应该是1,但是必须向
codePointAt方法传入2。解决这个问题的一个办法是使用
for...of循环,因为它会正确识别32位的UTF-16字符[/code]
var s = '𠮷a';
for (let ch of s) {[/code]
console.log(ch.codePointAt(0).toString(16)); } // 20bb7 // 61
codePointAt方法是测试一个字符由两个字节还是由四个字节组成的最简单方法
[/code]
function is32Bit(c) {
return c.codePointAt(0) > 0xFFFF;
}
is32Bit("𠮷") // true
is32Bit("a") // false
3.String.fromCodePoint()方法,可以识别大于
ES6提供了[code]String.fromCodePoint
0xFFFF的字符,在作用上,正好与
codePointAt方法相反
String
.fromCodePoint(0x20BB7)
// "𠮷"
String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
// true
上面代码中,如果
String.fromCodePoint方法有多个参数,则它们会被合并成一个字符串返回。
注意,
fromCodePoint方法定义在
String对象上,而
codePointAt方法定义在字符串的实例对象上。
4.字符串的便利器接口
ES6为字符串添加了遍历器接口(详见《Iterator》一章),使得字符串可以被
for...of循环遍历。
for (let codePoint of 'foo') {
console.log(codePoint)
} // "f" // "o" // "o"
除了遍历字符串,这个遍历器最大的优点是可以识别大于
0xFFFF的码点,传统的
for[/code]
循环无法识别这样的码点
[/code]
var text = String.fromCodePoint(0x20BB7);
for (let i = 0; i < text.length; i++) {
console.log(text[i]);
}
// " "
// " "
for (let i of text) {
console.log(i);
}
// "𠮷"
上面代码中,字符串
text只有一个字符,但是
for循环会认为它包含两个字符(都不可打印),而
for...of[/code]
循环会正确识别出这一个字符的字符
5.at()
ES5对字符串对象提供charAt方法,返回字符串给定位置的字符。该方法不能识别码点大于[code]0xFFFF
[/code]
'abc'.charAt(0) // "a"
'𠮷'.charAt(0) // "\uD842"[/code]
上面代码中,
charAt方法返回的是UTF-16编码的第一个字节,实际上是无法显示的。
目前,有一个提案,提出字符串实例的
at方法,可以识别Unicode编号大于
0xFFFF的字符,返回正确的字符。
'abc'.at(0) // "a"
'𠮷'.at(0) // "𠮷"
6.includes(), startsWith(), endsWith()[code]
includes():返回布尔值,表示是否找到了参数字符串 startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。[/code]
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
[code] var s = 'Hello world!';
s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true
这三个方法都支持第二个参数,表示开始搜索的位置。
var s = 'Hello world!'
s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false
上面代码表示,使用第二个参数的行为与其他两个方法有所不同。它针对前n时,[code]endsWith
n个字符,而其他两个方法针对从第
n个位置直到字符串结束。
7.repeat()
repeat方法返回一个新字符串,表示将原字符串重复
n次
[/code]
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
参数如果是小数,会被取整(舍去小数)
'na'.repeat(2.9) // "nana"
如果
repeat的参数是负数或者
Infinity,会报错
但是,如果参数是0到-1之间的小数,则等同于0,这是因为会先进行取整运算。0到-1之间的小数,取整以后等于
-0,
repeat视同为0
参数
NaN等同于0
如果
repeat的参数是字符串,则会先转换成数字
[/code]
'na'.repeat('na') // ""
'na'.repeat('3') // "nanana"
8.padStart(),padEnd()
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。
padStart()用于头部补全,
padEnd()用于尾部补全
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串
如果省略第二个参数,默认使用空格补全长度
9、模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量
// 普通字符串
`In JavaScript '\n' is a line-feed.`
// 多行字符串
`In JavaScript this is
not legal.`
console.log(`string text line 1
string text line 2`);
// 字符串中嵌入变量,模板字符串中嵌入变量,需要将变量名写在${}之中,大括号内部可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
//模板字符串还能调用函数
function fn() {
return "Hello World";
}
`foo ${fn()} bar`
// foo Hello World bar
如果大括号中的值不是字符串,将按照一般的规则转为字符串。比如,大括号中是一个对象,将默认调用对象的
toString[/code]
方法
如果模板字符串中的变量没有声明,将报错
[/code]
上面代码中的模板字符串,都是用反引号表示。如果在模板字符串中需要使用反引号,则前面要用反斜杠转义
var greeting = `\`Yo\` World!`;
如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中,如果你不想要这个换行或空格,可以使用trim方法消除它
`
<ul>
<li>first</li>
<li>second</li>
</ul>
`.trim()[/code]
[code] 10.标签模板[/code]
模板字符串的功能,不仅仅是上面这些。它可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。这被称为“标签模板”功能(tagged template)。
alert`123`
// 等同于
alert(123)
标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数
但是,如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数
var a = 5;
var b = 10;
tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);[/code]
上面代码中,模板字符串前面有一个标识名函数处理模板字符串后的返回值[/code]tag,它是一个函数。整个表达式的返回值,就是[code]tag
[/code]
函数tag依次会接收到多个参数。
function tag(stringArr, value1, value2){
// ...
}
// 等同于
function tag(stringArr, ...values){
// ...
}
“标签模板”的一个重要应用,就是过滤HTML字符串,防止用户输入恶意内容
var message =
SaferHTML`<p>${sender} has sent you a message.</p>`;[/code]
function SaferHTML(templateData) {
var s = templateData[0];
for (var i = 1; i < arguments.length; i++) {
var arg = String(arguments[i]);
// Escape special characters in the substitution.
s += arg.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
// Don't escape special characters in the template.
s += templateData[i];
}
return s;
}[/code]
[/code]
相关文章推荐
- ES6入门(let和const,解构赋值,正则扩展,字符串扩展,数值扩展)
- ECMAScript 6笔记(let,const 和 变量的解构赋值)
- 【ES6学习】— (1)ES6简介、let与const命令以及变量的解构赋值
- ES6新特性 let、const、变量对象的解构赋值
- ES6学习笔记一之js发展、let、const、解构赋值
- ECMAScript6学习笔记 ——let、const、变量解构赋值
- es6学习篇之 let和const命令 、变量的解构赋值
- ES6学习笔记一:let、const、解构赋值
- ES6学习笔记之变量声明let,const
- ES6学习笔记-变量解构赋值
- 变量的赋值---字符串的解构赋值
- 复习es6-解构赋值+字符串的扩展
- 【es6】【变量的解构赋值】【字符串,数值和布尔值解构】【函数参数的解构赋值】【用途】
- 2、变量的解构赋值 —ES6学习笔记
- js-ES6学习笔记-变量的解构赋值
- ES6学习笔记(二)变量的解构赋值
- const命令,全局变量的属性,变量的解构赋值
- ECMAScript 6学习笔记(一)let、const、变量的结构赋值
- ES6学习笔记:变量的解构赋值
- es6入门(二):解构赋值和字符串的扩展