资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

实现类型判断-创新互联

实现类型判断 挑战介绍

本节我们来挑战一道大厂面试真题 —— 实现类型判断。

成都创新互联服务项目包括通江网站建设、通江网站制作、通江网页制作以及通江网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,通江网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到通江省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!挑战准备

新建一个getType.js文件,在文件里写一个名为getType的函数,并导出这个函数,如下图所示:
在这里插入图片描述

这个文件在环境初始化时会自动生成,如果发现没有自动生成就按照上述图片自己创建文件和函数,函数代码如下:

function getType(target) {// 补充代码
}

module.exports = getType;
挑战内容

请封装一个函数,能够以字符串的形式精准地返回数据类型。

要求返回的类型全部由小写字母组成。

示例:

输入输出
true‘boolean’
100‘number’
‘abc’‘string’
100n‘bigint’
null‘null’
undefined‘undefined’
Symbol(‘a’)‘symbol’
[]‘array’
{}‘object’
function fn() {}‘function’
new Date()‘date’
/abc/‘regexp’
new Error()‘error’
new Map()‘map’
new Set()‘set’
new WeakMap()‘weakmap’
new WeakSet()‘weakset’
注意事项
  • 文件名、函数名不可随意更改。
  • 文件中编写的函数需要导出,否则将无法提交通过。
题目解答:

先贴一波答案

function getType(target) {const type = typeof target;
  if (type !== "object") {return type;
  }
  return Object.prototype.toString
    .call(target)
    .replace(/^\[object (\S+)\]$/, "$1")
    .toLocaleLowerCase();
}

首先我们要知道javascrip数据类型有两种:

  1. 基本类型:Undefined,Null,Boolean,Number,String

  2. 引用类型:

    • 第一类:原生对象:object,Array,Date,RegExp,Function以及有基本类型衍生出来的包装类型Boolean,Number,String;

    • 第二类内置对象,如Global,Math

    • 宿主对象,如IE中的window,WS中的WScript实例,以及任何用户创建的类

判断一个数据的类型,比较常用的有下面几种方式:

  • typeof
  • instanceof
  • Object.prototype.toString.call(xxx)

判断一个数据的类型,用得最多的就是 typeof 操作符, 但是使用typeof常常会遇到以下问题:

  • 无法判断null
  • 无法判断除了function之外的引用类型。
// 可以判断除了 null 之外的基础类型。
console.log(typeof true);// boolean
console.log(typeof 100);// number
console.log(typeof "abc");// String
console.log(typeof 100n);// bigint
console.log(typeof undefined);// undefined
console.log(typeof Symbol("a"));// symbol

// 无法判断 null function 之外的引用类型。
console.log(typeof null);// object
console.log(typeof []);// object
console.log(typeof {});// object
const fn = function(){};
console.log(typeof fn);// function

typeof无法精确地判断引用类型,这时,可以使用 instanceof 运算符,但是instanceof运算符一定要是判断对象实例的时候才是正确的

console.log([] instanceof Array);// true
const obj = {};
console.log(obj instanceof Object);// true
const fn = function(){};
console.log(fn instanceof Function);// true
const date = new Date();
console.log(date instanceof Date);// true
const re = /abc/;
console.log(re instanceof RegExp);// true

const str1 = "qwe";
const str2 = new String("qwe");
console.log(str1 instanceof String); // false,无法判断原始类型。
console.log(str2 instanceof String); // true

null比较特殊,可以直接判断

function getType(target) {// ...
  if (target === null) {return "null";
  }
  // ...
}

调用Object.prototype.toString方法,会统一返回格式为[object Xxx]的字符串,用来表示该对象(原始类型是包装对象)的类型。

// 引用类型 以此类推
console.log(Object.prototype.toString.call({})); // '[object Object]'
console.log(Object.prototype.toString.call(function () {})); // "[object Function]'
console.log(Object.prototype.toString.call(/123/g)); // '[object RegExp]'
console.log(Object.prototype.toString.call(new Date())); // '[object Date]'
console.log(Object.prototype.toString.call([])); // '[object Array]'
console.log(Object.prototype.toString.call(new WeakSet())); // '[object WeakSet]'

// 原始类型  以此类推
console.log(Object.prototype.toString.call(1)); // '[object Number]'
console.log(Object.prototype.toString.call("abc")); // '[object String]'

Object.prototype.toString方法来获取数据具体的类型,然后把多余的字符去掉即可,只取[object Xxx]里的Xxx

所以最终的代码实现为

function getType(target) {// 先进行 typeof 判断,如果是基础数据类型,直接返回。
  const type = typeof target;
  if (type !== "object") {return type;
  }

  // 如果是引用类型或者 null,再进行如下的判断,正则返回结果,注意最后返回的类型字符串要全小写。
  return Object.prototype.toString
    .call(target)
    .replace(/^\[object (\S+)\]$/, "$1")
    .toLocaleLowerCase();
}

或者返回

// ...
return Object.prototype.toString
  .call(target)
  .match(/\s([a-zA-Z]+)\]$/)[1] // 这种写法也可以。
  .toLocaleLowerCase();

不用正则表达式也可以哦

// ...
return Object.prototype.toString
  .call(target)
  .slice(8, -1) 
//slice(startIndex,endIndex),从0开始索引,其中8代表从第8位(包含)开始截取(本例中代表空格后面的位置,'['也是代表一位,不要看少了哦),-1代表截取到倒数第一位(不含),所以正好截取到[object String]中的String。
  .toLocaleLowerCase();

call 是函数的方法,是用来改变 this 指向的,用 apply 方法也可以。

如果不改变this指向为我们的目标变量xxxthis将永远指向调用的Object.prototype,也就是原型对象,对原型对象调用toString方法,结果永远都是[object Object]

console.log(Object.prototype.toString([]));
// 输出 '[object Object]'  不调用 call,this 指向 Object.prototype,判断类型为 Object。
console.log(Object.prototype.toString.call([]));
// 输出 '[object Array]'   调用 call,this 指向 [],判断类型为 Array

最后加几个学到的常见的js面试问题

1:JavaScript 有哪些数据类型

答: JavaScript 的数据类型分为原始类型和对象类型。

原始类型有 7 种,分别是:

  • Boolean
  • Number
  • BigInt
  • String
  • Null
  • Undefined
  • Symbol

对象类型(也称引用类型)是一个泛称,包括数组、对象、函数等一切对象。

常见面试题 2:typeof null 的结果是什么

答:

typeof null; // 'object'
常见面试题 3:原始类型和引用类型的区别是什么

答:

类型原始类型对象类型
不可改变可以改变
属性和方法不能添加能添加
存储值地址(指针)
比较值的比较地址的比较
常见面试题 4:typeof 和 instanceof 的区别是什么

答:

  • typeof运算符用来判断数据的类型。
  • instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上,也可以用来判断数据的类型。
    • typeof返回一个变量的类型字符串,instanceof返回的是一个布尔值。
    • typeof可以判断除了null以外的基础数据类型,但是判断引用类型时,除了function类型,其他的无法准确判断。
    • instanceof可以准确地判断各种引用类型,但是不能正确判断原始数据类型。
常见面试题 5:Symbol 解决了什么问题

答:Symbol是 ES6 时新增的特性,Symbol是一个基本的数据类型,表示独一无二的值,主要用来防止对象属性名冲突问题。

const obj = {name: "song",
  age: 18,
};

obj.name = "xxx"; // 给 obj.name 赋值,把以前的 name 覆盖了
console.log(obj); // { name: 'xxx', age: 18 }
copy
const obj = {name: "song",
  age: 18,
};
const name = Symbol("name");

obj[name] = "xxx"; // 使用 Symbol,不会覆盖

console.log(obj); // { name: 'song', age: 18, Symbol(name): 'xxx' }
console.log(obj.name); // 'song'
console.log(obj[name]); // 'xxx'
挑战总结
  • 这个题之前几次测试都没过,因为还不是很理解原始类型和对象类型的类型判断的方法
  • Bigint和symbol也不熟悉,感觉第一次看到,不清楚他们是哪一种类型的数据
  • 对instanceof的使用也不够熟练

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享名称:实现类型判断-创新互联
分享网址:http://cdkjz.cn/article/dcsjoe.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220