每日一题之js类型判断

文章介绍了JavaScript中用于检测数据类型的typeof操作符,其在处理引用类型时的局限性以及instanceof运算符的使用。此外,还详细讲解了Object.prototype.toString方法如何揭示对象的[[Class]]属性,以及如何通过这个方法来更精确地判断对象类型。最后,文章提供了一个面试题来检验对这些概念的理解,并讨论了解题思路。
摘要由CSDN通过智能技术生成

typeof

typeof 操作符唯一的目的就是检查数据类型

类型typeof 结果
基本类型undefinedundefined
Booleanboolean
Numbernumber
Stringstring
Symbolsymbol
BigIntbigint
nullobject
引用类型Object(Object, Array, Map, Set, Regexp, Date 等)object
Functionfunction

你会发现用typeof来判断引用类型时, 都会返回 ‘object’
. 为此, 引入了 instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

var arr = [];
arr instanceof Array; // true
typeof arr; // "object"

function A() {}
function B() {}

// Javascript 继承
B.prototype = new A();
var b = new B();

b instanceof A; // true
b instanceof B; // true

instanceof 的内部实现原理

  • 思路: 利用 原型和原型链, 每一个函数都有一个显式的 prototype, 每一个对象都有一个隐式原型 **proto**, 当我们对象的原型链中存在构造函数的显式原型 prototype时, 我们就可以确定它们之间存在关系;
function myInstanceOf(constructor, instance) {
  let prototype = constructor.prototype;
  let proto = instance.__proto__;
  while (true) {
    // 说明道原型链订单, 还未找到, 返回 false
    if (proto === null) {
      return false;
    }
    if (proto === prototype) {
      return true;
    }
    // 继续向 proto 的原型链上遍历
    proto = Object.getPrototypeOf(proto);
  }
}

Object.prototype.toString()

  • toString() 方法返回一个表示该对象的字符串。该方法旨在重写(自定义)派生类对象的类型转换的逻辑。
  • valueOf() 方法返回对象的原始值表示

该方法由 字符串转换优先调用, 但是 数字的强制转换原始值的强制转换 会优先调用 valueOf, 因为基本的 valueOf() 方法返回一个对象,toString() 方法通常在结束时调用

默认情况下(不重写 toString方法), 任何一个对象调用 Object原生的 toString方法, 都会返回一个 [object type], 其中 type是对象的类型

let a = {};

a; // {}
a.toString(); // "[object Object]"

[[class]]

每个 实例 都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的 type 。 [[Class]] 不能直接地被访问,但通常可以通过 Object.prototype.toString.call(…) 方法调用来展示。

// Boolean 类型,tag 为 "Boolean"
Object.prototype.toString.call(true); // => "[object Boolean]"

// Number 类型,tag 为 "Number"
Object.prototype.toString.call(10); // => "[object Boolean]"

// String 类型,tag 为 "String"
Object.prototype.toString.call("1312312"); // => "[object String]"

// Array 类型,tag 为 "String"
Object.prototype.toString.call([]); // => "[object Array]"

// Function 类型, tag 为 "Function"
Object.prototype.toString.call(function () {}); // => "[object Function]"

// Error 类型(包含子类型),tag 为 "Error"
Object.prototype.toString.call(new Error()); // => "[object Error]"

// RegExp 类型,tag 为 "RegExp"
Object.prototype.toString.call(/\d+/); // => "[object RegExp]"

// Date 类型,tag 为 "Date"
Object.prototype.toString.call(new Date()); // => "[object Date]"

// 其他类型,tag 为 "Object"
Object.prototype.toString.call(new (class {})()); // => "[object Object]"

所以可以通过这个方法来判断每个对象的类型

function generator(type){
  return function(value){
    return Object.prototype.toString.call(value) === "[object "+ type +"]"
  }
}

let isFunction = generator('Function')
let isArray = generator('Array');
let isDate = generator('Date');
let isRegExp = generator('RegExp');

isArray([]));    // true
isDate(new Date()); // true
isRegExp(/\w/); // true
isFunction(function(){}); //true

以下是一道简单的面试题

+[1 + [2] + 3] + [1 + 2 + true - false] + [[3 - false + "1"]];

// 拆分一下
let a = +[1 + [2] + 3];
// [2]会首先进行转换 [2].valueOf, 结果不是基本类型, [2]在调用toString(), 返回'2', 最后 1 + '2' + 3, 1,3进行隐式转换, +'123' ==> 123
let b = [1 + 2 + true - false];
// [3+true-false], true, false会进行转换, true=>1, false=>0, 最后1-0==>[1+3]==>[4]==>[4].valueOf().toString()==>'4'
let c = [[3 - false + "1"]];
// 先转换数组里面的一层, [3-0+'1']==>['31'], 结果: [['31']]==>[['31']].valueOf().toString()==>'31'

// 最后 a+b+c
// 123+'4'+'31'==>123431

面试题目, 如何同时让等式成立, a=1&&a=2&&a===3

  • 思路:
    重写 a 的 valueOf 方法
let a = {
  value: [3, 2, 1],
  valueOf: function () {
    return this.value.pop();
  },
};

总结:

  • 当一侧为 String 类型,被识别为字符串拼接,并会优先将另一侧转换为字符串类型。
  • 当一侧为 Number 类型,另一侧为原始类型,则将原始类型转换为 Number 类型。
  • 当一侧为 Number 类型,另一侧为引用类型,将引用类型和 Number 类型转换成字符串后拼接。
  • 只有 null undefined ‘’ NaN 0 false 这几个是 false,其他的情况都是 true,比如 {} , []。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值