instanceof 是如何工作的
知其然
JavaScript 提供 instanceof 关键字判断一个对象所属的构造函数。在 js 高级编程中讲到 instanceof 的作用:
instanceof 操作符,用来测试实例与原型链中出现过的构造函数,只要出现过就会返回 true。
个人对这句话不是很理解,看下面例子:
function Person(){
this.name="tjm";
}
function Student(){
Person.call(this);
this.grade = 1;
}
Student.prototype = new Person();
var stu = new Student();
console.log(stu instanceof Student); //true
console.log(stu instanceof Person); //true
首先要知道,每个构造函数在没显示指定原型的情况下,会默认分配一个原型对象,该原型对象中包含 constructor 属性指向构造函数,以及 prototype 属性指向 Object 的原型。但通过原型继承,显示指定 Student.prototype = new Person() , 那么构造函数 Student 的原型是 Person 对象,而该原型有一个 prototype 属性指向 Person 构造函数的原型,一个name 等于 tjm 的属性。因此,可以看出,stu 实例的原型链中并没有出现 Student 构造函数,但是stu instanceof Student 依然返回 true,这就让我感到疑惑了。下图展示了 Student 的构造函数的原型链。

知其所以然
发现了不解的地方,一个很好的办法就是通过实践来进行检验,多做几次实验测试,就能够发现规律。看下面这段代码。
function Person(){ //(Object|obj)
this.name="tjm";
}
function Student(){ s1
Person.call(this);
this.grade = 1;
}
Student.prototype = new Person(); // p1
var stu = new Student();
Student.prototype = new Person(); // p2
console.log(stu instanceof Student); // false
console.log(stu instanceof Person); // true
上面代码在 stu 实例化之后,再更改 Student 构造函数的原型实例,虽然原型实例还是一个 Person 对象,但是 stu instanceof Student 却为 false 了。下面通过原型对象来分析 instanceof 来判断的值。stu 在实例化时,内部 【prototype】 属性指向的是当时 Student 构造函数所指向的对象,那么 stu 原型对象是 p1 (Person 对象), 但是在 stu 对象实例化之后,Student 构造函数的原型更改为 p2 , 也是一个 Person 对象。虽然 p1,p2 都是 Person 的对象,但是他们却是不同的,拥有不同的内存地址,使用 == 操作符,结果是 false 。通过对上面代码进行分析,可以得出这样的结果:
obj instanceof Construcotr—> instanceof 操作符是判断 Constructor 构造函数的原型对象是否存在实例 obj 的原型链中,如果存在,那么返回true,否则返回 false。
根据上面总结再来分析一下代码,stu 实例的原型链中的对象为 p1,p0,Object, 而 Student 的原型对象为 p2 ,因此 stu instanceof Student 当然返回 false。 Student 的原型对象没有在 stu 实例的原型链中。明白了instanceof 操作符真的工作原理,下面我们很容更改 stu 原型链中的对象,使得 stu instancecof Student 返回 true。好在 es5 提供了 __proto__ 属性访问实例的原型。
function Person(){
this.name="tjm";
}
function Student(){
Person.call(this);
this.grade = 1;
}
var p1 = new Person();
Student.prototype = p1;
var stu = new Student();
var p2= new Person();
Student.prototype = p2;
stu.__proto__ = p2; //通过更改 stu 原型为 p2
console.log(stu instanceof Student); // true
console.log(stu instanceof Person); // true
通过 stu.__proto__ = p2; 语句,将 stu 的原型更改为与 Student 构造函数一样的原型对象 p2, 这下 stu instanceof Studetn 结果返回 true。
小结
instanceof 操作符作用是:在运行时,构造函数的原型对象是否出现在实例的原型链中,如果出现则返回 true,否则返回false。 切记,一定是运行时,而不是初始化时。
instanceof 是如何工作的的更多相关文章
- Javascript 封装问题
Javascript 封装问题 为什么会用这样一个题目呢,这是要说封装的什么问题,本文并不讲高深的封装理论,只是解决一个小问题. 问题来源 今天在百度知道上闲逛,遇到一个网友的问题,问题如下,问题的地 ...
- 深入理解JavaScript原型:prototype,__proto__和constructor
JavaScript语言的原型是前端开发者必须掌握的要点之一,但在使用原型时往往只关注了语法,其深层的原理并未理解透彻.本文结合笔者开发工作中遇到的问题详细讲解JavaScript原型的几个关键概念, ...
- javaScript 工作必知(六) delete in instanceof
in in 判断 左边 的字符串或者能转换成字符串的是否属于 右边 的属性. var data = { x: 1, y: 4 };//定义了直接对象 alert("x" in d ...
- 5.在MVC中使用泛型仓储模式和工作单元来进行增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...
- [翻译]Java HashMap工作原理
大部分Java开发者都在使用Map,特别是HashMap.HashMap是一种简单但强大的方式去存储和获取数据.但有多少开发者知道HashMap内部如何工作呢?几天前,我阅读了java.util.Ha ...
- [工作中的设计模式]解释器模式模式Interpreter
一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我 ...
- JSP工作原理
一.历史 JSP是Servlet的扩展,JSP没出现之前,就已经出现了Servlet技术.Servlet是利用了"输出流",动态的生成了HTML页面.包括 每一个HTML标签和所有 ...
- [zz]Java中的instanceof关键字
1.What is the 'instanceof' operator used for? stackoverflow的一个回答:http://stackoverflow.com/questions/ ...
- 每日学习心得:Js获取Checkboxlist所选值、instanceof 和typeof区别、为Array添加contains方法
2013-11-24 前言: 上周在工作中遇到了一些跟JS以及前台交互的问题,虽然算不上多么高深,但是在解决时也走了一些弯路,所以就总结一下. 1. JS获取checkboxList所选的值 这 ...
随机推荐
- hibernate 使用枚举字段的最佳实践
枚举类虽然很简单,但是却往往是系统中业务逻辑最集中最复杂的地方.本文将会分享我们项目中基于hibernate的枚举类使用规范,包含数据库中枚举列数据类型.注释.枚举列与枚举类的映射等. 一.枚举类定义 ...
- 【CSS3】块级元素与行内元素的区别
一.行内元素与块级函数的三个区别 行内元素的特点: 和其他元素都在一行上: 高,行高及外边距和内边距部分可改变: 宽度只与内容有关: 行内元素只能容纳文本或者其他行内元素. 行内元素设置width无效 ...
- Hello ReactJS
前言 React学习前先搭好环境,官网的例子看着比较分散.结合webpack就可以体验完整的es6开发流程了. 源码:https://github.com/Ryan-Miao/hello-react- ...
- java中io流浅析
1.java.io包下File类:java程序中的此类的一个对象,就对应着硬盘中的一个文件或网络中的一个资源.File file1 = new File("d:\\io\\helloworl ...
- Jenkins发布MVC应用程序
一个大的项目一般都会进行模块化.层次化分隔,每个模块.每个层次都可能是一个或多个工程文件组成,而且各个模块都有依赖关系,有先后顺序,先build哪个然后再build哪个都是有顺序的,如果想build一 ...
- nodeJS实现路由功能
前面的话 本文将使用NodeJS实现较复杂应用的路由功能 结构 项目结构如下 代码如下 功能 [router.js] // 加载所需模块 var http = require('http'); var ...
- 实例甜点 Unreal Engine 4迷你教程(4)之用C++实现添加子Widget到VerticalBox中以及ClearChildren
前置教程: 1. 实例甜点前面的三篇教程: 2. 最好看看笔者前面的一篇关于博文(后记:本来笔者想用C++做DragAndDrop的功能,但是失败了,下面是蓝图实现的方法): http://www.c ...
- ++i,i++和i += 1的区别
++i,i++和i += 1的区别 单条语句:i++;.++i;和 i += 1;等价. int i = 0; ++i; // 或者i++;或者i += 1; cout << i < ...
- 16. leetcode 404. Sum of Left Leaves
Find the sum of all left leaves in a given binary tree. Example: 3 / \ 9 20 / \ 15 ...
- Java集合框架Collections【List/Set】
1.基本介绍: 集合就是存放对象的,他比数组好的一点就是他一开始不清楚自己长度 容器一般是分为很多种的,很多的容器在一起然后进过断的抽象和抽取就成了一个体系,我们称之为集合框架 我们看体系首先是看顶层 ...