-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JavaScript专题之类型判断(上) #28
Comments
博主,这句哈撒意思?ES6 是新增了 Symbol 类型,博主是否写错了? 加油写,我会一直看的。 |
@HerryBin 感谢支持~ 正在努力撰写中…… 想表达的意思就是对上面六种数据类型的值进行 typeof 运算,结果分别对应下面的值 typeof undefined // "undefined"
typeof null // "object"
typeof true // "boolean"
typeof 1 // "number"
typeof "s" // "string"
typeof {} // "object" |
我想问下这里 或 后面的object在什么情况下会发生 |
@WittyBob 比如说 ES6 新增的 Symbol、Map、Set 等类型,它们并不在 class2type 列表中,所以使用 type 函数,返回的结果会是 object |
@mqyqingfeng 酷炫屌炸天 |
关于结果是小写哪里如果不写这段 "Boolean Number String Function Array Date RegExp Object Error Null Undefined".split(" ").map(function(item, index) {
class2type["[object " + item + "]"] = item.toLowerCase();
}) 如数组打印出来它会是大写的吗? |
@wangdabaoqq 正常调用 Object.prototype.toString.call(obj) 的时候,以 obj 为一个日期类型为例的话,结果会是 [object Date],不是全大写,而是首字母大写,需求是希望结果是 "date" |
function detectType(val){
return Object.prototype.toString.call(val).split(' ')[1].split(']')[0].toLowerCase();
} 不考虑兼容性的话,这样写有其他的问题吗? |
@xu824332362 可以呀,你也可以用正则匹配出来~ |
var isArray = Array.isArray || function( obj ) { |
@cp-apple Array.isArray 是一个判断,意思是如果有 Array.isArray 这个方法,isArray 就等于这个方法,如果没有才使用后面这个函数,注意,这里的 isArray 是一个函数,如果加上 Array.isArray(obj),如果 obj 不是数组,isArray 的值就等于 false 了 |
@mqyqingfeng 噢噢,这样啊,谢谢。o.o |
Object.prototype.toString 标题和第一行 Object 拼错啦~ up 主 ~ (-c- |
@merzoo 哈哈,感谢细心的 merzoo 指出~ o( ̄▽ ̄)d |
记忆中还有一种判定方法是 |
@ClarenceC 确实的,基本是四种方法:
对于数组类型,还有 Array.isArray 可以用于判断~ |
看了类型判断的下一篇,里面讲到window的时候,大佬用了一段 |
@Tan90Qian 厉害了,我也才发现,原来: Object.prototype.toString.call(location)
// "[object Location]"
Object.prototype.toString.call(history)
// "[object History]" 而且他们跟自身相等是因为引用是相同的吧,就像: var obj = {};
console.log(obj === obj) // true |
@mqyqingfeng 对,是因为“自身和自身的引用相同”,但其实这个思路其实在写逻辑判断的时候非常少用吧?正常的情况是,基本不会在对引用类型进行逻辑判断的时候直接对数据本身使用 PS:博主大大有空去看下bind的那一篇,感觉有些问题。 |
@Tan90Qian bind 那篇有回复,确实是有问题的,我也发现了这一点,不过想到既然 MDN 实现如此,那我也讲到这种程度吧……完整的实现确实会更繁琐一点 |
@mqyqingfeng 看到了,之前邮箱一直没有邮件提醒,我还以为dalao最近没空。从月初开始,每天看2、3篇博客,顺便“找茬”,收获非常大~ |
我想问下Object的valueOf和toString的区别在哪 |
把map换成forEach是否更合理一些? @mqyqingfeng |
试了一下新增的其他类型:
加起来有 15 种了,乖乖~ |
function type(obj) { |
function checkType(target) {
return Object.prototype.toString.call(target).slice(8, -1)
} |
var promise = new Promise( |
个人感觉jQuery这里做的不太好的就是,判断数据类型的type函数的扩展性不太好
这个方法取Object.prototype.toString.call(obj)的构造函数名称的部分 然后直接转换成小写 就可以针对各种各样的构造函数啦 |
symbol 不是基础类型吗?应该会走typeof 那一个吧 |
type API 个人感觉这么写更好些~ const typeMap = "Symbol Boolean Number String Function Array Date RegExp Object Error"
.split(" ")
.reduce((prev, item) => {
prev[`[object ${item}]`] = item.toLowerCase();
return prev;
}, {});
function type(obj) {
//解决IE6 中的兼容
if(null == obj) return '' + obj;
return typeof obj !== "object"
? typeof obj
: typeMap[Object.prototype.toString.call(obj)] || 'object';
} |
文中"那Object.protototype.toString 究竟是一个什么样的方法呢",这里多写了个to |
请问一下怎么理解 typeof 函数 = function 而不是 object |
function type(obj) {
// 一箭双雕
if (obj == null) {
return obj + "";
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[Object.prototype.toString.call(obj)] || "object" :
typeof obj;
} 这个地方有点疑惑,typeOf不是能直接检测出来为function类型吗?而且自己测试了在ie8+中是没有兼容问题的。那么为什么还需要通过Object.prototype.toString.call(obj)这一段进行function的类型检测呢?楼主。。。。是有什么其他的原因吗? |
大佬,我想问下明明Object.prototype.toString.call()已经可以检测出来所有这些类型了(包括基本类型),为什么还要去区分基本类型然后使用typeof呢?直接都是用Object.prototype.toString.call()不就好了吗 |
function type(obj) { |
"嗯,看起来很完美的样子~~ 但是注意,在 IE6 中,null 和 undefined 会被 Object.prototype.toString 识别成 [object Object]! |
typeof 效率更高 |
学习的时候,得留下印记,不然今后如何感慨岁月如梭呢,转眼间,已经关注大佬博客3年了 |
const o = { name: 11 }
class Person {
name = ''
constructor() {
this.name = 11
}
}
const p = new Person()
const str = 'dddd'
const num = 111
const bool = true
const d = new Date()
const f = function () { }
const m = new Map()
const s = new Set()
const wm = new WeakMap()
const arr = [1,2,3]
function type(obj) {
if (obj === null) return 'null'
// if (Array.isArray(obj)) return 'Array'
const a = obj.constructor.name
const b = Object.prototype.toString.call(obj).slice(8, -1)
console.log(a, '---', b);
}
type(null)
type(o)
type(p)
type(str)
type(num)
type(bool)
type(d)
type(f)
type(m)
type(s)
type(wm)
type(arr) |
前言
类型判断在 web 开发中有非常广泛的应用,简单的有判断数字还是字符串,进阶一点的有判断数组还是对象,再进阶一点的有判断日期、正则、错误类型,再再进阶一点还有比如判断 plainObject、空对象、Window 对象等等。
以上都会讲,今天是上半场。
typeof
我们最最常用的莫过于 typeof,注意,尽管我们会看到诸如:
的写法,但是 typeof 可是一个正宗的运算符,就跟加减乘除一样!这就能解释为什么下面这种写法也是可行的:
引用《JavaScript权威指南》中对 typeof 的介绍:
那我们都知道,在 ES6 前,JavaScript 共六种数据类型,分别是:
Undefined、Null、Boolean、Number、String、Object
然而当我们使用 typeof 对这些数据类型的值进行操作的时候,返回的结果却不是一一对应,分别是:
undefined、object、boolean、number、string、object
注意以上都是小写的字符串。Null 和 Object 类型都返回了 object 字符串。
尽管不能一一对应,但是 typeof 却能检测出函数类型:
所以 typeof 能检测出六种类型的值,但是,除此之外 Object 下还有很多细分的类型呐,如 Array、Function、Date、RegExp、Error 等。
如果用 typeof 去检测这些类型,举个例子:
返回的都是 object 呐,这可怎么区分~ 所以有没有更好的方法呢?
Object.prototype.toString
是的,当然有!这就是 Object.prototype.toString!
那 Object.protototype.toString 究竟是一个什么样的方法呢?
为了更加细致的讲解这个函数,让我先献上 ES5 规范地址:https://es5.github.io/#x15.2.4.2。
在第 15.2.4.2 节讲的就是 Object.prototype.toString(),为了不误导大家,我先奉上英文版:
凡是规范上加粗或者斜体的,在这里我也加粗或者斜体了,就是要让大家感受原汁原味的规范!
如果没有看懂,就不妨看看我理解的:
当 toString 方法被调用的时候,下面的步骤会被执行:
通过规范,我们至少知道了调用 Object.prototype.toString 会返回一个由 "[object " 和 class 和 "]" 组成的字符串,而 class 是要判断的对象的内部属性。
让我们写个 demo:
由此我们可以看到这个 class 值就是识别对象类型的关键!
正是因为这种特性,我们可以用 Object.prototype.toString 方法识别出更多类型!
那到底能识别多少种类型呢?
至少 12 种!
你咋知道的?
我数的!
……
让我们看个 demo:
除了以上 11 种之外,还有:
除了以上 13 种之外,还有:
所以我们可以识别至少 14 种类型,当然我们也可以算出来,[[class]] 属性至少有 12 个。
type API
既然有了 Object.prototype.toString 这个神器!那就让我们写个 type 函数帮助我们以后识别各种类型的值吧!
我的设想:
写一个 type 函数能检测各种类型的值,如果是基本类型,就使用 typeof,引用类型就使用 toString。此外鉴于 typeof 的结果是小写,我也希望所有的结果都是小写。
考虑到实际情况下并不会检测 Math 和 JSON,所以去掉这两个类型的检测。
我们来写一版代码:
嗯,看起来很完美的样子~~ 但是注意,在 IE6 中,null 和 undefined 会被 Object.prototype.toString 识别成 [object Object]!
我去,竟然还有这个兼容性!有什么简单的方法可以解决吗?那我们再改写一版,绝对让你惊艳!
isFunction
有了 type 函数后,我们可以对常用的判断直接封装,比如 isFunction:
数组
jQuery 判断数组类型,旧版本是通过判断 Array.isArray 方法是否存在,如果存在就使用该方法,不存在就使用 type 函数。
但是在 jQuery v3.0 中已经完全采用了 Array.isArray。
结语
到此,类型判断的上篇就结束了,我们已经可以判断日期、正则、错误类型啦,但是还有更复杂的判断比如 plainObject、空对象、Window对象、类数组对象等,路漫漫其修远兮,吾将上下而求索。
哦, 对了,这个 type 函数抄的 jQuery,点击查看 type 源码。
专题系列
JavaScript专题系列目录地址:https://github.com/mqyqingfeng/Blog。
JavaScript专题系列预计写二十篇左右,主要研究日常开发中一些功能点的实现,比如防抖、节流、去重、类型判断、拷贝、最值、扁平、柯里、递归、乱序、排序等,特点是研(chao)究(xi) underscore 和 jQuery 的实现方式。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。
The text was updated successfully, but these errors were encountered: