目录
ES6
防抖
节流
防抖、节流应用
改变this
call
typeof this !== 'function'
context = context || window
context._this = this
delete context._this
bind: return _this.apply(context, [...arguments].slice(1));
深拷贝
!arr|| arr == null || typeof arr != 'object'
arr instanceof Array ? [] : {}
for (const key in arr)
result[key] = cloneDeep(arr[key])
setTimeout()
倒计时
setTimeout模拟实现setInterval
setInterval模拟实现setTimeout
new :Fn=[...arguments].shift()
*寄生组合式继承:call,create,constructor
Object.defineProperty(obj, prop, descriptor)
Object.create
Object.freeze
Object for of
*instance of
算法
合法的URL
千位分割:num.slice(render, len).match(/\d{3}/g).join(',')
触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,会重计算函数执行时间。
function debounce(fun,time) {
let flag // 定义状态
return function () {
clearTimeout(flag)// 在执行之前 清除 定时器的 flag 不让他执行
flag = setTimeout(() => {
fun.call(this,arguments)//拿到正确的this对象,即事件发生的dom
}, time)
}
}
连续触发事件但是在 n 秒中只执行一次函数。两种方式可以实现,分别是时间戳版和定时器版。
function throttle(fun, time) {
let flag // 定义一个空状态
return function () { // 内部函数访问外部函数形成闭包
if (!flag) { // 状态为空执行
flag = setTimeout(() => {
fns.apply(this, arguments) // 改变this指向 把 event 事件对象传出去
flag = null // 状态为空
}, time)
}
}
}
防止某一时间频繁触发
// 给function的原型上面添加一个 _call 方法
Function.prototype._call = function (context) {
// 判断调用者是否是一个函数 this 就是调用者
if (typeof this !== 'function') {
throw new TypeError('what is to be a function')
}
// 如果有 context 传参就是传参者 没有就是window
context = context || window
// 保存当前调用的函数
context._this = this
// 截取传过来的参数
/*
arguments
a: 1
fn: ƒ fns()
*/
// 通过 slice 来截取传过来的参数
const local = [...arguments].slice(1)
// 传入参数调用函数
let result = context._this(...local)
// 删属性
delete context._this
return result
}
let obj = { a: 1 }
function fns(a, b) {
console.log(a, b);
console.log(this)
}
fns._call(obj, 23, 555)
function cloneDeep(arr = {}) {
// 终止递归
if (!arr|| arr == null || typeof arr != 'object' ) return arr
// 用 instanceof 判断原型链上是否有该类型的原型 是 Array => [] ! Arrays =>{}
let result=arr instanceof Array ? [] : {}
// forin 循环对象的key值
for (const key in arr) {
// 对象 key 赋值 result
result[key] = cloneDeep(arr[key])
}
return result
}
//返回值timeoutID是一个正整数,表示定时器的编号。
let timeoutID = scope.setTimeout(function[, delay]),//delay表示最小等待时间,真正等待时间取决于前面排队的消息
clearTimeout(timeoutID) //取消该定时器。
function timedCount() {
c -=1;
if(c===0){
clearTimeout(t);
return;
}
t = setTimeout(function() {
timedCount()
}, 1000);
}
// 使用闭包实现
function mySetInterval(fn, t) {
let timer = null;
function interval() {
fn();
timer = setTimeout(interval, t);
}
interval();
return {
// cancel用来清除定时器
cancel() {
clearTimeout(timer);
}
};
}
function mySetTimeout(fn, time) {
let timer = setInterval(() => {
clearInterval(timer);
fn();
}, time);
}
// 使用
mySetTimeout(() => {
console.log(1);
}, 2000);
"_new"函数,该函数会返回一个对象,
该对象的构造函数为函数参数、原型对象为函数参数的原型,核心步骤有:
const _new = function() {
const object1 = {}
const Fn = [...arguments].shift()
object1.__proto__ = Fn.prototype
const object2 = Fn.apply(object1, arguments)
return object2 instanceof Object ? object2 : object1
}
通过寄生组合式继承使"Chinese"构造函数继承于"Human"构造函数。要求如下:
1. 给"Human"构造函数的原型上添加"getName"函数,该函数返回调用该函数对象的"name"属性
2. 给"Chinese"构造函数的原型上添加"getAge"函数,该函数返回调用该函数对象的"age"属性
function Human(name) {
this.name = name
this.kingdom = 'animal'
this.color = ['yellow', 'white', 'brown', 'black']
}
Human.prototype.getName = function() {
return this.name
}
function Chinese(name,age) {
Human.call(this,name)//call函数借助”Human“的构造器来获得通用属性
this.age = age
this.color = 'yellow'
}
//返回的对象__proto__属性为对象参数的原型
Chinese.prototype = Object.create(Human.prototype)//使用现有的对象来作为新创建对象的原型
//修复"Chinese"构造函数的原型链,即自身的"constructor"属性需要指向自身
Chinese.prototype.constructor = Chinese
Chinese.prototype.getAge = function() {
return this.age
}
该函数创建一个新对象,使用现有的对象来提供新创建的对象的proto,核心步骤有:
Object.create法创建一个新对象,使用现有的对象来提供新创建的对象的proto。
const _objectCreate = proto => {
if(typeof proto !== 'object' || proto === null) return
const fn = function() {}
fn.prototype = proto
return new fn()
}
Object.freeze = writable: false + Object.seal = writable: false + Object.preventExtensions + configable: false
key:
const _objectFreeze = object => {
if(typeof object !== 'object' || object === null) {
throw new TypeError(`the ${object} is not a object`)
}
const keys = Object.getOwnPropertyNames(object);
const symbols = Object.getOwnPropertySymbols(object);
[...keys, ...symbols].forEach(key => {
Object.defineProperty(object, key, {
configurable: false,
writable: false,
})
})
Object.preventExtensions(object)
}
// 创建一个构造函数
function MyObject() {
// 为构造函数的实例对象添加两个属性
this.prop1 = 'Value 1';
this.prop2 = 'Value 2';
}
// 在原型上添加一个自定义的迭代器方法
MyObject.prototype[Symbol.iterator] = function () {
// 获取实例对象的所有属性名并存储在数组 keys 中
const keys = Object.keys(this);
let index = 0;
// 返回一个迭代器对象,包含 next 方法
return {
next: () => {
// 如果还有属性未遍历完
if (index < keys.length) {
// 获取当前属性名 key,并递增索引 index
const key = keys[index++];
// 返回包含当前属性名和对应值的对象,并设置 done 为 false 表示未遍历完
return { value: [key, this[key]], done: false };
} else {
// 如果所有属性都已遍历完,返回 done 为 true 表示遍历结束
return { done: true };
}
},
};
};
// 创建一个实例对象
const instance = new MyObject();
// 使用 for...of 遍历实例对象的属性
for (const [key, value] of instance) {
// 打印属性名和对应值
console.log(key, value);
}
const _instanceof = (target, Fn) => {
let proto = target.__proto__
let prototype = Fn.prototype
while(true) {
if(proto === Fn.prototype) return true
if(proto === null) return false
proto = proto.__proto__
}
}
const _instanceof = (target, Fn) => {
return Fn.prototype.isPrototypeOf(target);
}
URL结构一般包括协议、主机名、主机端口、路径、请求信息、哈希
https://www.bilibili.com/video/BV1F54y1N74E/?spm_id_from=333.337.search-card.all.click&vd_source=6fd32175adc98c97cd87300d3aed81ea
//开始: ^
//协议: http(s)?:\/\/
//域名: [a-zA-Z0-9]+-[a-zA-Z0-9]+|[a-zA-Z0-9]+
//顶级域名 如com cn,2-6位: [a-zA-Z]{2,6}
//端口 数字: (:\d+)?
//路径 任意字符 如 /login: (\/.+)?
//哈希 ? 和 # ,如?age=1: (\?.+)?(#.+)?
//结束: $
// https:// www.bilibili com /video/BV1F54y1N74E ?spm..
/^(http(s)?:\/\/)?(([a-zA-Z0-9]+-[a-zA-Z0-9]+|[a-zA-Z0-9]+)\.)+([a-zA-Z]{2,6})(:\d+)?(\/.+)?(\?.+)?(#.+)?$/.test(url)
const format = (n) => {
let num = n.toString() // 拿到传进来的 number 数字 进行 toString
let len = num.length // 在拿到字符串的长度
// 当传进来的结果小于 3 也就是 千位还把结果返回出去 小于3 不足以分割
if (len < 3) {
return num
} else {
let render = len % 3 //传入 number 的长度 是否能被 3 整除
if (render > 0) { // 说明不是3的整数倍
return num.slice(0, render) + ',' + num.slice(render, len).match(/\d{3}/g).join(',')
} else {
return num.slice(0, len).match(/\d{3}/g).join(',')
}
}
}
let str = format(298000)
console.log(str)