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

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日

相关文章

  • 关于日期正则表达式的思路详解

    《关于日期正则表达式的思路详解》是一篇涉及日期格式的正则表达式文章,旨在帮助读者理解如何通过正则表达式匹配各种常见的日期格式。文章主要分为以下三个部分: 1. 常见日期格式的分析 在这一部分中,我们对常见的日期格式进行了分析,包括ISO 8601日期格式、美国日期格式、欧洲日期格式等等,同时针对每种日期格式提供了相应的正则表达式示例。 例如,我们可以通过以下…

    JavaScript 2023年6月10日
    00
  • JavaScript中箭头函数与普通函数的区别详解

    下面是“JavaScript中箭头函数与普通函数的区别详解”的完整攻略。 一、前言 在ES6的时代,随着箭头函数的引入,它逐渐被越来越多的开发者所使用,那么箭头函数和普通函数又有何区别呢?接下来,我们将从诸如函数内部的this、arguments、new、原型等角度来详细讲解两种函数的异同。 二、this 普通函数中的this是由函数的调用方式动态绑定的,而…

    JavaScript 2023年5月27日
    00
  • Yii实现单用户博客系统文章详情页插入评论表单的方法

    实现单用户博客系统文章详情页插入评论表单的方法,可以通过以下步骤来完成: 第一步:创建表结构 首先需要设计评论表的表结构。我们可以创建一个名为“comment”的表,其中包含以下字段: id:评论id,主键,自增 article_id:所评论的文章id,外键,关联文章表 content:评论内容 created_at:创建时间 updated_at:更新时间…

    JavaScript 2023年6月11日
    00
  • JavaScript 实现鼠标拖动元素实例代码

    下面就给您详细讲解一下“JavaScript 实现鼠标拖动元素实例代码”的攻略。 什么是鼠标拖动元素 鼠标拖动元素是指利用鼠标对网页上的某个元素进行拖动操作,把元素从一个位置移到另一个位置。在前端开发中,鼠标拖动元素经常被用于实现拖拽排序、拖拽上传等功能。 实现鼠标拖动元素的基本步骤 实现鼠标拖动元素的基本步骤如下: 给需要拖动的元素添加鼠标按下的事件监听器…

    JavaScript 2023年6月10日
    00
  • 使用JS动态显示文本

    下面是使用JS动态显示文本的完整攻略: 1. 编写HTML代码 首先,在HTML代码中需要创建一个用于显示文本内容的元素,可以是<span>、<div>或者其他你想要的元素。例如,下面代码创建了一个<div>元素: <div id="my-text"></div> 2. 写JS代…

    JavaScript 2023年5月27日
    00
  • JavaScript 数组详解

    JavaScript 数组详解 简介 JavaScript 中的数组是一种用于存储和操作一组或多组数据的有序集合。数组可以存储任何类型的数据、可以根据需要进行扩展或缩小。JavaScript 数组有许多强大的方法和属性,可以对数组进行各种处理,例如查找、添加、删除和排序等操作。 数组的基本操作 声明数组 在 JavaScript 中,可以使用以下方式声明一个…

    JavaScript 2023年5月17日
    00
  • javascript smipleChart 简单图标类

    OK,下面是“javascript simpleChart 简单图表类”的详细攻略: 1. 简介 simpleChart 是基于原生的 JavaScript 开发的一个简单易用的图表库,用于在网页中绘制常见的统计图表,如折线图、柱形图、饼图等。它的优点是使用灵活、兼容性好、易于扩展,适合用于数据可视化方面的开发。 2. 如何使用 2.1 引入文件 使用 si…

    JavaScript 2023年6月10日
    00
  • JavaScript实现打地鼠小游戏

    让我来介绍一下如何使用JavaScript实现打地鼠小游戏的攻略。这个攻略将涵盖整个实现过程,并且提供两个示例来帮助解释。 准备工作 首先,为了开始这个小游戏的开发,我们需要准备一些基本的工具和框架。以下是需要准备的内容: HTML:用于构建页面并显示游戏。 CSS:用于样式和布局方案。 JavaScript:用于游戏逻辑的实现。 图片资源:用于创建动画和显…

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