一、js手撕
实现一个判断具体数据类型的函数
function checkType(val){
return Object.prototype.toString.call(val).slice(8,-1).toLowerCase()
}
手写深拷贝
function deepClone(obj){
if(obj === null || typeof obj!= 'object')
return obj
const clone = Array.isArray(obj)? []: {}
for(const key in obj){
if(Object.hasOwnProperty.call(obj, key))
clone[key] = deepCoppy(obj[key])
}
return clone
}
手写防抖 和 节流
- 防抖(回城):对于连续快速触发,只执行最后一次
function debounce(fun, delay){
let timer = null
return function(...args){
if(timer)
clearTimeout(timer)
timer = setTimeout(()=>{
fun.call(this, ...args)
},delay)
}
}
- 节流(技能冷却):在规定时间内不会重复触发回调,只有大于这个时间间隔才会触发
function throttle(fun, delay){
let timer = null
return function(...args){
if(!timer){
timer = setTimeout(()=>{
fun.call(this, ...args)
timer = null
},delay)
}
}
}
手写原型继承、组合继承、寄生组合继承、ES6继承
| 原型继承 |
组合继承 |
寄生组合继承 |
ES6继承 |
| 缺点:属性和方法无法私有化 |
缺点:每次创建子类实例,都执行了两次父类构造函数 |
缺点:书写麻烦 |
缺点:无 |
function Animal(){}
Animal.prototype.eat = function(){
console.log('eating')
}
function Dog(){}
Dog.prototype = new Animal()
Dog.prototype.bark = function(){
console.log('barking')
}
const myDog = new Dog()
myDog.eat()
myDog.bark()
|
function Animal(name){
this.name = name
}
Animal.prototype.eat = function(){
console.log(`${this.name} is eating`)
}
function Dog(name, type){
Animal.call(this, name)
this.type = type
}
Dog.prototype = new Animal()
Dog.prototype.constructor = Dog
Dog.prototype.bark = function(){
console.log(`${this.type} is barking`)
}
const myDog = new Dog('豆豆', '金毛')
myDog.eat()
myDog.bark()
|
function Animal(name){
this.name = name
}
Animal.prototype.eat = function(){
console.log(`${this.name} is eating`)
}
function Dog(name, type){
Animal.call(this, name)
this.type = type
}
Dog.prototype = Object.create(Animal.prototype)
Dog.prototype.constructor = Dog
Dog.prototype.bark = function(){
console.log(`${this.type} is barking`)
}
const myDog = new Dog('豆豆', '金毛')
myDog.eat()
myDog.bark()
|
class Animal{
constructor(name){
this.name = name
}
eat(){
console.log(`${this.name} is eating`)
}
}
class Dog extends Animal{
constructor(name, type){
super(name)
this.type = type
}
bark(){
console.log(`${this.type} is barking`)
}
}
const myDog = new Dog('豆豆', '金毛')
myDog.eat()
myDog.bark()
|
手写发布订阅模式(观察者模式)
class Subject {
constructor() {
this.observers = []
}
addObserver(observer) {
this.observers.push(observer)
}
removeObserver(observer) {
const index = this.observers.indexOf(observer)
if (index != -1) {
this.observers.splice(index, 1)
}
}
notify(data) {
this.observers.forEach(observer => {
observer.update(data, observer.name)
})
}
}
class Observer {
constructor(name) {
this.name = name
}
update(data, observer) {
console.log(`Received data: ${data} ${observer}`)
}
}
const sub = new Subject()
const obs1 = new Observer('observer1')
const obs2 = new Observer('observer2')
sub.addObserver(obs1)
sub.addObserver(obs2)
sub.notify('Hello')
手写Promise.all()串行
手写Promise.all()并行
手写Promise.race()
手写Promise.allSelected()
手写async和await
手写instanceof
手写数组扁平
手写数组去重
手写数组交集
手写数组并集
手写数组差集
手写new
手写call()
手写apply()
手写bind()
手写快排
手写二分查找
手写下划线转小驼峰 get_element_by_id -> getElementById
手写url转对象
回调函数实现循环打印红黄绿 红(2s) -> 黄(1s) -> 绿(3s)
promise实现循环打印红黄绿 红(2s) -> 黄(1s) -> 绿(3s)
async await实现循环打印红黄绿 红(2s) -> 黄(1s) -> 绿(3s)
遍历dom节点
对象数组转树
Promise应用场景手写题
二、判断输出