1. typeof
typeof操作符返回一个字符串,表示为经求值的操作数的类型。可能返回值如下表
类型 | 返回值 |
---|---|
Number | ‘number’ |
Boolean | ‘boolean’ |
String | ‘string’ |
Null | ‘object’ (特殊) |
Undefined | ‘undefined’ |
Symbol(ES6新增类型) | ‘symbol’ |
函数 | ‘function’ |
其它任何对象 | ‘object’ |
常见题目
题目一
(funciton() {
return typeof arguments;
})
// 返回值为:object
Array.prototype.slice.call(arguments);
arguments是对象,不是真正的数组,它是一个伪数组,是可以使用方括号和整数索引的元素。通常可以利用Array的原型方式将其转换为数组。
var f = function fun(){ return 1; };
typeof fun(); // error
function fun(){ return 1; }为表达式,fun实际是一个名字,不是函数声明。函数绑定到变量f。
指定的函数标识符:fun的用途是使堆栈跟踪更加清晰,能使匿名函数递归调用其自身,不需要使用argument.callee()
题目二
var y = 1, x = y = typeof x;
x; // undefined
//实际执行顺序
var y;
y = 1;
y = typeof x; // 等同于 y = typeof window.x, 结果为y = 'undefined'
var x;
x = y;
x;
执行y=typeof x时,x还未被定义,所以y=‘undefined’(字符串),然后x=y
题目三
(function f(f){
return typeof f();
})(function(){ return 1; });
// 'number'(字符串)
//分解如下:
var g = function() { return 1 }
(function(f) {
return typeof f(); // 等同于 return typeof 1
})(g)
// 函数f参数是一个函数,f函数内部执行该函授后返回类型。
// f函数参数为f,与函数名冲突,函数也接受本身作为自己的参数。此时调用f(),需看谁具有更高的优先级,显然参数的优先级高
题目四
var foo = {
bar: function(){ return this.baz; },
baz: 1
}
typeof (f = foo.bar)();
// 'undefined'(字符串)
// 分解如下:
var foo = {
bar: function(){ return this.baz; },
baz: 1
}
f = foo.bar
typeof f()
// foo.bar存储给f然后调用,此处this引用是全局对象,不会指向foo的baz属性
// 简而言之,foo.bar的上下文是foo,但是赋值给f后,上下文是window
题目五
难点在于if 中的 function f(){} 要如何处理?
函数声明的实际规则如下:
函数声明只能出现在程序或函数体内。从语法上讲,它们不能出现在Block(块)({ … })中,例如不能出现在 if、while或for语句中。因为 Block(块)中只能包含Statement语句, 而不能包含函数声明这样的源元素。唯一可能让表达式出现在Block(块)中,就是让它作为表达式语句的一部分。但是规范明确规定了表达式语句不能以关键字function开头。也就是函数表达式同样也不能出现在Statement语句或Block(块)中(因为Block(块)就是由Statement语句构成的)。
var x = 1;
if (function f(){}) {
x += typeof f;
}
x;
// 'undefined'
//分解如下:
var x = 1;
if (function(){}) {
x += typeof f;
}
x;
// 再次分解
var x = 1;
x += typeof f;
x;
题目五
自己手动尝试哦!!!
function f(){ return f; }
new f() instanceof f;
function f(){ return this }
new f() instanceof f;
function f(){ }
new f() instanceof f;
2. Object.prototype.toString.call(value)
toString()定义在Object.prototype上,可使用该方法判断数据类型。注意:Object.prototype.toString()本身是允许被修改的,假设该方法未被修改过,使用方法如下:
1.判断基本类型,函数类型,日期类型,数组类型
值(value)(对应call的参数) | 返回值 |
---|---|
1 | ‘[object Number]’ |
false | ‘[object Boolean]’ |
’1‘ | ‘[object String]’ |
null | ‘[object Null]’ |
undefined | ‘[object undefined]’ |
function f(){ } | ‘[object Function]’ |
new Date() | ‘[object Date]’ |
[1, 2, 3] | ‘[object Array]’ |
2.正则表达式和自定义类型
很明显,该方法不能准确判断一个person是Person的实例,可以用instanfod操作符来判断。
var reg = /[hbc]at/gi;
Object.prototype.toString.call(arr); // '[object Array]'
function Person(name, age) {
this.name = name;
this.age = age;
}
var person = new Person("Rose", 18);
Object.prototype.toString.call(arr); // '[object Object]'
console.log(person instanceof Person); // 输出结果为true
3.判断原生JSON对象
var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);
console.log(isNativeJSON);//输出结果为”[object JSON]”说明JSON是原生的,否则不是;
3. instanceof(基础认识)
instanceof要求开发者明确确认对象为某特定类型。即instanceof用于判断引用类型属于哪个构造函数的方法。
var arr = []
arr instanceof Array // true
typeof arr // object, typeof 是无法判断是否为数组的
但是对于number,string,boolean这三种类型,只有通过构造函数定义才能检测出
// 能被检测出
let num = new Number(1);
// 不能被检测出
let num = 1
它更重的一点是 instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型。
// 判断 f 是否是 Foo 类的实例 , 并且是否是其父类型的实例
function Aoo(){}
function Foo(){}
Foo.prototype = new Aoo(); // JavaScript 原型继承
var f = new Foo();
console.log(foo instanceof Foo) // true
console.log(foo instanceof Aoo) // true