写几篇关于js部分的知识点,之前已经写过一篇了,但是因为js的内容比较多,所以慢慢的更新,之前的第一篇的文章篇幅比较大,导致很多人可能都不怎么看的完,所以后面的关于js方面的知识点,一篇文章就几个知识点就可以了,不用那么长,没啥实质性的作用,也不太好记,今天主要说一下关于对象,generator,symbol等知识点,后续的再说吧。
let o = new Object()
o.name = 'jim'
o.func = function() {
console.log(o.name)
}
o.func()
let c = {
name: 'jim',
func: function() {
console.log(c.name)
}
}
let o4 = Object.create(c)
c.func()
let o1 = {
name: 'jim',
func: function() {
console.log(o1.name)
}
}
o1.func()
function creatObj(params) {
let o = new Object()
o.name = params
o.func = function() {
console.log(o.name)
}
return o
}
let o2 = new creatObj('jim')
o2.func()
//缺点是:
console.log(o2 instanceof creatObj) //false
function Co(params) {
this.name = params
this.func = function() {
console.log(this.name)
}
}
let o3 = new Co('jim')
o3.func()
console.log(o3 instanceof Co) //true
class Coj {
constructor(params) {
this.name = params
this.func = function() {
console.log(this.name)
}
}
}
let o5 = new Coj('jim')
o5.func()
console.log(o5 instanceof Coj) //true
js优化的方法中有一个不得不提的方式就是防抖和节流,今天我们就简单的说一下他的工作流程,首先说一下节流
- 节流
节流字面意思就是节省流动,这里的流动映射到js优化中可以简单的理解为操作,节流就是减少操作的进行,比如我们滚动页面的时候,如果不做节流的操作,假设我们滚动一次就请求一次函数,函数单一的还好, 如果函数本身就执行的比较麻烦的函数,这个时候我们的页面可能会出现卡死的情况,cpu也吃不消,这个时候我们需要的是,滚动的时候我们加个时间控制,不管你滚动的多快只要不超过我们设置的时间间隔,我都不给你执行即可,这个过程就是节流,那么代码实现就是通过一个闭包加上时间延迟进行实现。
// 函数节流 let f = () => { console.log('this is option logs') } function showLog(func, delay) { let timer return function() { let that = this let arg = arguments if (timer) { return } timer = setTimeout(function() { func.call(that, arg) timer = null }, delay) } } window.addEventListener('resize', showLog(f, 2000))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
这里不管你窗口放大缩小的多快,只要不超过2s,2s内你不停的执行我也只会2s执行一次,不会再不停地执行
- 防抖
防抖顾名思义就是防止抖动,点击一次时间之后进行计时,这个时间内,不进行再次操作,我们就执行函数,如果一直点击,时间就会一直被重置,那么函数就一直不会被执行,这个就是防抖的一个流程,这样做的好处就是比如付款的时候,不停地点击,可能会出现反复付款的情况,那么这个时候很容易出问题,防抖很大一部分应用场景是页面滚动和表单提交,所以这里写一个简单的demo
const btn = document.querySelector('button') let c = () => { console.log('我被点击了') } let f = (c, dealy) => { let timer return function() { let that = this let arg = arguments clearTimeout(timer) timer = setTimeout(function() { c.apply(that, arg) }, dealy); } } btn.addEventListener('click', f(c, 2000))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
这样在2s内不管你点击多少次,我都只会在我的计时结束之后执行一次,就起到了防抖的效果。
一个永远都不会重复相等的基本数据类型,介绍完毕
let i = Symbol() let j = Symbol() // console.log(i === j) //false
- 1
- 2
- 3
- 添加描述
// 添加描述 let s = Symbol('this is symbol') console.log(s) //Symbol(this is symbol) console.log(s.description) //this is symbol
- 1
- 2
- 3
- 4
- 不同的定义方式,获取描述信息的方式相同
let a = Symbol.for('this') let b = Symbol.for('this') console.log(a === b) //true //获取描述信息方式改变 console.log(Symbol.keyFor(a)) // 这个只能是全局的for定义才是可以的, 普通的定义方式是没办法获取的
- 1
- 2
- 3
- 4
- 5
使用for来进行定义 使用for进行定义的时候,其实是在全局进行保存了一个值,这个时候我们重新定义了一个新的值的话,那么重要描述信息是一致的,就被当做一个同一个
- 使用场景举例
let obj = { 'jim': 'my name is jim', 'jim': 'my name is other jim' } console.log(obj) //{ jim: 'my name is other jim' } 后面的会覆盖前面的
- 1
- 2
- 3
- 4
- 5
尝试解决
let k1 = 'jim' let k2 = 'jim' let obj1 = { k1: 'my name is jim', k2: 'my name is other jim' } console.log(obj1) //{ k1: 'my name is jim', k2: 'my name is other jim' } 很明显key值不对
- 1
- 2
- 3
- 4
- 5
- 6
- 7
let k1 = 'jim' let k2 = 'jim' let obj1 = { [k1]: 'my name is jim', [k2]: 'my name is other jim' } console.log(obj1) //{ jim: 'my name is other jim' } 后面的会覆盖前面的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
使用symbol解决
let k1 = { name: 'jim', key: Symbol('jim') } let k2 = { name: 'jim', key: Symbol('jim') } let obj1 = { [k1.key]: 'my name is jim', [k2.key]: 'my name is other jim' } console.log(obj1[k1.key]) //my name is jim console.log(obj1[k2.key]) //my name is other jim
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 获取symbol的属性
let sys = Symbol('this is symbol') let objf = { name: 'jim', [sys]: 'symbol' } for (let i in objf) { console.log(i) // name } for (let o of Object.keys(objf)) { console.log(o) //name } for (let o of Reflect.ownKeys(objf)) { console.log(o) // name Symbol(this is symbol) } for (let o of Object.getOwnPropertySymbols(objf)) { console.log(o) //Symbol(this is symbol) } let keys = Object.keys(objf).concat(Object.getOwnPropertySymbols(objf)) for (let i of keys) { console.log(i) //name Symbol(this is symbol) }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 保护属性对象的作用
let params = Symbol('this is symbol') class Info { constructor(name) { this.name = name this[params] = 'sb' } getInfo() { return `${this.name} + ${this[params]}` } } let gi = new Info('wlm') console.log(gi.getInfo()) //wlm + sb for (let i in gi) { console.log(i) //name }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
好处就是可以直接在js中写html代码,同时支持换行,插值等操作
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="content">
</div>
<script type="text/javascript">
let f = (...p) => {
for (let i of p) {
console.log(i) // 5,6,8,9,11
}
}
(() => {
let info = 'this is params'
let h2 = `这是被字面量填充进去的h1
这是被字面量填充进去的h2
这是被字面量填充进去的h3
这是一个参数:${info}`
let content = document.getElementById('content')
content.append(h2)
// f(3, 4, 5, 6, 7, 8)
let a = 5,
b = 6,
c = 8,
d = 9
// 和中间的符号没有关系
f`${a},${b},${c},${d},${a + b}` //['', ',', ',', ',', ',', '']
f`${a} + ${b} + ${c} + ${d} + ${a + b}` //['', ' + ', ' + ', ' + ', ' + ', '']
})()
</script>
</body>
</html>
今天讲一下关于Generator的知识点,很多人可能用过但是也有一部分没有用过,今天就大概说一下,首先Generator也是一个函数,只是他比较特殊,不仅仅是写法特殊,同时他的运行过程设计的也比较特殊,他可以分段执行函数,终止函数,同时他的函数执行方式也和普通函数不一样,他需要通过next进行执行,中断函数需要通过yield进行,下面我们写一段代码,感受一下:
function* gen() { yield 'jim' yield 'kim' yield 'mary' return 'tom' } let l = gen() console.log(l.next()) //{ value: 'jim', done: false } console.log(l.next()) //{ value: 'kim', done: false } console.log(l.next()) //{ value: 'mary', done: false } console.log(l.next()) //{ value: 'tom', done: true } console.log(l) //Object [Generator] {}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
特性:
- GENERATOR 用于异步编程
- es6 新出来的 可以交出函数的执行权
- 可以通过yield暂停执行状态
- return value 和 done 分别表示 属性值和执行状态 done : true 和false true 表示已经执行结束 false 表示还没有执行结束
- 通过next()进行函数的执行
generator函数之间均存在独立的作用域,互相之间不做干扰
function* count() { let n = 0 yield n++ yield n++ yield n++ return n } let cn = count() let newCn = count() console.log(cn.next()) //{ value: 0, done: false } console.log(cn.next()) //{ value: 1, done: false } console.log(newCn.next()) //{ value: 0, done: false } // 他们之间是没有任何关联的,都是独立存在的函数,每一次的变量接收函数都是全新的 console.log(cn.next()) //{ value: 2, done: false } console.log(cn.next()) //{ value: 3, done: true } // 已经执行结束 么有函数可以执行 underfined console.log(cn.next()) //{ value: undefined, done: true }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
generator函数传递参数的时候会将上一个yield的执行状态重置掉
function* pf() { let n = 0 let v = yield n + 40 console.log('v=' + v) //v=90 yield n++ console.log('n=' + n) //n=1 yield n++ console.log('n=' + n) //n=2 yield n++ yield n++ return n } let p = pf() console.log(p.next()) //{ value: 40, done: false } p.next(90) console.log(p.next()) //{ value: 1, done: false } console.log(p.next()) //{ value: 2, done: false } console.log(p.next()) //{ value: 3, done: false } console.log(p.next()) //{ value: 4, done: true }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
可以看出 上面当我们传递一个90进去的时候,发现并没有发生相加的情况,因为此时的n + 40的状态已经被参数覆盖了,也就是说相加的操作已经不存在了,所以这里是覆盖的操作
强调一下,这篇文章不是水文,就是单纯的想要将这些知识点总结一下给你们,毕竟没一个知识点都是可以单独拿出来写的,但是写到一篇文章里面这样你们就不用移步到别的地方了,这篇文章也算是对前面js高级部分没有总结完的做一个补充吧,后续再有的话,我会继续更新的。