Javascript面向对象(十)——类检测instanceof
来源:互联网 发布:马赛克去除软件注册码 编辑:程序博客网 时间:2024/05/17 12:03
Javascript面向对象(十)——类检查instanceof
instanceof
操作符允许监测一个对象是否属于特定的类,也考虑了继承。
很多场景需要检测,这里我们用其构建一个多态函数,处理不同参数取决他们类型。
instanceof 操作符
语法为:
obj instanceof Class
如果obj属性class(或从它继承的列)返回true,举例:
class Rabbit {}
let rabbit = new Rabbit();
// is it an object of Rabbit class?alert( rabbit instanceof Rabbit ); // true
对构造函数一样工作:
// instead of classfunction Rabbit() {}alert( new Rabbit() instanceof Rabbit ); // true
内置的类,如Array:
let arr = [1, 2, 3];alert( arr instanceof Array ); // truealert( arr instanceof Object ); // true
请注意arr也属于Object类,Array类原型继承自Object。
instanceof操作检查原型链,使用静态方法Symbol.hasInstance,也可以实现。
obj instanceof Class的算法大概如下:
1、如果有一个静态方法Symbol.hasInstance,那么使用它,如下:
// assume anything that canEat is an animalclass Animal { static [Symbol.hasInstance](obj) { if (obj.canEat) return true; }}let obj = { canEat: true };alert(obj instanceof Animal); // true: Animal[Symbol.hasInstance](obj) is called
2、大多数类没有symbol.hasInstance
,这种情况下,检查如果Class.prototype和obj原型链的某个原型相等。
换句话说,比较:
obj.__proto__ == Class.prototypeobj.__proto__.__proto__ == Class.prototypeobj.__proto__.__proto__.__proto__ == Class.prototype...
在上面的示例中,Rabbit.prototype == rabbit.proto ,所以立刻返回结果。
在继承情况,rabbit也是父类的实例:
class Animal {}class Rabbit extends Animal {}let rabbit = new Rabbit();alert(rabbit instanceof Animal); // true// rabbit.__proto__ == Rabbit.prototype// rabbit.__proto__.__proto__ == Animal.prototype (match!)
这里描绘了 rabbit instanceof Animal
实现什么,和使用 Animal.prototype
比较:
顺便说下,也有一个方法objA.isPrototypeOf(objB)
, 如果objA是objB原型链中的某一个,则返回true。
所以使用obj instanceof Class测试,也可以使用Class.prototype.isPrototypeOf(obj) 改写。
很有趣,Class构造器不参与检查,仅原型链和Class.prototype属性检查。
所以,当prototype改变时,导致有趣的结果出现。如下:
function Rabbit() {}let rabbit = new Rabbit();// changed the prototypeRabbit.prototype = {};// ...not a rabbit any more!alert( rabbit instanceof Rabbit ); // false
为了保障安全,所以减少改变prototype。
利好:不同类型的Object toString
我们已经知道普通对象转成字符串值为[object Object]:
let obj = {};alert(obj); // [object Object]alert(obj.toString()); // the same
这时调用了toString的结果。但有个隐藏特性可以让toString更强大,我们能使用其作为typeof的扩展,供instanceof的替换使用。
听起来很奇怪,确实,让我们看看。
根据规范,内置的toString可以从Object中抽取,在对象上下文中执行,返回结果依赖执行对象。
- number 返回 [object Number]
- boolean 返回 [object Boolean]
- null 返回 [object Null]
- undefined 返回 [object Undefined]
- array 返回 [object Array]
- …
我们开始演示:
// copy toString method into a variable for conveniencelet objectToString = Object.prototype.toString;// what type is this?let arr = [];alert( objectToString.call(arr) ); // [object Array]
这里我们使用call在this=arr的上下文执行objectToString,内部toString算法检查this,并返回相应的结果。再看示例:
let s = Object.prototype.toString;alert( s.call(123) ); // [object Number]alert( s.call(null) ); // [object Null]alert( s.call(alert) ); // [object Function]
Symbol.toStringTag
对象的toString行为可以通过特定对象属性Symbol.toStringTag进行定制。举例:
let user = { [Symbol.toStringTag]: 'User'};alert( {}.toString.call(user) ); // [object User]
对于大多数特定环境对象,有这样的属性,这里是一些浏览器相关的示例:
// toStringTag for the envinronment-specific object and class:alert( window[Symbol.toStringTag]); // windowalert( XMLHttpRequest.prototype[Symbol.toStringTag] ); // XMLHttpRequestalert( {}.toString.call(window) ); // [object Window]alert( {}.toString.call(new XMLHttpRequest()) ); // [object XMLHttpRequest]
看到了吧,结果就是Symbol.toStringTag(如果存在),包装至[object …]。
最后,我们有更有力的typeof,不仅可以在基本数据类型上使用,也可以是内置对象,甚至可以自定义。
当我们需要对象类型字符串,而不是去检查对象类型,可以使用内置对象的toString代替instanceof。
总结
我们总结下类型检查方法:
使用对象返回值 typeof基本类型string {}.toString基本类型,内置对象,有Symbol.toStringTag的对象string instanceof所有对象true/false我们看到,{}.toString技术上是更高级的typeof.
instanceof操作符在当类继承,考虑其层次结果是使用。
- Javascript面向对象(十)——类检测instanceof
- javascript面向对象(十)
- 面向对象(高级)————instanceof关键字
- 面向对象(高级)————instanceof关键字
- 面向对象高级——instanceof关键字的使用以及抽象类与接口的应用
- 面向对象之instanceof
- 面向对象--instanceof
- 面向对象的JavaScript——类
- Javascript面向对象—继承
- javascript 面向对象 检测用户注册
- 面向对象--instanceof,equals方法
- JAVA面向对象-----instanceof 关键字
- Java面向对象instanceof关键字
- Java面向对象-instanceof关键字
- JavaScript面向对象程序设计——对象
- 面向对象(一)——包、构造器、多态和instanceof
- 面向对象的陷阱——instanceof运算符的陷阱
- javascript面向对象——面向对象基础
- 模块
- You don't have permission to access / on this server.
- 假如有Thread1、Thread2、ThreaD3、Thread4四条线程分别统计C、D、E、F四个盘的大小,所有线程都统计完毕交给Thread5线程去做汇总,应当如何实现?
- 字符串格式化
- 电子科技大学---操作系统课程实验(一)
- Javascript面向对象(十)——类检测instanceof
- Tinker使用
- 需求分析中如何画用例图
- [设计模式]命令模式(command)
- java面试题库
- Ajax与简易封装
- java.sql.SQLException: Field 'id' doesn't have a default value
- android的View加载过程
- THE INTERNET