Skip to content
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

类型判断 #8

Open
huitoutunao opened this issue Jun 30, 2021 · 0 comments
Open

类型判断 #8

huitoutunao opened this issue Jun 30, 2021 · 0 comments
Labels

Comments

@huitoutunao
Copy link
Owner

类型判断

前言

在 web 开发和前端工具类库中,我们能够看到类型判断的广泛应用。

类型判断,顾名思义就是判断一个值是简单类型还是复杂类型。接下来让我们来学习下如何在代码中实现类型判断。

typeof

typeof 操作符返回一个字符串,表示未经计算的操作数的类型。

我们知道在 ES6 之前,JavaScript 有 6 种数据类型,分别是:Undefined、Null、Boolean、Number、String、Object。通过下面例子,观察下它们被判断成什么结果。

console.log(typeof bar) // undefined
console.log(typeof null) // object
console.log(typeof true) // boolean
console.log(typeof 42) // number
console.log(typeof 'foo') // string
console.log(typeof {}) // object
console.log(typeof function baz() {}) // function

我们发现这上面有两个特殊的地方,一个是 null 被判断成是 Object 类型,另一个是 function 类型,它不在 6 种数据类型内。虽然 typeof 可以检测出 JavaScript 的六种数据类型,但是 Object 下还有很多细分的类型,如 Array、Function、Date、RegExp、Error 等。

举个例子看下检测情况:

console.log(typeof new Date()) // object
console.log(typeof new Array()) // object

咦?Object 的细分类型该怎么区分呢?答案是 Object.prototype.toString。

Object.prototype.toString

toString() 方法返回一个表示该对象的字符串。

每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中 type 是对象的类型。

我们使用 toString() 方法查看上面的 Date 和 Array 的类型:

const date = new Date()
const array = new Array()

console.log(Object.prototype.toString.call(date)) // [object Date]
console.log(Object.prototype.toString.call(array)) // [object Array]

因此我们可以使用 toString() 方法来区分 Object 的细分类型。

typeof 虽然不能区分 object 的细分类型,但是它的性能比较好。具体见下面的测试结果图:

is_type1

测试网站戳这里哈~

isString

我们跟着 lodash 库学习下如何实现字符串检测,下面贴出相关源码:

const toString = Object.prototype.toString

function getTag (value) {
    if (value == null) {
        return value === undefined ? '[object Undefined]' : '[object Null]'
    }
    return toString.call(value)
}

function isString (value) {
    const type = typeof value
    return type === 'string' || 
        (type === 'object' && value != null && !Array.isArray(value) && getTag(value) == '[object String]')
}

// demo
const a = new String('hello')
const b = 'world'

console.log(isString(a)) // true
console.log(isString(b)) // true

分析:从源码可以得出,lodash 为了追求性能首先是使用 typeof 操作符进行检测,如果这一步不能判断出具体类型,再使用 Object.prototype.toString() 方法进行检测。

这里可能有同学产生疑问,咦?为什么源码中出现了 !Array.isArray(value) 这个条件判断?本人推测是性能方面的考虑。因为 Array.isArray() 的运行性能比 Object.prototype.toString() 优,所以避免使用 Object.prototype.toString 判断不是 string 类型的值。

isObject

我们跟着 lodash 库学习下如何实现对象检测,下面贴出相关源码:

function isObject (value) {
    const type = typeof value
    return value != null && (type === 'object' || type === 'function')
}

分析:首先排除了 null 这个值,因为上面提过它的 typeof 检测值是 object,然后就是不要漏了函数类型,因为函数是对象的细分类,而它的 typeof 检测值是 function,最后返回判断结果值。

结语

本文到这里就结束了。在 lodash 库里还有其它类型检测的方法,感兴趣的同学可以去阅读源码,类型判断的大体思路是我上面介绍的 typeofObject.prototype.toString 方法。

@huitoutunao huitoutunao added the 专题系列 JS专题 label Jun 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant