一、let和const申明变量和常量:
//作用域只限于当前代码块
//使用let申明的变量作用域不会提升
//在相同的作用域下不能申明相同的变量
//for循环体现let的父子作用域
如下示例可以看出let的优势:
<button>按钮一</button>
<button>按钮二</button>
<button>按钮三</button>
<script>
window.onload = function(){
const buttons = document.getElementsByTagName("button");
for(var i = 0; i<buttons.length; i++){
(function(i){
buttons[i].onclick = function(){
alert(i);
}
})(i);
}
}
</script>
window.onload = function(){
const buttons = document.getElementsByTagName("button");
for(let i = 0; i<buttons.length; i++){
buttons[i].onclick = function(){
alert(i);
}
}
}
二、es6的解构赋值:一一对应
数组:
let [name, age, sex] = ["Samve", 30, "men"];
console.log(name);
console.log(age);
console.log(sex);
对象:
let {name, age, sex} = {name: "张三" , age: 30, sex: "men"};
console.log(name);
console.log(age);
console.log(sex);
字符:
let [a, b, c, d, e] = "我是中国人!";
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);
三、Spread Operator 展开运算符:
ES6中另外一个好玩的特性就是Spread Operator 也是三个点儿...接下来就展示一下它的用途。
组装对象或者数组
//数组
const color = ['red', 'yellow']
const colorful = [...color, 'green', 'pink']
console.log(colorful) //[red, yellow, green, pink]
//对象
const alp = { fist: 'a', second: 'b'}
const alphabets = { ...alp, third: 'c' }
console.log(alphabets) //{ "fist": "a", "second": "b", "third": "c"
}
有时候我们想获取数组或者对象除了前几项或者除了某几项的其他项
//数组
const number = [1,2,3,4,5]
const [first, ...rest] = number
console.log(rest) //2,3,4,5
//对象
const user = {
username: 'lux',
gender: 'female',
age: 19,
address: 'peking'
}
const { username, ...rest } = user
console.log(rest) //{"address": "peking", "age": 19, "gender": "female"
}
对于 Object 而言,还可以用于组合成新的 Object 。(ES2017 stage-2 proposal) 当然如果有重复的属性名,右边覆盖左边
const first = {
a: 1,
b: 2,
c: 6,
}
const second = {
c: 3,
d: 4
}
const total = { ...first, ...second }
console.log(total) // { a: 1, b: 2, c: 3, d: 4 }
四、面向对象Class:
构造函数的另一种写法,作用在于对象原型的写法更加清晰,更加面向对象的编程方式
//1、构造函数
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype = {
constructor: Person,
print(){
console.log("我叫:" + this.name + ",今年:" + this.age + "!");
}
};
let person = new Person("张三", 19);
console.log(person);
//2、通过Class面向对象
class Person{
constructor(name, age){
this.name = name;
this.age = age;
}
print(){
console.log("我叫:" + this.name + ",今年:" + this.age + "!");
}
}
let person = new Person("张三", 19);
console.log(person);
person.print();
五、字符串扩展:
1、模板字符串:
let str = '适合敲代码';
let html = `
<html>
<head></head>
<body>
<p>今天天气不错</p>
<div>${str}</div>
</body>
</html>
`;
console.log(html);
2、endsWith():
3、startsWith():
4、includes():
5、repeat():
六、对象扩展:
1、Object.assign()这个方法来实现浅复制:
Object.assign() 可以把任意多个源对象自身可枚举的属性拷贝给目标对象,然后返回目标对象。第一参数即为目标对象。在实际项目中,我们为了不改变源对象。一般会把目标对象传为{}
const objA = { name: 'cc', age: 18 }
const objB = { address: 'beijing' }
const objC = {} // 这个为目标对象
const obj = Object.assign(objC, objA, objB)
// 我们将 objA objB objC obj 分别输出看看
console.log(objA) // { name: 'cc', age: 18 }
console.log(objB) // { address: 'beijing' }
console.log(objC) // { name: 'cc', age: 18, address: 'beijing' }
console.log(obj) // { name: 'cc', age: 18, address: 'beijing' }
// 是的,目标对象ObjC的值被改变了。
// so,如果objC也是你的一个源对象的话。请在objC前面填在一个目标对象{}
Object.assign({}, objC, objA, objB)
2、Object.is():判断两个值是否相等
console.log(NaN === NaN); //false
console.log(-0 === 0); //true
console.log(Object.is(NaN, NaN));//true
console.log(Object.is(0, -0));//false
3、Object.keys():
4、Object.values():
5、Object.entries():
6、对象中使用变量作为key:
const str = "name";
const obj = {
["my" + str]: "hello"
}
console.log(obj);
七、对象初始化简写:
ES5我们对于对象都是以键值对的形式书写,是有可能出现键值对重名的。例如:
function people(name, age) {
return {
name: name,
age: age
};
}
键值对重名,ES6可以简写如下:
function people(name, age) {
return {
name,
age
};
}
同样,key和value一样的,写一个就够了:
let name = "张三";
let age = "李四";
let person = {
name,
age
}
console.log(person);
ES6 同样改进了为对象字面量方法赋值的语法。ES5为对象添加方法:
const people = {
name: 'lux',
getName: function() {
console.log(this.name)
}
}
ES6通过省略冒号与 function 关键字,将这个语法变得更简洁
const people = {
name: 'lux',
getName () {
console.log(this.name)
}
}
八、箭头函数:
箭头函数最直观的三个特点。
不需要 function 关键字来创建函数
省略 return 关键字
继承当前上下文的 this 关键字
this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。
//例如:
[1,2,3].map(x => x + 1)
//等同于:
[1,2,3].map((function(x){
return x + 1
}).bind(this))
说个小细节。
当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{} 和 return;例如:
var people = name => 'hello' + name
//参数name就没有括号
作为参考
var people = (name, age) => {
const fullName = 'hello' + name
return fullName
}
//如果缺少()或者{}就会报错
九、函数默认参数:
在ES5我们给函数定义参数默认值是怎么样?
function action(num) {
num = num || 200
//当传入num时,num为传入的值
//当没传入参数时,num即有了默认值200
return num
}
但细心观察的同学们肯定会发现,num传入为0的时候就是false,但是我们实际的需求就是要拿到num = 0,此时num = 200 明显与我们的实际想要的效果明显不一样。
ES6为参数提供了默认值。在定义函数时便初始化了这个参数,以便在参数没有被传递进去时使用。
function action(num = 200) {
console.log(num)
}
action(0) // 0
action() //200
action(300) //300
十、import 和 export:
import导入模块、export导出模块
//全部导入
import people from './example'
//有一种特殊情况,即允许你将整个模块当作单一对象进行导入
//该模块的所有导出都会作为对象的属性存在
import * as example from "./example.js"
console.log(example.name)
console.log(example.age)
console.log(example.getName())
//导入部分
import {name, age} from './example'
// 导出默认, 有且只有一个默认
export default App
// 部分导出
export class App extend Component {};
总结:
1.当用export default people导出时,就用 import people 导入(不带大括号)
2.一个文件里,有且只能有一个export default。但可以有多个export。
3.当用export name 时,就用import { name }导入(记得带上大括号)
4.当一个文件里,既有一个export default people, 又有多个export name 或者 export age时,导入就用 import people, { name, age }
5.当一个文件里出现n多个 export 导出很多模块,导入时除了一个一个导入,也可以用import * as example
十一、数组扩展:
使用console.dir(Array)和console.dir(Array.prototype)查看es6中新增的属性的方法,比较常用的有:
1、Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组:
那么什么是类数组对象呢?所谓类数组对象,最基本的要求就是具有length属性的对象。
1)将类数组对象转换为真正数组:
let arrayLike = {
0: 'tom',
1: '65',
2: '男',
3: ['jane','john','Mary'],
'length': 4
}
let arr = Array.from(arrayLike)
console.log(arr) // ['tom','65','男',['jane','john','Mary']]
那么,如果将上面代码中length属性去掉呢?实践证明,答案会是一个长度为0的空数组。
这里将代码再改一下,就是具有length属性,但是对象的属性名不再是数字类型的,而是其他字符串型的,代码如下:
let arrayLike = {
'name': 'tom',
'age': '65',
'sex': '男',
'friends': ['jane','john','Mary'],
length: 4
}
let arr = Array.from(arrayLike)
console.log(arr) // [ undefined, undefined, undefined, undefined ]
会发现结果是长度为4,元素均为undefined的数组
由此可见,要将一个类数组对象转换为一个真正的数组,必须具备以下条件:
a、 该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组;
b、该类数组对象的属性名必须为数值型或字符串型的数字。
ps: 该类数组对象的属性名可以加引号,也可以不加引号。
2)将Set结构的数据转换为真正的数组:
let arr = [12,45,97,9797,564,134,45642]
let set = new Set(arr)
console.log(Array.from(set)) // [ 12, 45, 97, 9797, 564, 134, 45642 ]
Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。如下:
let arr = [12,45,97,9797,564,134,45642]
let set = new Set(arr)
console.log(Array.from(set, item => item + 1)) // [ 13, 46, 98, 9798, 565, 135, 45643 ]
3)将字符串转换为数组:
let str = 'hello world!';
console.log(Array.from(str)) // ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d", "!"]
4)Array.from参数是一个真正的数组:
console.log(Array.from([12,45,47,56,213,4654,154]))
像这种情况,Array.from会返回一个一模一样的新数组。
2、Array.of():
把一组织转换成数组。
3、arr.find()与arr.findInex():
arr.find():找出第一个符合条件的数组成员,如果没有找到则返回undefined。
arr.findIndex():找到位置,没有则返回-1。
4、.map():
5、.reduce():
6、.filter():
7、forEach():
8、.copyWithin:
9、every():
10、some():
11、map():
12、filter():
13、reduce():
14、reduceRight():
15、forEach():
16、find():
17、findIndex():
18、includes():
19、keys():
20、values():
21、entries():