一、typeof

1、 手写实现

  1. /*
  2. 实现思路:
  3. 1.利用Object.prototype.toString()方法
  4. 2.将Object.prototype.toString()方法获取的字符串进行截取
  5. 3.利用toLowerCase()方法,将字符串转为小写
  6. */
  7. function typeOf(obj) {
  8. return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase();
  9. }

二、instanceof

1、基本概念

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

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
instanceof操作符的内部实现机制和隐式原型、显式原型有直接的关系。instanceof的左值一般是一个对象,右值一般是一个构造函数,用来判断左值是否是右值的实例。它的实现原理是沿着左值的proto一直寻找到原型链的末端,直到其等于右值的prototype为止。
instanceof 的作用是判断一个对象是不是一个函数的实例。比如 obj instanceof fn, 实际上是判断fn的prototype是不是在obj的原型链上。所以

2、手写实现

  1. /*
  2. 实现思路:
  3. 1.leftVaule代表实例对象
  4. 2.rightVaule代表构造函数
  5. 3.利用typeof方法,判断输入的leftVaule是否为对象,如果不是,则返回false
  6. 4.遍历leftVaule的原型链,直到找到rightVaule的prototype,如果查找失败的话,返回false,反之,返回true
  7. */
  8. function instanceofMethod (left, right) {
  9. let prototype = right.prototype;
  10. let proto = left.__proto__;
  11. while (true) {
  12. if (proto === prototype) return true;
  13. if (proto === null) return false;
  14. //若本次查找无结果,则沿着原型链向上查找
  15. proto = proto.__proto__;
  16. }
  17. }

3、引用类型会出现的问题

基本包装类型对象:ECMAScript还提供了3个特殊的引用类型: Boolean、Number、String。这些类型与其他内置对象类型相似,但同时具有各自的基本类型相应的特殊行为。实际上,每当读取一个基本类型值得时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。 包装类型,是一个专门封装原始类型的值,并提供对原始类型的值执行操作的API对象

其他内置对象与基本包装类型对象的区别?

普通的内置对象与基本包装类型的主要区别就是对象的生命期,使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中,而自动创建的基本包装类型的对象,则只是存在于一行代码的执行瞬间,然后立即被立即销毁。这意味着我们不能再运行时为基本包装类型值添加属性和方法,也没有所谓的 constructor了。
所以

  1. console.log('a' instanceof String) // false
  2. console.log(0 instanceof Number) // false
  3. console.log(false instanceof Boolean) // false
  4. // null为一切对象的始祖
  5. console.log(null instanceof null) // TypeError: Right-hand side of 'instanceof' is not an object