手撕js方法的实现
学的越深入,越对js里面那些封装好的方法充满好奇。实际用的时候,这些原型上的方法也是真的香,帮我们把代码精简了几个档次。比如new,bind,map等。了解掌握这些原理也能帮助自己对js的理解。
1.new
先从简单的来。平时用的new,能帮我们把一个构造函数实例化。先贴代码
// new是个函数, 里面一定有一个对象参数,最后抛出也是一个对象
function myNew(arguments) {
// 创建一个实例对象
let obj = {}
// 取到外部 传进来的构造器
let Constructor = Array.prototype.shift.call(arguments)
// 实现继承,要实例可以访问构造器的属性,相当于实例化的隐式原型指向构造函数的显示原型
obj.__proto__ = Constructor.prototype
// 调用构造器,改变其this指向到实例
let ret = Constructor.apply(obj, arguments)
return typeof ret === 'object' && ret !== null ? ret : obj
}
// 精简点也方便理解的版本
function myNew(fun) {
return function () {
let obj = {
__proto__: fun.prototype
}
fun.call(obj, ...arguments)
return obj
}
}
2.object.create
这个应该比new更简单些,只要知道平时这个方法的运用场景就能手写的出来,和上面一样来两种。
function create( object ) {
if (typeof obj != 'object') { //null 进行typeof 也是 null
throw TypeError
}
// 只要将创建出来的隐式原型指向 参数即可。
let obj = object
obj.__proto__ = object
return obj
}
// 一样是精简点的,但没进行参数判断,不妨碍理解。
function create( object ) {
return { __proto__: object}
}
3.call
常用的三种改变this作用域的方法,先来个call吧。
Function.prototype.myCall = function (context) {
// this指向调用call的对象
if (typeof this !== 'function') {
// 调用call的不是函数
throw new TypeError('Error')
}
const fn = Symbol('fn')
const args = [...arguments].slice[1]
context = context || window
// 将调用call函数的对象添加到context属性中
context[fn] = this
// 执行该属性
const result = context[fn](...args)
// 删除该属性
delete context[fn]
// 返回执行结果
return result
}
// 精简没其他参数
Function.prototype.myCall = function (obj) {
//给传入的作用域里添加调用call这个函数,这样函数指向的便是参数里的作用域,然后执行,执行完在删除
obj.fn = this; // 此时this就是函数fn
obj.fn(); // 执行fn
delete obj.fn; //删除fn
};
4.未完待续...
js可以实现的方法有点多,远远没有结束,先码住三个,日后在写。
转载自:https://juejin.cn/post/6889413297720950792