常见的手写js

new

new 操作符

new 的原理是什么?通过 new 的方式创建对象和通过字面量创建有什么区别?

在调用new的过程中会发生四件操作

  1. 新建了一个对象
  2. 新对象链接到原型对象上
  3. 绑定 this
  4. 返回这个新对象
1
2
3
4
5
6
function myNew(fn,...args){
let obj = {};
obj.__proto__ = fn.prototype
fn.apply(obj,args)
return obj
}

instanceof 原理

instanceof 的原理是什么?

instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype

1
2
3
4
5
6
7
8
9
function myInstanceof(left, right) {
let prototype = right.prototype;
left = left.__proto__;
while (true) {
if (left === null || left === undefined) return false;
if (prototype === left) return true;
left = left.__proto__;
}
}

分析:

  • 首先获取类型的原型
  • 然后获得对象的原型
  • 然后一直循环判断对象的原型是否等于类型的原型,直到对象原型为 null,因为原型链最终为 null

防抖与节流

之前看到一个很形象的比喻。节流防抖就好比乘电梯,比如 delay 是 10 秒,防抖就是电梯每进来一个人就要等 10 秒再运行,而节流就是电梯保证每
10 秒可以运行一次

手写 call、apply、bind

call 实现

1
2
3
4
5
6
7
8
Function.prototype.myCall = function (context, ...args) {
context = context || globalThis; // 没有传入上下文,默认指向全局对象
const mySymbol = Symbol('mySymbol') // 避免和上下文的属性名冲突
context[mySymbol] = this // 把调用的函数赋值给上下文的属性
const result = context[mySymbol](...args) // 调用函数
delete context[mySymbol] // 删除上下文的属性
return result // 返回函数的执行结果
}

apply 实现

1
2
3
4
5
6
7
8
9

Function.prototype.myApply = function (context, args) {
context = context || globalThis;
const mySymbol = Symbol('mySymbol')
context[mySymbol] = this
const result = context[mySymbol](...args)
delete context[mySymbol]
return result
}

bind 实现

1
2
3
4
5
6
Funtion.prototype.myBind = function (context, ...args) {
const fn = this
return function (...newArgs) {
return fn.apply(context, args.concat(newArgs))
}
}

常见的手写js
https://zouhualu.github.io/20220528/常见的手写js/
作者
花鹿
发布于
2022年5月28日
许可协议