JavaScript类型检测之typeof 和 instanceof 的缺陷与优化

yizhihongxing

JavaScript类型检测之typeof 和 instanceof 的缺陷与优化

typeof的缺陷

在JavaScript中,typeof操作符用于检测一个变量或表达式的数据类型,返回一个字符串常量。

typeof variable

typeof操作符返回的结果只有一下几种:

  • "undefined": 如果变量没有被赋值或者值为undefined
  • "boolean": 如果变量是布尔类型
  • "number": 如果变量是数值类型
  • "string": 如果变量是字符串类型
  • "object": 如果变量是对象或者null
  • "symbol":如果变量是ES6中新增的Symbol类型

typeof操作符看上去非常方便,但是在一下几种情况下,它会有一些缺陷:

无法准确地检测变量类型

typeof null // "object"

当我们使用typeof来检测null时,返回的结果是"object",而不是"null"。这是由JavaScript中的历史原因造成的,也是一个已知的BUG。

无法区分不同类型的对象

typeof {name: "John", age: 18} // "object"
typeof [1, 2, 3] // "object"

当我们使用typeof来检测一个对象或者数组时,返回的结果都是"object",无法区分不同类型的对象。

无法检测函数类型

typeof function(){} // "function"

函数是JavaScript中的一种特殊类型,但是使用typeof检测函数时,返回的结果是"object",而不是"function"。这也是JavaScript中的一个已知BUG。

instanceof的缺陷

在JavaScript中,instanceof操作符用于检测一个对象是否是某个类的实例。

object instanceof constructor

instanceof操作符返回一个布尔值,如果objectconstructor的实例,则返回true,否则返回false

虽然instanceof操作符看上去比typeof更加准确,但是它也存在以下几个缺陷:

无法检测基本数据类型

var value = 123;
value instanceof Number // false

在JavaScript中,numberbooleanstring等基本数据类型与对应的包装类型有明显的区别,但是使用instanceof检测基本数据类型时,结果总是为false

无法跨域检测对象

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
var iframeArray = iframeDocument.createElement('iframe');
console.log(iframeArray instanceof window.parent.Array) // false
console.log(iframeArray instanceof iframe.contentWindow.Array) // true

如果我们想要在不同的窗口或者不同的iframe中检测对象类型时,使用instanceof会出现问题。

优化思路

虽然typeofinstanceof存在一些缺陷,但是我们依然可以利用它们进行类型检测,只需要对它们的缺陷进行一些规避和优化。

规避typeof的缺陷:

var isType = function (type) {
  return function(obj) {
    return Object.prototype.toString.call(obj) === '[object ' + type + ']';
  }
}

var isObject = isType('Object');
var isArray = isType('Array');
var isFunction = isType('Function');
var isString = isType('String');
var isNumber = isType('Number');
var isBoolean = isType('Boolean');
var isNull = isType('Null');
var isUndefined = isType('Undefined');

通过自定义一个isType方法,来避免typeof无法准确检测对象类型的问题。这个方法内部通过Object.prototype.toString.call来获取精确的类型信息,并返回一个布尔值。

规避instanceof的缺陷:

function _instanceof(left, right) {
  // 获取 right 的 prototype 属性值
  var prototype = right.prototype;
  // 获取 left 的原型对象
  left = left.__proto__;
  // 遍历 left 的原型链
  while (true) {
    // 如果 left 的原型链等于 null,则说明原型链遍历完毕
    if (left === null) {
      return false;
    }
    // 如果 left 的原型链等于 right 的 prototype,则说明 left 是 right 的实例
    if (prototype === left) {
      return true;
    }
    // 继续遍历原型链
    left = left.__proto__;
  }
}

自定义_instanceof方法,通过获取左侧对象的原型链,与右侧构造函数的prototype属性进行匹配,从而规避了instanceof不能跨域检测对象的问题。

示例说明

示例1:检测对象类型

function Person(name, age) {
  this.name = name;
  this.age = age;
}

var john = new Person("John", 18);

console.log(isObject(john)); // true
console.log(isFunction(john)); // false
console.log(isArray(john)); // false

在这个示例中,我们定义了一个Person类,并创建了一个john对象。通过使用自定义的isObjectisFunctionisArray方法来检测john对象的类型,可以得到准确的结果。

示例2:跨域检测对象

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
var iframeArray = iframeDocument.createElement('iframe');

console.log(_instanceof(iframeArray, window.parent.Array)); // true

在这个示例中,我们创建了一个新的iframe,并在这个iframe中创建了一个iframeArray对象。使用自定义的_instanceof方法来检测iframeArray对象是否是window.parent.Array类型时,可以得到准确的结果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript类型检测之typeof 和 instanceof 的缺陷与优化 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • 一文教你如何实现localStorage的过期机制

    首先需要明确 localStorage 是HTML5标准中的一种客户端存储方式,可以在浏览器中存储数据并保留在客户端本地。而过期机制则是指设置一个过期时长,在达到时限之后,数据自动失效并被清空。 下面就来介绍如何实现 localStorage 的过期机制: 步骤1:封装localStorage 首先我们需要进行封装 localStorage,以方便我们在任何…

    JavaScript 2023年6月11日
    00
  • 用js自动判断浏览器分辨率的代码

    确定浏览器分辨率的方法有很多种,其中一种方法就是使用JavaScript代码来获取浏览器分辨率。以下是实现该功能的方法: 方法一:使用screen对象 我们可以使用 screen 对象来获取用户的屏幕分辨率。 let screenWidth = screen.width; let screenHeight = screen.height; console.l…

    JavaScript 2023年6月11日
    00
  • javascript解析json实例详解

    当我们从后台获取数据时,常常会得到一个以 JSON 格式组成的字符串,而在前端中我们需要将这个 JSON 字符串转换成 JavaScript 对象以便进行进一步的操作。那么如何解析 JSON,让它变成我们想要的 JavaScript 对象呢?下面以实例的形式讲解一下。 1、解析 JSON 字符串 解析 JSON 主要使用 JavaScript 中的 JSON…

    JavaScript 2023年5月27日
    00
  • js显示世界时间示例(包括世界各大城市)

    下面就是“js显示世界时间示例(包括世界各大城市)”的完整攻略。 思路概述 本代码的主要思路是通过获取当前时间(即本地时间),将其转换为世界各大城市的对应时间,并在页面上显示出来。具体实现方法是使用 JavaScript 和 Moment.js 库。 实现步骤 引入 Moment.js 库 Moment.js 是一个 JavaScript 日期处理库,可以方…

    JavaScript 2023年5月27日
    00
  • js计算时间过去的时间

    JS计算时间过去的时间,可以使用Date对象及其方法来实现。具体流程如下: 获取当前时间 可以使用new Date()来创建Date对象,实现获取当前时间,代码如下: let now = new Date(); 指定时间 可以使用new Date(year, monthIndex, day, hour, minute, second, millisecond…

    JavaScript 2023年5月27日
    00
  • JavaScript实现PC端横向轮播图

    下面是JavaScript实现PC端横向轮播图的完整攻略: 准备工作 要实现PC端横向轮播图,需要先准备好以下几点: HTML结构,即容器元素及其子元素,通常是一个div包裹符合数量的图片(img标签)。 CSS样式,如容器元素宽高、溢出隐藏、子元素浮动、统一宽高等。 JS代码,用来实现轮播图的滑动效果,具体实现方式后面会讲到。 实现步骤 确认容器元素的宽度…

    JavaScript 2023年6月11日
    00
  • ASP基础入门第二篇(ASP基础知识)

    那我就来详细讲解一下“ASP基础入门第二篇(ASP基础知识)”的完整攻略吧。 标题一:ASP基础入门第二篇(ASP基础知识) 段落一:什么是ASP? ASP全称为Active Server Pages,是一种动态网页技术。利用ASP技术,可以在网页中嵌入服务器脚本,对用户的输入进行处理,生成动态内容并进行展示。ASP技术可以与多种服务器脚本语言结合使用,例如…

    JavaScript 2023年6月11日
    00
  • 使用RequireJS库加载JavaScript模块的实例教程

    我来详细讲解如何使用RequireJS库加载JavaScript模块。 什么是RequireJS RequireJS是一个JavaScript模块加载器,它可以帮助我们实现依赖模块的异步加载。它采用了AMD规范,并提供了一种便捷的方式,使JavaScript开发人员可以更容易地组织和管理代码。 安装与配置 下载RequireJS 去RequireJS的官方网…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部