很多前端开发者经常困惑:什么时候该用 instanceof,什么时候该用 typeof?这两个操作符看起来都用于类型检查,但它们的用途和原理完全不同。
instanceof 的语法很简单:
object instanceof Constructor // 返回 true 或 false左边是要检查的对象,右边是构造函数。简单说,就是检查对象是否属于某个构造函数的实例。
typeof 的用法更直接:
typeof value // 返回类型字符串instanceof 的核心是检查对象的原型链。它的工作流程是这样的:
获取对象的原型:Object.getPrototypeOf(obj)
获取构造函数的原型属性:Constructor.prototype
沿着原型链向上查找,直到:
找到匹配的原型 → 返回 true
找到 null 还没有匹配 → 返回 false
用代码来模拟这个过程:
function instanceOf(obj, Ctor) {
if (typeof obj !== 'object' || obj === null) return false;
let proto = Object.getPrototypeOf(obj);
while (proto) {
if (proto === Ctor.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
return false;
}假设我们有这样的继承关系:
function Animal() {}
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
const d = new Dog();原型链是这样的:
d → Dog.prototype → Animal.prototype → Object.prototype → null检查结果:
d instanceof Dog // true,第一层匹配
d instanceof Animal // true,第二层匹配
d instanceof Object // true,第三层匹配
d instanceof Cat // false,整个链都没有 Cat.prototype"abc" instanceof String // false
123 instanceof Number // false
true instanceof Boolean // false只有使用 new 创建的包装对象才会返回 true:
new String('abc') instanceof String // true在不同 iframe 或窗口中,相同的构造函数会有不同的原型:
// 在 iframe A 中
const iframeArray = window.frames[0].Array;
const arr = [];
arr instanceof Array // true
arr instanceof iframeArray // falsefunction F() {}
const o = new F();
F.prototype = {}; // 修改了原型
console.log(o instanceof F); // falseES6 引入了 Symbol.hasInstance,可以自定义 instanceof 的行为:
class MyArray {
static [Symbol.hasInstance](obj) {
return Array.isArray(obj) && obj.length > 3;
}
}
[1,2,3,4] instanceof MyArray; // true
[1,2] instanceof MyArray; // false| 值 | typeof 结果 | instanceof 检查 | 说明 |
|---|---|---|---|
| [] | 'object' | Array | typeof 无法区分数组和对象 |
| {} | 'object' | Object | 同上 |
| new String('') | 'object' | String | 包装对象 |
| function fn(){} | 'function' | Function | typeof 能识别函数 |
| null | 'object' | 任何都是 false | JavaScript 的历史问题 |
| "hello" | 'string' | String → false | 原始类型 |
// 不推荐的方法
const isArray = value => value instanceof Array;
// 推荐的方法
const isArray = value => Array.isArray(value);Array.isArray() 比 instanceof 更好,因为它:
性能更好
解决跨框架问题
代码意图更清晰
function getType(value) {
// 先处理 null
if (value === null) return 'null';
// 处理其他类型
const type = typeof value;
if (type !== 'object') return type;
// 详细的对象类型检查
if (Array.isArray(value)) return 'array';
if (value instanceof Date) return 'date';
if (value instanceof RegExp) return 'regexp';
return 'object';
}// 检查是否是字符串
if (typeof value === 'string') {
// 处理字符串
}
// 检查是否是函数
if (typeof callback === 'function') {
callback();
}// 检查是否是日期对象
if (value instanceof Date) {
console.log(value.getFullYear());
}
// 检查是否是自定义类的实例
if (employee instanceof Manager) {
employee.approveRequest();
}// 处理 null 和 undefined
if (value == null) {
// 同时处理 null 和 undefined
}
// 安全的属性访问
if (typeof obj?.property === 'string') {
// 使用可选链避免错误
}// 错误
if (value instanceof String) {
// 这只会对 new String('') 返回 true
}
// 正确
if (typeof value === 'string') {
// 对字符串字面量和 String 对象都有效
}function User(name) {
this.name = name;
}
const user1 = new User('张三');
User.prototype = {}; // 修改原型
const user2 = new User('李四');
console.log(user1 instanceof User); // false
console.log(user2 instanceof User); // trueclass Animal {}
class Flyable {
static [Symbol.hasInstance](obj) {
return typeof obj.fly === 'function';
}
}
class Bird extends Animal {
fly() {}
}
const bird = new Bird();
console.log(bird instanceof Animal); // true
console.log(bird instanceof Flyable); // truefunction safeTypeCheck(value, type) {
if (typeof type === 'function') {
return value instanceof type;
}
switch (type) {
case 'array': return Array.isArray(value);
case 'null': return value === null;
case 'undefined': return value === undefined;
default: return typeof value === type;
}
}记住这几个要点:
typeof 用于检查原始类型和函数,返回类型字符串
instanceof 用于检查对象是否是某个构造函数的实例,检查原型链
原始类型 用 typeof 检查,对象类型用 instanceof 检查
跨框架 时使用 Array.isArray() 等内置方法
注意原型修改 对 instanceof 结果的影响
在实际开发中,根据具体需求选择合适的类型检查方法。对于基础类型,typeof 更合适;对于复杂的对象类型,instanceof 更准确。理解它们的原理和差异,能帮助你写出更健壮的代码。
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!
VR能让人完全沉浸在虚拟环境中;AR能创建一个叠加在虚拟内容的世界,但不能与真实环境交互; MR则是虚拟与现实的混合体,它能创造出可以与真实环境交互的虚拟物体。最后,XR则是包括三种“现实”(AR,VR,MR)的术语。
call,apply,bind的区别:apply接收数组 func.apply(obj, [arus]),call一连串参数 func.call(obj, param1, param2....),bind返回一个函数 func.bind(obj,param...)(parms...)
event.screenX、event.screenY鼠标相对于用户显示器屏幕左上角的X,Y坐标。标准事件和IE事件都定义了这2个属性,event.clientX、event.clientY鼠标相对于浏览器可视区域的X,Y坐标
对于英文单词,如果有一个连写且长度很长的英文单词,在第一行显示不下的情况下,浏览器默认不会截断显示,而是把这个单词整体挪到下一行。但是当整体挪到下一行还是显示不完全该肿么办呢?
URL统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL
框架和类库等概念的出现都是源于人们对复用的渴望。“不要重复发明轮子”,成了软件界的一句经典名言。从最初的单个函数源代码的复用,到面向对象中类的复用(通常以类库的形式体现)
js是JavaScript 源码文件, .min.js是压缩版的js文件。减小体积 .min.js文件经过压缩,相对编译前的js文件体积较小,传输效率快。防止窥视和窃取源代码
SDH是基于TDM技术,主要用于传输语音,此外采用GFP封装来传输IP包,物理介质为光纤。PTN是采用DWDM技术,主要用于传输IP包、以太网帧,此外采用MPLS-TP技术来实现PWE3伪线
写代码的时候就经常把这两个属性弄混淆,到底是href还是src,href表示超文本引用,用在link和a等元素上,href是引用和页面关联,是在当前元素和引用资源之间建立联系,src表示引用资源,表示替换当前元素,用在img,script,iframe上
运行后发现,点击后src没有变化,调试发现,这里this是window对象,而不是img标签对象。顿时感觉有点迷惑,因为以前绑定事件中,拿标签属性都是用的this,怎么这里不对了?
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!