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日

相关文章

  • js日期时间补零的小例子

    关于“js日期时间补零的小例子”的完整攻略,我将介绍以下内容: 1. 问题概述 在JS编程中,我们经常需要将日期时间转化为特定的格式,例如”2019-11-07 09:23:16″,当时分秒为一位数时,需要在前面补零。本教程将从JS代码实现的角度出发,为大家介绍如何使用JS代码实现时间补零功能。 2. 代码实现 下面是JS代码实现时间补零的一个小例子: fu…

    JavaScript 2023年5月27日
    00
  • 彻底解决页面文字编码乱码问题

    彻底解决页面文字编码乱码问题的攻略主要分为以下几个步骤: 1. 确认网页编码 在解决页面文字编码乱码问题之前,我们需要先确定当前网页的编码方式。常见的网页编码方式有 UTF-8、GB2312、GBK 等等。你可以通过查看网页源代码的 meta 标签或者请求头中的 content-type 信息来确认编码方式。 一般情况下,我们推荐网页使用 UTF-8 编码,…

    JavaScript 2023年5月19日
    00
  • javascript中json对象json数组json字符串互转及取值方法

    下面是“JavaScript中JSON对象、JSON数组、JSON字符串互转及取值方法”的完整攻略: 1. JSON对象 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,其数据格式和JavaScript对象的格式类似。在JavaScript中,可以通过JSON对象来解析JSON字符串,也可以将JavaScript对…

    JavaScript 2023年5月27日
    00
  • JavaScript字符串的长度问题

    JavaScript字符串的长度问题在实际代码编写过程中非常常见,本篇攻略将详细讲解该问题。 什么是JavaScript字符串的长度 JavaScript字符串的长度是指该字符串所包含的字符数,换言之,字符串的长度就是其中字符的数量。 如何获取JavaScript字符串的长度 在JavaScript中,获取一个字符串的长度可以通过Javascript字符串的…

    JavaScript 2023年5月28日
    00
  • vue调用本地摄像头实现拍照功能

    下面我将详细讲解“vue调用本地摄像头实现拍照功能”的完整攻略。 1. 添加依赖库 首先需要引入vue-web-cam库,它提供了调用本地摄像头的功能。可以通过如下命令安装: npm install vue-web-cam 2. 实现拍照功能 接下来,我们需要在组件中实现拍照功能。这里提供两种示例。 示例 1:使用原生的HTML和JavaScript实现拍照…

    JavaScript 2023年6月11日
    00
  • JavaScript架构localStorage特殊场景下二次封装操作

    那么以下是对JavaScript架构localStorage特殊场景下二次封装操作的具体攻略: 什么是localStorage? localStorage 是一种可以在浏览器本地存储数据的 API。它可以通过 key-value 对的形式保存数据,每个 key-value 对都会被浏览器独立存储,并且不受域名和浏览器限制。 为什么需要二次封装操作? loca…

    JavaScript 2023年6月11日
    00
  • JavaScript 高级语法介绍

    JavaScript 高级语法介绍攻略 什么是 JavaScript 高级语法? JavaScript 高级语法是指相对于语言基础而言更深入、更难掌握的语言知识部分。学习 JavaScript 高级语法可以帮助开发者更加灵活地运用 JavaScript 编程语言,实现更复杂、更高级的功能。 JavaScript 高级语法包括哪些? JavaScript 高级…

    JavaScript 2023年5月18日
    00
  • Javascript 使用function定义构造函数

    Javascript 使用function定义构造函数 在Javascript中,我们可以使用function来定义一个构造函数,从而创建对象实例。这种方式被称为使用构造函数模式。 定义构造函数 定义一个构造函数很简单,只需要使用function关键字,紧接着是函数名和括号,然后在函数体内部定义对象的属性和方法即可。 function Person(name…

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