1. ECMAscript2015 共有三种作用域
- 全局作用域
- 函数作用域
- 块级作用域(新增)
2. 变量声明: let const
- let const 都是块级作用域,let是变量,const是常量
var element = [{},{},{}]
for (var i = 0; i < element.length; i++){
element[i].onclick = function () {
console.log(i)
}
}
element[2].onclick()
// 通过 闭包
var element = [{},{},{}]
for (var i = 0; i < element.length; i++){
element[i].onclick = (function (i) {
return function () {
console.log(i)
}
}){i}
}
element[2].onclick()
// 通过 let 块级作用域
var element = [{}, {}, {}]
for(let i = 0; i < element.length; i++) {
// let定义的变量是块级作用域
element[i].onclick = function () {
console.log(i)
}
}
element[2].onclick() // 2
- let const 不会变量提升
console.log(foo) // undefined
var foo = 'jal'
console.log(foo2) // ReferenceError
let foo2 = 'jal'
- const 值类型 不可更改 引用类型可增加属性
const arr = [1,2,3]
arr.push(4)
const arr1 = [1,2,3]
arr1 = []
const str = '123'
str = '4576'
3. 数组的解构
方括号 [] 中的变量按顺序匹配数组元素
// 传统方式
const arr = [1, 2, 3]
const a = arr[0]
const b = arr[1]
const c = arr[2]
console.log(a, b ,c) // 1 2 3
// 数组解构方式
const [a, b, c] = arr
console.log(a, b ,c) // 1 2 3
const [, , c] = arr
console.log(c) // 3
const [a, ...c] = arr // 三个点解构只能用于最后一个位置
console.log(c) // [ 2, 3 ]
const [a, b, c, d] = arr
console.log(d) // undefined
const [a, b, c = 123, d = 'defaultValue'] = arr
console.log(c, d) // 3 defaultValue
const path = 'a/b'
const [, , b] = path.split('/')
console.log(b) // b
4. 对象的解构
const obj = {name: 'yibo', age: 22}
const {name} = obj
console.log(name) // yibo
const {name: objName, sex = 'boy'} = obj
console.log(objName, sex) // yibo boy
5. 模板字符串
const name = 'yibo'
const str = `this is ${name}`
console.log(str)
6. 模板字符串标签函数
const name = 'tom'
const gender = true
function myTagFunc (str, name, gender) {
console.log(str, name, gender) // [ 'hey, ', ' is a ', '.' ] tom true
return str[0] + name + str[1] + gender + str[2]
}
const result = myTagFunc`hey, ${name} is a ${gender}.`
console.log(result) // hey, tom is a true.
7. 字符串方法
- includes()
- startsWith()
- endsWith()
8. 函数默认值
// 带有默认值的参数要放在最后
function foo (enble = true) {
console.log(enable)
}
foo(true) // true
foo(false) // fasle
foo() // true
9. 剩余参数
剩余参数只能出现在形参的最后一位,而且只能使用一次
// ES5 之前用 arguments 接受剩余参数
function foo () {
console.log(arguments)
}
// ES6 之后 可以使用 剩余参数 。。。 去接受,但是只能出现在形参最后一位, 而且只能使用一次
function foo (...args) {
console.log(args)
}
foo(1,2,3) // [1,2,3]
10. 展开数组
const arr = ['foo', 'bar', 'baz']
console.log.apply(console, arr) // foo bar baz
console.log(...arr) // foo bar baz
11. 箭头函数
const inc = n => n + 1
console.log(inc(1)) // 2
const sum = (a, b) => {
return a + b
}
console.log(sum(1,2))
- 箭头函数不会改变this指向,this为上层作用域的this(声明箭头函数所在的this指向)
const parson = {
name: 'tom',
sayHi: function () {
console.log(`hi, my name is ${this.name}`)
},
sayHiAnyc: function (){
setTimeout(function(){
console.log(`sayHiAsync: hi my name ins ${this.name}`)
})
},
say: () => {
console.log(`hi my name is ${this.name}`)
},
sayHiAsync2: () => {
setTimeout(()=>{
console.log(`sayHiAsync2: hi my name is ${this.name}`)
})
}
}
12. 对象字面量增强
-
属性名和属性值相同时,可以省略,只写属性名
-
对象方法可以直接写函数形式,method(){} a: function () { }
-
使用方括号的方式计算动态属性名
const bar = 111
const obj = {
foo: 123,
// bar: bar
bar,
// method:function(){
// console.log(`method: ${this}`)
// },
methods(){ // 直接写方法 同上面的冒号属性
console.log(`method: ${this}`)
}
[Math.radom()]:123 // 计算属性名
}
13. 对象扩展方法
- Object.assign(target,source): 将多个源对象中的属性赋值到一个目标对象中
// Object.assign 用第二个参数的对象属性覆盖第一个参数的对象,返回结果为第一个对象
const source1 = {
a: 'aaa',
b: 'bbb'
}
const source2 = {
a:'source2a',
c:'ccc'
}
const target = {
a:'targeta',
b:'targetb'
}
const result = Object.assign(target,source1,source2)
console.log(result)
function fun(obj) {
// obj.name = 'function.obj'
// console.log(obj)
const funObj = Object.assign({}, obj)
funObj.name = 'function.obj'
console.log(funObj)
}
const obj = {
name: 'global obj'
}
fun(obj)
console.log(obj)
- Object.is 对===的比较,+0不等于-0, NAN等于NAN
console.log(
0 === false, // false
0 == false, // true
+0 ===-0, // true
NaN === NaN, // false
Object.is(+0, -0), // false
Object.is(NaN, NaN) // true
)
14. 代理对像
ES5中有一个Object.defineProperty,Vue2就是通过这个实现数据双向绑定
ES6提供了Proxy,可以监视对象的读写过程,Vue3.0通过Proxy实现数据绑定
// 监视对象中某个属性的读写
const person = {
name: 'zoe',
age: 18
}
person.abvc
// 第一个参数是需要代理的对象
const personProxy = new Proxy(person, {
// 监听获取属性
// target 所监听的对象, property 外接访问的属性名
// return 作为外接访问的返回值
get(target, property) {
// console.log(target, property);
// return 1
return property in target ? target[property] : 'umderfind'
},
// set 监听设置属性
set(target, property, value) {
if(property === 'age') {
if(!Number.isInteger(value)) {
throw Error(`${value} is not init`)
}
}
target[property] = value
console.log(target, property, value);
}
})
personProxy.age = 10
console.log(personProxy.name);
15.Object.definrProperty 与 Proxy 的区别
- defineProperty 只能监视属性的读写,proxy 能监视到更多对象操作,例如delet 或者 对象方法的调用
const person = {
name: 'zoe',
age: 18
}
const personProty = new Proxy(person,{
deleteProperty(target, property){
console.log(target, property);
delete target[property]
}
})
delete personProty.age
console.log(personProty);
// =======================================
- 对数组更好的支持
const list = [1,2,3,4]
const listProxy = new Proxy(list,{
set(target,property,value) {
target[property] = value
console.log(target,property,value);
return true
}
})
listProxy.push(5)
- proxy 是以非侵入的方式监管了对象的读写
16. Set 数据结构
-
类似数组一样的结构,但是set 结构中的成员是不重复的
-
add() 用于增加set 数据,可以链式调用
-
size 获取 set 数据解构的长度
-
has ()判断集合是否存在某个特定的值
-
delete ()用于删除集合中某个特定的值
-
clear()清除集合中的数据
const s = new Set()
s.add(1).add(2).add(3)
console.log(s);
console.log(s.has(1));
s.delete(1)
console.log(s);
s.clear()
console.log(s);
// 常用于数组去重
const arr = [1,1,2,2,3,3,4]
// const result = Array.from( new Set(arr))
const result = [...new Set(arr)]
console.log(result);
17.Map 数据结构
-
当我门为对象增加属性时,如果属性不是字符串格式的,我们对象内部会调用toString 方法 将键转换成字符串作为键值
-
键值对集合,用来映射两个任意键值对之间的关系
-
Set () 设置数据
-
Get () 获取数据
-
Has () 判断某个键是否存在
-
Delete () 删除某个键
-
Clear () 清空所有的键值
// const obj = {}
// obj[true] = '123'
// obj[123] = '123'
// obj[{a: 1}] = '123'
// console.log(Object.keys(obj)); // 此时 对象作为键时 出现问题 [ '123', 'true', '[object Object]' ]
const m = new Map()
const tom = {name: 'tom'}
m.set(tom, '123')
console.log(m);
console.log(m.get(tom));
console.log(m.has(tom));
-
map 和对象的区别就是
-
map 可以使用任意数据结构作为键
-
对象只能用字符串作为键
18. Symbol 数据结构,一种全新的原始数据类型
- 表示独一无二的值
- 为对象添加独一无二的属性名
- 设置对象的私有属性成员
const s = Symbol()
console.log(typeof s);
// 创建的每个值都是唯一的
console.log(Symbol() === Symbol());
// 允许传递一个字符串,作为symbol 对象的描述文本
console.log(Symbol('a'));
console.log(Symbol('b'));
console.log(Symbol('c'));
console.log(Symbol('d'));
// 对象可以使用 symbol 属性作为对象的属性值
const obj = {}
obj[Symbol()] = '123'
obj[Symbol()] = '345'
console.log(obj);
// 也可以使用对象字面量形式 直接在对象中使用symbol 作为我们对象的属性名
const obj = {
[Symbol()]: 123
}
console.log(obj);
// 模拟对象的私有成员
// a.js============
const name = Symbol()
const person = {
[name]: 123,
say() {
console.log(this[name]);
}
}
// b.js============
console.log(person[Symbol()]); // underfind
person.say()
19. For of
const arr = [1,2,3]
for (const item of arr) {
console.log(item) // 1,2,3
}
arr.forEach(item =>{
console.log(item) // 1,2,3
})
// for of 比 forEach 的好处是 for of 可以随时终止循环
// forEach 是无法终止遍历的
for (const item of arr) {
console.log(item)
if(item > 10) {
break
}
}
// set map 都可以使用for of 遍历
const s= new Set([1,2])
for (const item of s) {
console.log(item) // 1, 2
}
const m = new Map()
m.set('a',123)
m.set('b',123)
for(const item of m) {
console.log(item) // [a,123],[b,123]
}
// 配合数组结构方式
for(const [key, value] of m) {
console.log(key, value)
}
// for of 不能遍历对象 因为对象是不可迭代的
const obj = {a:123, b:345}
for(const item of obj) {
console.log(item) // 此时会报错
}