乐趣区

关于javascript:每日一题之js类型判断

typeof

typeof 操作符惟一的目标就是查看数据类型

类型 typeof 后果
根本类型 undefined undefined
Boolean boolean
Number number
String string
Symbol symbol
BigInt bigint
null object
援用类型 Object(Object, Array, Map, Set, Regexp, Date 等) object
Function function

你会发现用 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,比方 {} , []。
退出移动版