Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JS手撕(一)    类型判断、instanceof、数组去重

JS手撕(一)    类型判断、instanceof、数组去重

作者头像
赤蓝紫
发布于 2023-03-16 07:23:46
发布于 2023-03-16 07:23:46
1.8K00
代码可运行
举报
文章被收录于专栏:clzclz
运行总次数:0
代码可运行

JS手撕(一)    类型判断、instanceof、数组去重

前言

看这篇文章的小伙伴,建议看完每一节,都尝试自己手撕一遍,最好就是弄懂原理后再开始手撕(不要边看边手撕,会产生依赖),本人就是看别人的文章后手撕的(因为手撕题型记不住,还有一些大佬有很有意思的解法)

类型判断

有用过JS一段时间的小伙伴应该对typeof比较属性,我们需要进行类型判断的时候一般都会先想到它。但是呢,它有一个很大的局限性,比如如果是nullarray都会被认为是objectarray是因为是一个特殊的对象,而null则是因为JS诞生以来null的实现导致的。

所以现在就来手撕一个类型判断函数。原理就是使用Object.prototype.toString来获取具体的类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myTypeof(arg) {
  console.log(Object.prototype.toString.call(arg))
}


myTypeof(123);      // [object Number]
myTypeof('Hello');  // [object String]
myTypeof([]);       // [object Array]
myTypeof({});       // [object Object]
myTypeof(null);     // [object Null]

接着只需要把得到的字符串[object Type]后面的具体类型取出来即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myTypeof(arg) {
  return Object.prototype.toString.call(arg).slice(8, -1).toLowerCase();
}


console.log(myTypeof(123));       // number
console.log(myTypeof('Hello'));   // string
console.log(myTypeof([]));        // array
console.log(myTypeof({}));        // object
console.log(myTypeof(null));      // null

instanceof

上面已经有小小的提到的typeof,那么当然不能拉下它的好兄弟instanceof啦。

开始手撕之前,先复习一下instanceof究竟是啥。

MDN上的介绍已经很简单易懂了:instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上。原型和原型链可以看之前的详解原型链的文章。

所以只需要沿着原型链,依次判断实例的_proto_和构造函数的prototype是不是相同就行了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myInstanceof(obj, func) {
  // obj: 要检测的对象,也可以是特殊的对象,如数组
  // func:要检测的构造函数

  if (typeof func !== 'function') {
    throw new Error('第二个参数应该是构造函数');
  }


  let proto = obj.__proto__;
  let prototype = func.prototype;

  while (true) {
    if (proto === null) {
      return false;
    }

    if (proto === prototype) {
      return true;
    }

    proto = proto.__proto__;
  }
}


console.log(myInstanceof([], Array));
console.log(myInstanceof([], Object));

上面用的是__proto__来获取实例对象的原型,但是实际上,更推荐使用Object.getPrototypeOf(obj)来获取实例对象的原型

上面的代码还有有一些大问题,因为**instanceof是用来检测实例对象的**,所以我们还得去掉检测基本数据类型,如123 instanceof Number;得到的结果是false

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myInstanceof(obj, func) {
  // obj: 要检测的对象,也可以是特殊的对象,如数组
  // func:要检测的构造函数

  if (!(obj && ['object', 'function'].includes(typeof obj))) {
    // 判断这里是参考前端胖头鱼的仓库里的,比较巧妙
    return false;
  }

  if (typeof func !== 'function') {
    throw new Error('第二个参数应该是构造函数');
  }


  let proto = Object.getPrototypeOf(obj);
  let prototype = func.prototype;

  while (true) {
    if (proto === null) {
      return false;
    }

    if (proto === prototype) {
      return true;
    }

    proto = Object.getPrototypeOf(proto);
  }
}


console.log(myInstanceof([], Array));     // true
console.log(myInstanceof([], Object));    // true

console.log(myInstanceof(null, Object));  // false
console.log(myInstanceof(123, Number));   // false

数组去重

双转换法

先转换成Set对象,再转成数组,因为Set对象的性质就是不重复。

转换成Set对象,就是通过Set的构造函数转换就行。不过将Set对象转成数组有两种方法:

  1. 扩展运算符...
  2. Array.from()
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myUniqueArr(arr) {
  return Array.from(new Set(arr));
  // return [...new Set(arr)];
}

const arr = [1, 2, 2, 3, 4, 2, 1, 3, 6];
console.log(myUniqueArr(arr));    // [ 1, 2, 3, 4, 6 ]

新数组+遍历

原理就是遍历一遍原数组,如果不能在新数组中找到该元素,则新增到新数组里。因为一旦能找到,也就是说已经重复了,就不需要再添加到数组里了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myUniqueArr(arr) {
  const result = [];

  arr.forEach(item => {
    if (!result.includes(item)) {
      result.push(item);
    }
  })

  return result;
}


const arr = [1, 2, 2, 3, 4, 2, 1, 3, 6];
console.log(myUniqueArr(arr));    // [ 1, 2, 3, 4, 6 ]

上面用的是includes来判断数组有没有包含元素,实际上也能够使用indexOf等不等于-1来判断。

filter

使用filter来实现数组去重就有点有意思了。filter就是遍历一遍数组,只返回满足条件的。所以只需要判断当前索引是不是等于该元素在数组中的第一位置即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myUniqueArr(arr) {
  return arr.filter((item, index) => index === arr.indexOf(item));
}


const arr = [1, 2, 2, 3, 4, 2, 1, 3, 6];
console.log(myUniqueArr(arr));    // [ 1, 2, 3, 4, 6 ]

reduce

实际上使用reduce也是可行的。reduce的第一个参数是一个函数,第二个参数是初始值。

该函数的第一个参数是上一个函数的返回值,第二个参数是当前处理的元素。

通过reduce来实现数组去重就是设置初始值为[],如果累加的数组中不包含当前处理的元素则添加到数组中去。然后返回累加的数组

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myUniqueArr(arr) {
  return arr.reduce((pre, cur) => {
    if (!pre.includes(cur)) {
      pre.push(cur);
    }

    return pre;
  }, [])
}


const arr = [1, 2, 2, 3, 4, 2, 1, 3, 6];
console.log(myUniqueArr(arr));    // [ 1, 2, 3, 4, 6 ]

参考

死磕 36 个 JS 手写题(搞懂后,提升真的大) - 掘金

GitHub - qianlongo/fe-handwriting: 手写各种js Promise、apply、call、bind、new、deepClone….

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
30道高频JS手撕面试题
Object.getPrototypeOf:用来获取某个实例对象的原型(内部[[prototype]]属性的值,包含proto属性)
前端迷
2020/09/30
2.4K0
30道高频JS手撕面试题
面试必问:手撕代码系列(二)
沉浸式趣谈
2024/03/13
1490
面试必问:手撕代码系列(二)
JS面试题-手动实现一个instanceof功能
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
用户10106350
2022/10/28
4350
js手写题汇总(面试前必刷)
event bus既是node中各个模块的基石,又是前端组件通信的依赖手段之一,同时涉及了订阅-发布设计模式,是非常重要的基础。
helloworld1024
2022/11/09
1.1K0
JS进阶-数据类型的判断方式以及转换方式的汇总
强制类型转换方式包括 Number()、parseInt()、parseFloat()、toString()、String()、Boolean()
小渔夫
2022/05/10
1.1K0
JS进阶-数据类型的判断方式以及转换方式的汇总
前端经常遇到的手写js题
(3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)
helloworld1024
2022/11/02
8760
js进阶手写常见函数
无论是学习react还是vue,它们都是js的应用框架。剥去他们的壳子看到的始终是js,所以作为一个前端大厨必须要熟练掌握好js这个大勺,才能烧出一顿好菜
hellocoder2029
2022/10/03
4220
彻底搞懂JS原型与原型链
说到JavaScript的原型和原型链,相关文章已有不少,但是大都晦涩难懂。本文将换一个角度出发,先理解原型和原型链是什么,有什么作用,再去分析那些令人头疼的关系。
hellocoder2029
2022/10/17
3.5K1
JavaScript 笔试题(三)
第三行,首先会对 a.x 进行查找,没有找到就会先赋值 undefined,即:{n: 1, x: undefined}。此时 a 和 b 都指向同一个对象。然后 a 变量又赋值成一个新的对象:{n: 2},最后把新的 a 赋值给 x(前面的 a. 已经被替换成了原来的 a 所指向的那个内存中的对象),x 就有值了,b 就变成了:
多云转晴
2020/06/30
7890
最近面试经常被问到的js手写题
防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行
helloworld1024
2022/11/08
5440
JS之instanceof详解
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/163371.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/15
5860
JS之instanceof详解
JS 手写: instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
Cellinlab
2023/05/17
4390
32个常考的手写面试题,值得动手练一练
https://juejin.cn/post/6963167124881670152
前端达人
2021/06/16
7620
假如易立竞问你如何判断 JavaScript 中的数据类型?
我们习惯把对象称为引用类型,当然还有很多特殊的引用类型,比如 Function、Array、RegExp、Math、Date、Error、Set、Map、各种定型数组 TypedArray 等。
童欧巴
2021/06/25
5120
被要求实现instanceof,面试官到底考察我什么?
https://github.com/qianlongo/fe-handwriting
前端胖头鱼
2022/07/25
1540
被要求实现instanceof,面试官到底考察我什么?
32个手撕JS,彻底摆脱初级前端(面试高频)
作者:洛霞 https://juejin.im/post/6875152247714480136
前端达人
2020/11/11
1.9K0
32个手撕JS,彻底摆脱初级前端(面试高频)
前端手写面试题合集
AJAX是 Asynchronous JavaScript and XML 的缩写,指的是通过 JavaScript 的 异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页。
helloworld1024
2022/12/14
5570
JavaScript数据类型判断
instanceof可以用来判断对象是否是某个类的实例。instanceof的实现原理出门左转查看手撕instanceof
闲花手札
2021/09/08
1K0
JS数据类型判断方式总结
​ 原因是typeof检测机制是通过计算机二进制进行检测 ​ js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息: ​ 000:对象 010:浮点数 100:字符串 110:布尔 1:整数 ​ null的所有机器码均为0,所以typeof检测的时候也认为是对象了
何处锦绣不灰堆
2022/08/07
1.7K0
判断是否为数组的 JavaScript 方法总结
我们在日常开发中,常常有判断某值类型的需求,今天我们总结一下常见的几种用来判断是否为数组的 JavaScript 方法。
编程三昧
2021/08/22
1.2K0
判断是否为数组的 JavaScript 方法总结
相关推荐
30道高频JS手撕面试题
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验