目录
作用域:最佳实践,不用var
解构
模板字符串
参数默认值,严格等于undefined
... 运算符
箭头函数,没有自己的this
Proxy
Reflect:(统一提供一套用于操作对象的方法)
Promise TODO
class 类 TODO 与 new Obj() 的区别
Set 数据结构:最常用来数组去重。。。。
Map 数据结构
Symbol
for ... of (iterable接口)
迭代器的意义:对外提供统一遍历接口
生成器 Generator
Esmodule TODO
ES2016
ES2017
async await TODO
测试执行环境:nodejs 工具:nodemon
var ele = [{},{},{}]
for(var i=0;i<3;i++){
ele[i].onclick = function(){
console.log(i)
}
}
ele[0].onclick() // 此时打印的都是三
// 用闭包解决作用域的问题
var ele = [{},{},{}]
for(var i=0;i<3;i++){
ele[i].onclick = (function(i){
return function(){
console.log(i)
}
})(i)
}
ele[0].onclick()
// 用块级作用域
var ele = [{},{},{}]
for(let i=0;i<3;i++){
ele[i].onclick = function(){
console.log(i)
}
}
ele[0].onclick()
const 在 let 的基础上多了一个只读。不能改变内存地址,可以改变内存数据
赋值默认值:
const {foo = ''} = obj; // 默认值
const {code:otherCode} = res; // 设置别名
[b,a] = [a,b] // 交替变量
const obj = {b:{foo:1}}
const {a:{foo} ={}/** 假设没有解构到 a,此时的foo、也是会错的 */} = obj;
console.log(foo) // foo 1
// console.log(a) // a is not defined
const msg = `name ${1+2}`;
// 带标签的模板字符串 使用场景:实现模板引擎
const name = 'tom'
const gender = false
function myTagFunc(strings,...args){
// strings 获取到的除占位符以外的数组 [ 'hey,', ' is a ', '' ]
// args 获取到的是占位符的数组
console.log(strings,args)
}
const result = myTagFunc`hey,${name} is a ${gender}`
函数对模板字符串进行处理
function safe(strArr) {
let res = '';
console.log(arguments);
for(var i=0, len = strArr.length; i < len; i++) {
res += strArr[i].replace(//g, '>');
if(i < arguments.length -1) {
res += arguments[i + 1];
}
}
return res;
}
let name = 'Joh';
var result = safe`hello ${name}
`;
console.log(result); // <p>hello Joh</p>
字符串查找
function a(bar){
var foo = bar || 0; // 此时如果是 false或者0;就会赋值为0
}
function b(bar = 0){
console.log(bar)
}
const arr = ['foo','bar','baz'];
console.log.appy(console,arr)
console.log(...arr)
this : 箭头函数不会改变this的指向。箭头函数的this是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this就继承了定义函数的对象。
const obj = {
name:'tom',
sayAsync:function(){
setTimeout(()=>{
console.log(this.name) // 继承了sayAsync
})
}
}
obj.sayAsync() // tom
function newObj(){
this.a = 2;
return ()=>{ // 继承了newObj
console.log(this.a)
}
}
const b = newObj()
b() // 2
const person = {
name:'xx',
age:20
}
// 代理模式 TODO:代理模式在前端的应用,vue3的数据响应,替代vue2的defineProperty
const personProxy = new Proxy(person,{
get(target,property){
console.log(target,property)
return 'sss'
},
set(target,property,value){
target[property] = 200
}
})
console.log(personProxy.name) //sss
personProxy.age = 2000
console.log(personProxy.age) //200
const list = [];
const listProxy = new Proxy(list,{
set(target,property,value){
console.log('set',property,value)
target[property] = value;
return 'greater'
}
})
listProxy.push(1);
console.log(listProxy) // [1]
Reflect 成员方法就是Proxy处理对象的默认实现
const person = {
name:'xx',
age:20
}
// 如果没有定义get,相当于默认为以下操作
const personProxy = new Proxy(person,{
get(target,property){
return Reflect.get(target,property)
}
})
const obj = {
name:'xx',
age:20
}
// console.log('name' in obj)
// console.log(delete obj['age'] )
// console.log(Object.keys(obj))
console.log(Reflect.has(obj,'name'))
console.log(Reflect.deleteProperty(obj,'age'))
console.log(Reflect.ownKeys(obj))
实例方法,静态方法
const result = [...new Set([1,2,3,1,2])]
相对{}能够以对象作为Key.
和set一样有 foreach , for ... of 方法
每次创建都是唯一值 Symbol
作为Key值独一无二,私有成员
const name = Symbol()
const person = {
[name]:'xx',
say(){
console.log(this[name])
}
}
// other.js
person.say()
通过for in 方法或者 Object.keys ,JSON.stringify()是拿不到这个属性名的
可以通过 Object.getOwnPropertySymbols(obj)拿到
Symbol.for('foo') = Symbol.for('foo') // todo 这样做为何不直接 'foo' === 'foo'
代替foreach 可终止循环
遍历Map
object 不可被迭代,使用for of 会报错,因为他没有实现iterable
const m = new Map();
m.set('foo','123')
m.set('bar','456')
for(const [key,value] of m){
console.log(key,value)
}
const m = new Map();
m.set('foo','123')
m.set('bar','456')
const iterator = m[Symbol.iterator]()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
// { value: [ 'foo', '123' ], done: false }
// { value: [ 'bar', '456' ], done: false }
// { value: undefined, done: true }
// { value: undefined, done: true }
// { value: undefined, done: true }
实现迭代器:
// 迭代器模式
const obj = {
store:['foo','bar'],
[Symbol.iterator]:function(){
let index = 0;
const self = this;
return {
next:function(){
const result = {
value:self.store[index],
done:index >= self.store.length
}
index++
return result
}
}
}
}
for(const item of obj){
console.log('循环体',item)
}
const todos = {
life:['吃饭','睡觉','打豆豆'],
learn:['语文','数学','英语'],
work:['摸鱼'],
each: function(callback){
const all = [].concat(this.life,this.learn,this.work)
for(const item of all){
callback(item)
}
},
[Symbol.iterator]: function(){
const all = [...this.life,...this.learn,...this.work]
let index = 0;
return {
next:function(){
return {
value:all[index],
done: index++ >= all.length
}
}
}
}
}
for(const item of todos){
console.log('循环体',item)
}
返回一个生成器对象
// 案例1: 发号器
function *createIdMaker(){
let id = 1;
while(true){ // 不需要担心死循环的问题
yield id++
}
}
const generator = createIdMaker()
console.log(generator.next())
console.log(generator.next())
console.log(generator.next())
// 改进 函数实现iterator方法
const todos = {
life:['吃饭','睡觉','打豆豆'],
learn:['语文','数学','英语'],
work:['摸鱼'],
each: function(callback){
const all = [].concat(this.life,this.learn,this.work)
for(const item of all){
callback(item)
}
},
[Symbol.iterator]: function *(){
const all = [...this.life,...this.learn,...this.work]
for(const item of all){
yield item
}
}
}
for(const item of todos){
console.log('循环体',item)
}
Array的includes
2**2 === Math.pow(2,2)
Object.values(obj)
Obejct.entries(obj)
对象转Map
const obj = {a:1}
console.log(new Map(Object.entries(obj)))
String.prototype.padStart
String.prototype.padEnd
const books = {
html:5,
js:6,
javascript:12
}
for (const [name,count] of Object.entries(books)) {
console.log(`${name.padEnd(16,'-')}|${count.toString().padStart(3,'0')}}`)
}
html------------|005
js--------------|006
javascript------|012