这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
记录学了什么东西
防抖节流
防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
魔法师A在释放了火焰技能之后,第二个技能需要等待火焰消失后才能使用,若地上的火焰又找到可点燃物燃烧,则需要重新等待火焰消失方可释放技能。
节流:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
魔法师B释放技能有CD,在CD内疯狂按键也没有效果,需要等待CD冷却方能使用技能。且同一时段内只存在一个技能。
代码实现 `//防抖 function fangdou(fn, delay = 300){ let timer return function(){ if(timer){ clearTimeout(timer) } timer = setTimeout(() => { //但是考虑到fn有参数 fn() }, delay); } }
//节流 function jieliu(fn, delay = 300){ let flag = true return function(){ //开关关闭呢就跳出函数 if (!flag) return; //开关打开呢就继续倒计时 但是要关闭开关 这样下载走函数就跳出了 flag = false; timer = setTimeout(() => { fn(); flag = true; }, delay); } }`
原型、原型链
在JavaScript中是使用构造函数来新建一个对象的,每一个构造函数的内部都有一个 prototype 属性,它的属性值是一个对象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法。当使用构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针被称为对象的原型。一般来说不应该能够获取到这个值的,但是现在浏览器中都实现了 __proto__ 属性来访问这个属性,但是最好不要使用这个属性,因为它不是规范中规定的。ES5 中新增了一个 Object.getPrototypeOf() 方法,可以通过这个方法来获取对象的原型。
当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是 Object.prototype 所以这就是新建的对象为什么能够使用 toString() 等方法的原因。
指向
p.__proto__ // Person.prototype Person.prototype.__proto__ // Object.prototype p.__proto__.__proto__ //Object.prototype p.__proto__.constructor.prototype.__proto__ // Object.prototype Person.prototype.constructor.prototype.__proto__ // Object.prototype p1.__proto__.constructor // Person Person.prototype.constructor // Person
对闭包的理解
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。 比如
function A() { let a = 1 window.B = function () { console.log(a) } } A() B() // 1
闭包的用途
- 0.
return回一个函数
var n = 10
function fn(){
var n =20
function f() {
n++;
console.log(n)
}
return f
}
var x = fn()
x() // 21
复制代码
这里的 return
f,f()就是一个闭包,存在上级作用域的引用。
-
- 函数作为参数
var a = '林一一'
function foo(){
var a = 'foo'
function fo(){
console.log(a)
}
return fo
}
function f(p){
var a = 'f'
p()
}
f(foo())
/* 输出
* foo
/
复制代码
使用 return
fo返回回来,fo()就是闭包,f(foo())执行的参数就是函数fo,因为fo() 中的 a的上级作用域就是函数foo(),所以输出就是foo
-
- IIFE(自执行函数)
var n = '林一一';
(function p(){
console.log(n)
})()
/* 输出
* 林一一
/
复制代码
同样也是产生了闭包
p(),存在window下的引用n。
-
- 循环赋值
for(var i = 0; i<10; i++){
(function(j){
setTimeout(function(){
console.log(j)
}, 1000)
})(i)
}
复制代码
因为存在闭包的原因上面能依次输出1~10,闭包形成了10个互不干扰的私有作用域。将外层的自执行函数去掉后就不存在外部作用域的引用了,输出的结果就是连续的 10。为什么会连续输出10,因为 JS 是单线程的遇到异步的代码不会先执行(会入栈),等到同步的代码执行完
i++到 10时,异步代码才开始执行此时的i=10输出的都是 10。
-
- 使用回调函数就是在使用闭包
window.name = '林一一'
setTimeout(function timeHandler(){
console.log(window.name);
}, 100)
复制代码
-
- 递归