本文结合代码讲解,争取一次理解透,前提是需要掌握__proto__ 和prototype。__proto__ 和prototype关系转换可以参考上一片文章《__proto__、prototype、constructor》
typeof
用途:typeof operand || typeof(operand),返回一个字符串,表示未经计算的操作数的类型。
区分范围: number、undefined、symbol、string、function、boolean、object 这七种数据类型
无法区分:判断不出object 属于哪一种 object;将null 判断为 object。
使用 new 操作符
除 Function 外的所有构造函数的类型都是 'object'
typeof new String('String'); // 返回 'object'
typeof new Number(100); // 返回 'object'
typeof new Function(); // 返回 'function'
语法中的括号
typeof是单元运算符,运算优先级高于双元运算符,因此不加括号,会优先计算类型值==>括号有无将决定表达式的类型
var iData = 99;
typeof iData + ' Wisen'; // 'number Wisen'
typeof (iData + ' Wisen'); // 'string'
错误
被声明之前对块中的 let 和 const 变量使用 typeof 会抛出一个 ReferenceError
注意一些易错的场景
// 数值
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number';
// 字符串
typeof (typeof 1) === 'string'; // typeof 总是返回一个字符串
typeof String(1) === 'string';
// 布尔值
typeof Boolean(1) === 'boolean'; // Boolean() 会基于参数是真值还是虚值进行转换
typeof !!(1) === 'boolean'; // 两次调用 ! (逻辑非) 操作符相当于 Boolean()
// Symbols
typeof Symbol.iterator === 'symbol';
// 对象
// 使用 Array.isArray 或者 Object.prototype.toString.call区分数组和普通对象
typeof [1, 2, 4] === 'object';
typeof new Date() === 'object';
typeof /regex/ === 'object'; // 历史结果请参阅正则表达式部分
// 下面的例子令人迷惑,非常危险,没有用处。避免使用它们。
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';
typeof null;//"object"
// 函数
typeof function() {} === 'function';
typeof class C {} === 'function'
typeof Math.sin === 'function';
注意:JS的7种基本数据类型别混淆了:null,undefined,Number, String,Boolean,Object,Symbol
typeof null === "object"原理
JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null
代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"。
instanceof
object instanceof constructor
用途:检测 constructor.prototype 是否存在于参数 object 的原型链上,明确地确认对象为某特定类型。
结合原型链典例
function C() {}
function D() {}
let o = new C()
o instanceof C
// true, o.__proto__ === C.prototype
o instanceof D // false, D.prototype is nowhere in o's prototype chain
o instanceof Object
// true, o.__proto__===C.prototype; C.prototype.__proto__ === Object.prototype
C.prototype instanceof Object
// true, C.prototype.__proto__ === Object.prototype
C.prototype = {}
let o2 = new C()
o2 instanceof C
// true, o2.__proto__ ===C.prototype
o instanceof C
// false, because C.prototype is nowhere in o's prototype chain anymore
D.prototype = new C() // add C to [[Prototype]] linkage of D
let o3 = new D()
o3 instanceof D
// true , o3.__proto__ === D.prototype
o3 instanceof C
// true o3.__proto__ === D.prototype, D.prototype.__proto__ = C.prototype
console.log(Object instanceof Object);
//true Object.__proto__ === Function.prototype;Function.prototype__proto__ === Object.prototype
console.log(Function instanceof Function);
//true ,Function.__proto__ === Function.prototype
console.log(Number instanceof Number);
//false ,Number.__proto__ === Function.prototype
console.log(String instanceof String);//false ,理由同7
console.log(Function instanceof Object);
//true ,Function.__proto__ === Function.prototype,Function.prototype__proto__ === Object.prototype
console.log(Foo instanceof Function);//true ,理由同7
console.log(Foo instanceof Foo);//false,理由同7
let simpleStr = 'This is a simple string'
let myString = new String()
let newStr = new String('String created with constructor')
let myDate = new Date()
let myObj = {}
let myNonObj = Object.create(null)
simpleStr instanceof String // false, simpleStr is not an object
myString instanceof String // true,myString.__proto__ === myString.prototype
newStr instanceof String // true,myString.__proto__ === myString.prototype
myString instanceof Object // true,myString.prototype.__proto__===Object.prototype
myObj instanceof Object // rtrue, myObj.__proto__===Object.prototype
({}) instanceof Object // true,理由同13
myNonObj instanceof Object // false, prototype is end of prototype chain (null)
myString instanceof Date // returns false
myDate instanceof Date // returns true
myDate instanceof Object // returns true
myDate instanceof String // returns false
instanceof 原理实现
function instance_of(obj, constructor) {
var constructor = constructor.prototype;
obj = obj.__proto__;
while (true) {
if (obj === null)
return false;
if (obj === constructor)
return true;
obj = obj.__proto__; // 逐级查找原型链
}
}