Js核心原理精讲

1.数据类型

基础类型存储在栈内存,引用类型存储在堆内存
在这里插入图片描述

2.数据类型检查

  1. typeof
    基本数据类型null会判断为Object
    引用数据类型 Object,除了 function 会判断为 OK 以外,其余都是 ‘object’.
  2. instanceof
    instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型;
  3. Object.prototype.toString
    对于 Object 对象,直接调用 toString() 就能返回 [object Object];而对于其他对象,则需要通过 call 来调用,才能返回正确的类型信息。
function myInstanceof(left, right) {
   
  // 这里先用typeof来判断基础数据类型,如果是,直接返回false
  if(typeof left !== 'object' || left === null) return false;
  // getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
  let proto = Object.getPrototypeOf(left);
  while(proto) {
                     //循环往下寻找,直到找到相同的原型对象
    if(proto === right.prototype) return true;//找到相同原型对象,返回true
    proto = Object.getPrototypeof(proto);
    }
  return false;
}
// 验证一下自己实现的myInstanceof是否OK
console.log(myInstanceof(new Number(123), Number));    // true
console.log(myInstanceof(123, Number));                // false

全局通用类型判断方法

function getType(obj){
   
  let type  = typeof obj;
  if (type !== "object") {
       // 先进行typeof判断,如果是基础数据类型,直接返回
    return type;
  }
  // 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
  return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');  // 注意正则中间有个空格
}

3.深浅拷贝

浅拷贝

object.assign、扩展运算符、concat、slice
手写:

const shallowClone = (target) => {
   
  if (typeof target === 'object' && target !== null) {
   
    const cloneTarget = Array.isArray(target) ? []: {
   };
    for (let prop in target) {
   
      if (target.hasOwnProperty(prop)) {
     
          cloneTarget[prop] = target[prop];
      }
    }
    return cloneTarget;
  } else {
   
    return target;
  }
}

深拷贝

1.JSON.parse(JSON.stringfy())
缺点:

  1. 拷贝的对象的值中如果有函数、undefined、symbol 这几种类型,经过 JSON.stringify 序列化之后的字符串中这个键值对会消失;
  2. 拷贝 Date 引用类型会变成字符串;
  3. 无法拷贝不可枚举的属性;
  4. 无法拷贝对象的原型链;
  5. 拷贝 RegExp 引用类型会变成空对象;
  6. 对象中含有 NaN、Infinity 以及 -Infinity,JSON 序列化的结果会变成 null;
  7. 无法拷贝对象的循环引用,即对象成环 (obj[key] = obj)。

2.手写递归

let deepClone = (target) => {
   
    if (typeof target === 'object' && target !== null) {
   
        let cloneTarget = Array.isArray(target) ? [] : {
   };
        for (let key in target) {
   
            if (target.hasOwnProperty(key)) {
   
                cloneTarget[key] = deepClone(target[key]);
            }
        }
        return cloneTarget;
    } else {
   
        return target;
    }
}

缺点:

  1. 不能拷贝不可遍历属性
  2. 对Date、RegExp、Error、Function 这样的引用类型并不能正确地拷贝;
  3. 循环引用没有解决

3.递归进阶版

  1. 针对能够遍历对象的不可枚举属性以及 Symbol 类型,我们可以使用 Reflect.ownKeys 方法;
  2. 当参数为 Date、RegExp 类型,则直接生成一个新的实例返回;
  3. 利用 Object 的 getOwnPropertyDescriptors 方法可以获得对象的所有属性,以及对应的特性,顺便结合 Object 的 create 方法创建一个新对象,并继承传入原对象的原型链;
  4. 利用 WeakMap 类型作为 Hash 表,因为 WeakMap 是弱引用类型,可以有效防止内存泄漏(你可以关注一下 Map 和 weakMap 的关键区别,这里要用 weakMap),作为检测循环引用很有帮助,如果存在循环,则引用直接返回 WeakMap 存储的值。
const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)

let deepClonePlus = (target, hash = new WeakMap()) => {
   
    if (target instanceof Date) return new Date(target);
    if (target instanceof RegExp) return new RegExp(target);

    if (hash.has(target)) return hash.get(target);

    let allDesc = Object.getOwnPropertyDescriptors(target);
    let cloneTarget = Object.create(Object.getPrototypeOf(target), allDesc);

    hash.set(target, cloneTarget);
    for (let key of Reflect.ownKeys(target)) {
   
        cloneTarget[key] = (isComplexDataType(target[key]) && typeof target[key] !== 'function') ? deepClonePlus(target[key], hash) : target[key];
    }
    return cloneTarget;
}

4. 6种继承方式

在这里插入图片描述

5. new、apply、call、bind

function _new(ctor, ...args) {
   
    if(typeof ctor !== 'function'){
   
        throw "ctor must be a function"
    }
    let obj = {
   }<
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值