【JavaScript基础】手写instanceof、new、深拷贝、浅拷贝实现


前言

最近在看前端八股,顺便补充一下js基础,于是简单实现了一些js函数


一、instanceof实现

用途:判断引用类型数据是否为某个数据类型,只能比较引用类型数据,无法比较基本类型,基本类型比较推荐实用typeof

/**
*实现instanceof
*只检测对象,非对象无法检测,全部返回false
*/
function _instanceof(obj, target){
    //判断是否对象,或者是否为null
    if(typeof obj !== 'object' || obj === null) return false
    //获取obj的prototype
    let proto = Object.getPrototypeOf(obj)
    //obj的prototype存在
    while(proto){
        //判断是否为target的prototype
        if(proto === target.prototype) return true
        //不是则在原型链上继续获取prototype
        proto = Object.getPrototypeOf(proto)
    }
    //遍历完原型链还没有返回true 则表示类型不对 返回false
    return false
}
// 测试
console.log(_instanceof({}, Object)) // true
console.log(_instanceof([], Array)) // true
let map = new Map()
console.log(_instanceof(map, Map)); //true

二、new实现

/**
 * 实现new
 * @param {*} constructor 构造
 * @param  {...any} args  参数列表
 * @returns 创建的对象
 */
function _new(constructor, ...args){
    const obj = Object.create(constructor.prototype)
    //使用apply绑定this 传args类数组对象,
    //执行constructor构造函数方法
    let res = constructor.apply(obj, args)
     //构造函数如果没有返回值,则返回obj,否则返回res
    return typeof res === 'object' ? res : obj
}

//测试
function Test(name, age){
    this.name = name
    this.age = age
}
Test.prototype.say = function(){
    console.log(this.name, this.age)
}
Test.prototype.set = function(age){
    this.age = age
}

let test = _new(Test, '小陈', 22)
test.say() //小陈 22
test.set(222222)
test.say() //小陈 222222

三、浅拷贝实现

/**
 * 实现浅拷贝
 * @param {*} obj 
 * @returns 新对象
 */
function shallowClone(obj){
    // 判断是否为空
    if(obj === null) return obj
    // 判断是否基本数据类型
    if(typeof obj !== 'object') return obj
    // 为引用类型则创建新对象来存放
    const newObj = new obj.constructor()
    // 遍历对象
    for(let item in obj){
        // 判断该对象是否存在该属性,不包括继承属性
        if(obj.hasOwnProperty(item)) newObj[item] = obj[item]
    }
    return newObj
}

// 测试
let obj = {
    a: 1,
    name: '小陈',
    x:{
        xx: 222,
        y:[1,3,4],
        z:{
            bb: 1
        }
    }
}
let newObj = shallowClone(obj)
//修改newObj中引用类型属性,验证浅拷贝
newObj.x.z = 1
console.log(newObj) //{ a: 1, name: '小陈', x: { xx: 222, y: [ 1, 3, 4 ], z: 1 } }
console.log(obj)    //{ a: 1, name: '小陈', x: { xx: 222, y: [ 1, 3, 4 ], z: 1 } }

四、深拷贝实现

该实现为基本实现,未解决循环引用问题,解决该问题需要使用weakmap

/**
 * 实现基本深拷贝 不能解决循环引用问题 
 * @param obj 被拷贝的对象
 * @retuen 新对象
 */
function deepClone(obj){
    // 为null或undefined直接返回
    if(obj === null) return obj
    // 为Date则创建一个Date返回
    if(obj instanceof Date) return new Date(obj)
    // 基本类型直接返回
    if(typeof obj !== 'object') return obj
    // 引用类型才创建一个新对象,并递归拷贝对象里的属性
    // 使用new obj.constructor是因为该对象可能是普通对象,也可能是数组,用对象的构造方法可以创建对应的数据类型
    const newObj = new obj.constructor()
    for(let item in obj){
        // 拷贝到新对象中
        newObj[item] = deepClone(obj[item])
    }
    return newObj
}

// 测试
let obj = {
    a: 1,
    name: '小陈',
    sex: '男',
    x:[1,2,4,5],
    b:{
        xx: 'test',
        y: 1111
    }
}
let newObj = deepClone(obj)
// 修改newObj的值,看看原对象是否被影响,验证深拷贝
newObj.a = 2
console.log(newObj) //{a: 2,name: '小陈',sex: '男',x: [ 1, 2, 4, 5 ],b: { xx: 'test', y: 1111 }}
console.log(obj)    //{a: 1,name: '小陈',sex: '男',x: [ 1, 2, 4, 5 ],b: { xx: 'test', y: 1111 }}

总结

都是一些简单实现,该文章是用来记录学习实践,后续会继续更新
如果文中内容或解释有错误,欢迎指正

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值