参考文章:JavaScript之typeof
typeof
我们知道 typeof 可以用来判断一个值类型变量的类型,如下代码
typeof 10 // number
typeof '10' // string
typeof undefiend // undefiend
typeof true // boolean
typeof null // object
当然,上面的只是一些基础用法,下面介绍的 typeof 应用场景可能很多都没见过
一
function fun() {
console.log(typeof arguments)
}
fun(1, 2) // object
fun(1) // object
fun() // object
arguments 是函数的内置对象,都是一个对象了,所以是一个复杂数据类型,所以使用 typeof arguments 返回 object
二
let f = function g() {
return 23
}
console.log(typeof g()) // error,g is not defined
从报错信息可以看出来 g 并没有被定义,但是上面的代码明明有 function g。这是因为上面的代码是一个函数表达式,右边是一个函数赋值给了 f,虽然此函数有一个名字 g,但是本质上不是一个函数声明,也可以理解为 g 仅仅是一个名字而已,不起到任何作用,只是给这个匿名函数加了一个名字,真正的函数是 f,看如下代码就知道了
// 声明一个函数
function f(){
console.log('i am function')
}
f() // i am function
let cb = function () { // 此函数是一个匿名函数,赋值给了 cb,所以cb才是一个函数
console.lo('i am cb')
}
cb() // i am cb
三
var y = 1, x = y = typeof x
console.log(y) // undefiend
首先有连等符号将其从右至左拆开,即
var y = 1
y = typeof x
var x = y
var 声明的变量 x 提升,所以执行 typeof x 的时候 x的值为 undefined
四
(function f(f) {
console.log(typeof f()) // number
})(function () {
return 1
})
这个立即执行函数的实参是一个函数,返回 1,形参 f 接收到这个实参,所以此时立即执行函数内部的形参 f 是一个函数并且返回 1,所以 打印 number。
至于上面的 f 为什么不是立即执行函数本身而是立即执行函数的形参,可以看如下代码
;(function f() {
console.log(f) // [Function: f]
})()
;(function f(f) {
console.log(f) // 10
})(10)
;(function f() {
function f() {
console.log(1)
}
return f() // 打印2,预解析:将当前作用域的function声明都提前,后面的那个f覆盖掉了前面那个f,所以打印2
function f() {
console.log(2)
}
})()
五
var foo = {
bar: function () {
return this.baz
},
baz: 1
}
console.log(typeof (f = foo.bar)()) // undefined
分解第七行的代码,如下
f = foo.bar
typeof f()
此时将 foo 对象的 baz 方法 赋值给了 f,此时 f 这个 函数的 this 指向为 window,并且window 没有这个 baz 属性,所以打印 undefined
六
var f = (function f(){ return "1"; }, function g(){ return 2; })();
typeof f; // number
立即执行函数里面有两个函数 f 和 g,以逗号分割。此时我们可能不太明确是哪个函数的返回值起作用。所以,可以先看如下代码
let x = (1, 2, 3, 5)
console.log(x) // 5
const fun = () => {
return console.log('1'), 2, 3, 4, 5, 6
}
console.log(fun()) // 先打印 1,最后在打印 6
从上面的代码可以看出:当存在一个组合以逗号分割的形式存在,首先会从左到右依次计算,但这个组合的值以最后一个为准。
所以此题最后以 g 函数的为准,g 函数返回数字 2,所以 为 number
七
let x = 1
if (function f() {}) {
x += typeof f
}
console.log(x) // 1undefined
if 里面的() 是不能通过 function 声明一个函数的,括号里面应该是一个表达式,在此刻声明一个 f 没有任何作用,所以 typeof f 为 undefiend。
对上述代码改进
let y = 1
if ((y = function () {})) {
y += typeof y
}
console.log(y, typeof y) // function () {}function string
if 里面的括号是一个表达式,所以 y 被重新赋值了一个函数,函数与字符串相加会将整个函数与字符串拼接,对象和数组与字符串相加也会与字符串拼接
console.log([1, 2, , 3, 4, 5] + 'string') // 1,2,,3,4,5string
console.log({ name: 'name' } + 'string') // [object Object]string
八
console.log(typeof m) // undefined
var x = [typeof x, typeof y][1]
console.log(typeof typeof x) // string
由于 typeof x 和 typeof y 都是 字符串类型,值为 undefiend,所以 typeof typeof x 为 string
标题九
;(function (foo) {
console.log(typeof foo.bar) // undefined
})({ foo: { bar: 1 } })
形参 foo 接收了一个对象,这个对象没有 bar 属性,此对象下面的 foo 对象才有一个 bar 属性