let 和 const
let 的特点
- let 的作用域在最近的 {} 之间
- 如果在 let a 之前使用 a ,那么报错(Temp Dead Zone)
- 如果重复let a , 会报错
- let 存在块级作用域
let 循环
for(let i = 0; i < 5;i++){
console.log(i) // 块里面的i = 圆括号里面 i 的值
}
console.log(i) // Uncaught ReferenceError: i is not defined
const 特点
- const 的作用域在最近的 {} 之间
- 如果在 const a 之前使用 a ,那么报错(Temp Dead Zone)
- 如果重复const a , 会报错
- 只有一次赋值机会,并且必须在声明的时候立马赋值
- const声明创建一个值的只读引用,在引用内容是对象的情况下,可以改变对象的内容:
let user = { name: 'ZhangSan', age: 21 };
const USER_A = user;
console.log("USER_A :", USER_A ); // user: {name: "ZhangSan", age: 21}
user.age = 18;
console.log("USER_A :", USER_A ) // user: {name: "ZhangSan", age: 18}
解构赋值
数组的解构赋值
- 匹配 [ b, a ] = [ a, b ]
let [a,b,c] = [1,2,3] ;
console.log(a,b,c) // 1 2 3
let[a,[b],c] = [2,[3],4];
console.log(a,b,c) // 2,3,4
let [a,b,...rest] = [10,20,30,40,50]
console.log(rest) // [30, 40, 50]
- 交换变量
let a = 1;
let b = 2;
[a,b] = [b,a];
console.log(a,b) // 2 1
- 默认值
let [a,b=2] = [3];
a // 3
b // 2 使用默认值
let [a,b=2] = [3,4];
a // 3
b // 4 有对应数值,使用对应数值
undefined 和null 的区别:
var [a,b,c] = [1,2]
console.log(a,b,c) // 1 2 undefined
var [a,b,c] = [1,2, null]
console.log(a,b,c) // 1 2 null
let[a=2,b=3] = [undefined, null]
a // 2
b // null
- 函数传参
let arr = [1,2];
function test([a,b]) {
console.log("a: " + a); // a: 1
console.log("b: " + b) // b: 2
}
test(arr)
对象的解构赋值
- 对象匹配 let { a, b, c } = objABC
let { name , age} = {name: 'xxx',age: 18};
name // xxx
age // 18
- 对象匹配的同时重命名
let { name : username, age} = {name: 'xxx',age: 18};
username // xxx
age // 18
- 对象匹配 —— 改变原来的值
let name = 'ZhangSan';
let obj = {name: 'xxx',age: 18};
console.log(name); // ZhangSan
({ name, age } = obj ) ; // 这里要用()包住,因为大括号会被解析成一个代码块报错
console.log(name) // xxx
- 指定默认值并重命名
let {a: A=1, b=2 } = {a: 99}
console.log(A) // 99
console.log(b) // 2
- 对象浅拷贝
let obj1 = { name: 'xxx',age: 18,others: {
fruits: 'xx1', book: 'wrrr' } };
let obj2 = {...obj1};
console.log(obj2) // {name: "xxx", age: 18,others: {fruits: 'xx1', book: 'wrrr' }}
- 对象合并 ...
let obj1 = {p1: 1, p2: 2};
let obj2 = {p2: 30, p3: 99};
let obj3 = Object.assign({},obj1,obj2);
console.log(obj3) // {p1: 1, p2: 30, p3: 99}
let obj4 = {...obj1,...obj2};
console.log(obj4) // {p1: 1, p2: 30, p3: 99}
参数处理
默认参数值
函数默认参数允许在没有值或undefined被传入时使用默认形参。
function sum(a=0,b=0){
console.log('a:'+a);
console.log('b:'+b);
return a + b
}
sum(1) // a:1 b:0 1
sum(2,6) // a:2 b:6 8
上面的代码等价于:
function sum(a,b){
a = a || 0;
b = b || 0;
console.log('a:'+a);
console.log('b:'+b);
return a + b
}
剩余参数
展开运算符
先来看一个数组的扩展:
var a = [1,2,3];
console.log(...a) ; // 1 2 3
var b = [...a,99,88];
console.log(b); // 对数组进行扩展 [1, 2, 3, 99, 88]
var c = b.concat(77,66);
console.log(c); // [1, 2, 3, 99, 88, 77, 66]
let arr1 = [1,2,3,4,5,6];
let [a,b,c,...arr2] = arr1;
console.log(arr2) // [4, 5, 6]
... 相当于把数组拆开
- 函数参数的扩展
function max(arr){
return Math.max(...arr)
}; // 求最大值
max([1,22,44,66,5,66,77,3,22,33,11,34]) // 77
function sort(...arr){
return arr.sort()
};
sort(1,2,5,3) // [1, 2, 3, 5]
- 类数组对象转数组
ES5 写法是:
let newArr = Array.prototype.slice.call(ArrayLike)
ES6 写法如下:
let items = document.querySelectorAll('li');
Array.from(items).forEach((item) => console.log(item.innerText));
或者
let items = document.querySelectorAll('li');
[...items].forEach((item) => console.log(item.innerText))
模板字面量
多行字符串
let str = `
line1,
line2,
line3
`; // 注意这里的 ` 不是单引号
str // "
line1,
line2,
line3
"
字符串插值
let city = ' xxx';
let str = ` Hi
Welcome to ${city}.
` // 同样的, 这里的 ` 不是单引号
str // " Hi
Welcome to xxx.
"
可以用来拼接HTML:
var data = [1,2,3,4];
var liArr = data.map((item) => `<li class="xxx"> 内容 ${item}</li>`
).join('');
console.log(liArr); // <li class="xxx"> 内容 1</li><li class="xxx"> 内容 2</li><li class="xxx"> 内容 3</li><li class="xxx"> 内容 4</li>
var html = `<ul>${liArr}</ul>`;
console.log(html) // <ul><li class="xxx"> 内容 1</li><li class="xxx"> 内容 2</li><li class="xxx"> 内容 3</li><li class="xxx"> 内容 4</li></ul>
带标签的模板字面量
如果一个模板字符串由表达式开头,则该字符串被称为带标签的模板字符串,该表达式通常是一个函数,它会在模板字符串处理后被调用,在输出最终结果前,都可以通过该函数来对模板字符串进行操作处理。
let name = 'xxx';
let score = 60;
let fn = function (){
console.log(arguments)
}
fn `${name} 的成绩是 ${score}`
运行结果如下:

let name = 'xxx';
let score = 60;
let fn = function (){
let str = arguments[0];
let arg1 = arguments[1];
let arg2 = arguments[2];
if(arg2 >= 80){
return arg1 + str +arg2 + ',再接再厉哦!'
} else{
return arg1 + str + arg2 + ',要加油了哦!'
}
}
fn `${name} 的成绩是 ${score}`
// "xxx, 的成绩是 ,60,要加油了哦!"
把 name 和 score 改下:
name = 'x2';score = 90;
fn `${name} 的成绩是 ${score}`
// "x2, 的成绩是 ,90,再接再厉哦!"
原始字符串
在标签函数的第一个参数中,存在一个特殊的属性raw,我们可以通过它来访问模板字符串的原始字符串,而不经过特殊字符的替换。
function tag(strings) {
console.log(strings.raw[0]);
}
tag`string text line 1 \n string text line 2`;
// string text line 1 \n string text line 2
原有字面量增强
- 更安全的二进制字面量(0b1111101)
- 更安全的八进制字面量(0o767)
- 字符串支持 Unicode
-- String.fromCodePoint
-- String.prototype.codePointAt - 正则表达式字面量添加 Unicode 支持(u 标记)
- 正则表达式添加 y 标记,支持粘滞匹配
对象属性加强
属性定义支持短语法 obj = { x, y }
ES5写法:
var a = 1;
var b = 4;
var obj = {a:a,b:b} ;
obj // {a: 1, b: 4}
ES6写法:
let a = 1;
let b = 4;
let obj = {a,b} ;
obj // {a: 1, b: 4}
属性名支持表达式
动态属性名
原来的写法:
var name = 'a';
var obj = {};
obj[name] = 123;
obj // {a: 123}
ES6:
let name = 'a';
let obj = {[name]: 123};
obj // {a: 123}
属性修饰符Object.defineProperty()
a === 1 && a ===2 && a === 3 问题
var i = 0;
Object.defineProperty(window,'a',{
get(){
i += 1;
return i
}
})
a === 1 && a ===2 && a === 3 // true
类 class
var Slider = {
append: function(){
console.log(1)
},
render: function(){
console.log(2)
}
}
ECMAScript 2015引入了一种对象方法的简短写法, "function" 关键字可以丢掉:
var Slider = {
append(){
console.log(1)
},
render(){
console.log(2)
}
}
构造函数
class Cat {
constructor(name,personality){
this.name = name;
this.personality = personality;
} // 注意: 这里没有逗号
sayHi (){ // 这个函数会放在原型上
console.log(`Hi,I'm a ${this.name}, I'm ${this.personality}`);
}
}
var BritishShorthair = new Cat('BritishShorthair','docile');
console.log(BritishShorthair); // {name: "BritishShorthair", personality: "docile"}
BritishShorthair.sayHi(); // Hi,I'm a BritishShorthair, I'm docile
上面的代码等价于
function Cat(name,personality){
this.name = name;
this.personality = personality;
};
Cat.prototype.sayHi = function(){
console.log(`Hi,I'm a ${this.name}, I'm ${this.personality}`)
};
var BritishShorthair = new Cat('BritishShorthair','docile');
console.log(BritishShorthair); // Cat {name: "BritishShorthair", personality: "docile"}
BritishShorthair.sayHi(); // Hi,I'm a BritishShorthair, I'm docile
class 共有属性不能是非函数:
- 可以用原型写
xxx.prototype.race = 'animal'
- get
class Cat {
constructor(name,personality){
this.name = name;
this.personality = personality;
}
get race (){
return 'animal'
}
}
let BritishShorthair = new Cat('BritishShorthair','docile');
BritishShorthair.race // animal
但是 不能通过 BritishShorthair.race = newvalue
来改

所以又要用到 set
class Cat {
constructor(name,personality){
this.name = name;
this.personality = personality;
this._race = `animal`;
}
get race (){
return this._race
}
set race(value){
this._race = value
}
}
let BritishShorthair = new Cat('BritishShorthair','docile');
再修改就发现改成功了:

如果想让属性只读,就不写set
ES6 模块
用 import 和 export 写好之后,
可以用webpack 或者 parcel (推荐) 打包 ,然后引入
<script type="module" src="javascripts/app.js"></script> <!-- 已支持 ES6 模块的浏览器 -->
<script nomodule src="dist/app.js"></script> <!-- 不支持 ES6 模块的浏览器 -->
Generator函数的含义与用法
Thunk函数的含义与用法
co函数库的含义与用法
async函数的含义与用法
tj/co
网友评论