Javascript高级—如何实现一个类型判断函数?

embedded/2024/11/14 9:06:52/

实现一个类型判断函数

  1. 判断null
  2. 判断基础类型
  3. 使用Object.prototype.toString.call(target)来判断引用类型

[!NOTE]
注意: 一定是使用call来调用,不然是判断的Object.prototype的类型

之所以要先判断是否为基本类型是因为:虽然Object.prototype.toString.call()能判断出某值是:number/string/boolean,但是其实在包装的时候是把他们先转成了对象然后再判断类型的。 但是JS中包装类型和原始类型还是有差别的,因为对一个包装类型来说,typeof的值是object

javascript">/*** 类型判断*/
function getType(target) {//先处理最特殊的Nullif(target === null) {return 'null';}//判断是不是基础类型const typeOfT = typeof targetif(typeOfT !== 'object') {return typeOfT;}//肯定是引用类型了const template = {"[object Object]": "object","[object Array]" : "array","[object Function]": "function",// 一些包装类型"[object String]": "object - string","[object Number]": "object - number","[object Boolean]": "object - boolean"};const typeStr = Object.prototype.toString.call(target);return template[typeStr];
}

升级版本

// typeof可以检测基本数据类型
// Undefined, Null, Boolean, Number, String, Objec
// undefined, object, boolean, number, string, object// 以下是11种:
var number = 1;          // [object Number]
var string = '123';      // [object String]
var boolean = true;      // [object Boolean]
var und = undefined;     // [object Undefined]
var nul = null;          // [object Null]
var obj = {a: 1}         // [object Object]
var array = [1, 2, 3];   // [object Array]
var date = new Date();   // [object Date]
var error = new Error(); // [object Error]
var reg = /a/g;          // [object RegExp]
var func = function a(){}; // [object Function]function checkType() {for (var i = 0; i < arguments.length; i++) {console.log(Object.prototype.toString.call(arguments[i]))}
}checkType(number, string, boolean, und, nul, obj, array, date, error, reg, func)console.log(Object.prototype.toString.call(Math)); // [object Math]
console.log(Object.prototype.toString.call(JSON)); // [object JSON]function a() {console.log(Object.prototype.toString.call(arguments)); // [object Arguments]
}a();// TODO:Object.toString()的理解?
/*1. 如果 this 值是 undefined,就返回 [object Undefined]2. 如果 this 的值是 null,就返回 [object Null]3. 让 O 成为 ToObject(this) 的结果4. 让 class 成为 O 的内部属性 [[Class]] 的值5. 最后返回由 "[object " 和 class 和 "]" 三个部分组成的字符串*/// TODO:封装一个通用的type API?
// v1: 基础版本
var class2type = {};'Undefined Null String Number Boolean Object Function Array Date RegExp Error'.split(' ').map(function (item) {// 开始建立映射关系class2type[`[object ${item}]`] = item.toLowerCase();})function type(obj) {return typeof obj === 'object' || typeof obj === 'function'? class2type[Object.prototype.toString.call(obj)] || 'object': typeof obj;
}// v2:在 IE6 中,null 和 undefined 会被 Object.prototype.toString 识别成 [object Object]!
// TODO: 解决IE6下的null和undefined 会被识别为[object Object]?
var class2type = {};
'Undefined Null String Number Boolean Object Function Array Date RegExp Error'.split(' ').map(function (item) {class2type[`[object ${item}]`] = item.toLowerCase();
})/*** 查看type的基础类型* @param obj* @return {string|*}*/
function type(obj) {// 开始解决ie下的兼容问题if (obj == null) {return obj + '';}return typeof obj === 'object' || obj === 'function'//  ES6 新增的 Symbol、Map、Set 等类型,它们并不在 class2type 列表中,所以使用 type 函数,返回的结果会是 object? class2type[Object.prototype.toString.call(obj)] || 'object': typeof obj;
}/*** 查看obj是否为函数累类型* @param obj* @return {boolean}*/
function isFunction(obj) {return type(obj) === 'function';
}/*** 注意这里的isArray是一个函数,并不是一个函数执行的结果* @type {((arg: any) => arg is Array<any>) | (function(*=): boolean)}*/
var isArray = Array.isArray || function (obj) {return type(obj) === 'array';
}// TODO: plainObject, 就是该对象是通过 "{}" 或 "new Object" 创建的,该对象含有零个或者多个键值对?
// 存放toString的映射结果
var class2type = {};
// Object.prototype.toString
var toString = class2type.toString();
// Object.prototype.hasOwnProperty
var hasOwn = class2type.hasOwnProperty;function isPlainObject(obj) {// 排除掉宿主对象 eg: toString.call(window) === '[objct window]'if (!obj || toString.call(obj) !== '[object Object]') {return false;}/*** Object.getPrototypeOf() 方法返回指定对象的原型(即, 内部[[Prototype]]属性的值),如果没有继承属性,则返回 null 。* eg: obj.__proto__ === Object.protptype* @type {any}*/var proto = Object.getPrototypeOf(obj);// 如果没有原型对象的话,eg:Object.create(null), 就是纯对象if (!proto) {return true;}// 通过new Object方式创建的对象// 判断 proto 是否有 constructor 属性,如果有就让 Ctor 的值为 proto.constructorvar Constructor = hasOwn.call(proto, 'constructor') && proto.constructor;// 判断Constructor是不是Object的构造函数return typeof Constructor === 'function' && hasOwn.toString.call(Constructor) === hasOwn.toString.call(Object);
}// TODO: EmptyObject如何判断?
function isEmptyObject(obj) {var name;// 看一下当前的这个obj对象有没有属性,如果有的话就返回falsefor (name in obj) {// 遍历的不仅仅是obj自身的属性,而且也遍历了obj原型上的属性return false;}return true;
}
// test
console.log(isEmptyObject({})); // true
console.log(isEmptyObject([])); // true
console.log(isEmptyObject(null)); // true
console.log(isEmptyObject(undefined)); // true
console.log(isEmptyObject(1)); // true
console.log(isEmptyObject('')); // true
console.log(isEmptyObject(true)); // true// TODO: 判断是否为window对象?
// window对象的window属性指向其本身
function isWindow(obj) {return obj != null && obj == obj.window;
}// TODO: 判断是否为document对象?
function isDocument(obj) {return obj != null && obj.nodeType == obj.DOCUMENT_NODE;
}// TODO: 判断是不是DOM元素
function isDOMElement(obj) {// 这里需要强制把返回的结果转换为bool类型,eg:obj = undefined,!!undefined=r\truereturn !!(obj && obj.nodeType === 1);
}// TODO: isArrayLike如何实现?(可以判断数组和伪数组类型)
function isArrayLike(obj) {// 1. 先看obj有没有length属性var length = !!obj && ('length' in obj) && obj.length;var typeRes = type(obj);// 2. 排除掉函数和window对象, window也是有length属性的if (typeRes === 'function' || isWindow(obj)) {return false;}// 3. 开始处理结果return typeRes === 'array'                  // 1. 是数组类型|| length === 0                     // 2. 长度为0(函数中的arguments参数)|| typeof length === 'number'&& length > 0&& (length - 1) in obj;             // 3. length 属性是大于 0 的数字类型,并且obj[length - 1]必须存在(符合条件的类数组对象是一定存在最后一个元素的)}// underscore 如何实现的?
function isArrayLike(collection) {var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;var length = getLength(collection);return typeof length === 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
}

http://www.ppmy.cn/embedded/137459.html

相关文章

黑马程序员Docker学习【持续更新】

Docker 一、初始Docker 1.什么是Docker 之前学习的linux系统虽然可以部署应用&#xff0c;但是操作给部署带来了很大的麻烦。 分布式系统 中&#xff0c;依赖的组件非常多&#xff0c;不同组件之间部署时往往会产生一些冲突。在数百上千台服务中重复部署&#xff0c;环境不…

【java版本中间件opc ua协议】写入数据,轮询、订阅方式读取数据

环境&#xff1a;单位研发设备界面软件和plc主机通信&#xff0c;采用opc ua协议的方式&#xff0c;软件读取、写入到plc服务器中&#xff0c;我们的软件是c的&#xff0c;之前使用opc ua官方提供的c#版本写成&#xff0c;但是想要将软件移植到linux服务器中&#xff0c;这样需…

windows C#-异常处理

C# 程序员使用 try 块来对可能受异常影响的代码进行分区。 关联的 catch 块用于处理生成的任何异常。 finally 块包含无论 try 块中是否引发异常都会运行的代码&#xff0c;如发布 try 块中分配的资源。 try 块需要一个或多个关联的 catch 块或一个 finally 块&#xff0c;或两…

大小改变事件

即窗口尺寸变化时会触发这个事件 通常在窗口尺寸变化后&#xff0c;在尺寸改变事件中&#xff0c;获取最新的尺寸&#xff0c;然后将内部某些控件的大小也跟着改变&#xff0c;或者改变布局 ------------------------------------------------------------------------------…

微信小程序_小程序视图与逻辑_day3

一、目标 A. 能够知道如何实现页面之间的导航跳转 B. 能够知道如何实现下拉刷新效果 C. 能够知道如何实现上拉加载更多效果 D. 能够知道小程序中常用的生命周期 二、目录 A. 页面导航 B. 页面事件 C. 生命周期 D. WXS脚本 E. 案例-本地生活&#xff08;列表页面&#xff09;…

java-web-苍穹外卖-day1:软件开发步骤简化版+后端环境搭建

软件开发 感觉书本上和线上课程, 讲的太抽象, 不好理解, 但软件开发不就是为了开发应用程序吗?! 干嘛搞这么抽象,对吧, 下面个人对于软件开发的看法, 主打简单易懂, 当然,我一IT界小菜鸟, 对软件开发的认识也很浅显, 这个思维导图也仅仅是现阶段我的看法, 我以后会尽力…

知识图谱,语义分析,全文检索,neo4j,elaticsearch,知识库平台(java,vue)

一、项目介绍 一款全源码&#xff0c;可二开&#xff0c;可基于云部署、私有部署的企业级知识库云平台&#xff0c;一款让企业知识变为实打实的数字财富的系统&#xff0c;应用在需要进行文档整理、分类、归集、检索、分析的场景。 为什么建立知识库平台&#xff1f; 助力企业…

1-安装kingbase

VM上的操作 将虚拟机上的快照还原到[初始化安装Linux]上 在快照管理器的界面还能看到对于该快照的描述 1、root/kingbase.123 2、2CPU*1&#xff1b;MEM5GB&#xff1b;删打印机&#xff1b;禁止自动挂载DVD 3、/etc/xorg.conf 4、/install上传了以下文件&#xff1a; 一键工…