JavaScript中constructor属性一直不是很清楚,今日终于弄清了其中缘由,下面举例说明。

首先是一个典型的JavaScript实例声明:

function Person(){
this.name = name;
}
var p = new Person('Joe');
console.log(p.constructor === Person); //true
console.log(p.__proto__ === Person.prototype); //true

如果此时对Person的prototype中添加属性或函数:

function Person(){
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
}
var p = new Person('Joe');
console.log(p.constructor === Person); //true
console.log(p.__proto__ === Person.prototype); //true

但是如果对Person的prototype重新定义,将会产生如下结果:

function Person(){
this.name = name;
}
Person.prototype = {
getName : function(){
return this.name;
}
}
var p = new Person('Joe');
console.log(p.constructor === Person); //false
console.log(p.__proto__ === Person.prototype); //true

这里面关系到constructor属性的归属问题,本人试着用下面的代码验证:

Person.__proto__.constructor===Person.constructor //true
p.__proto__.constructor === p.constructor; //true

经过上述验证,可以证明constructor其实是__proto__的属性(此处存疑,因为是个人验证,不清楚上面的验证代码是否精准,如果有误,希望各位指出)。

根据new的工作原理(详见http://www.cnblogs.com/ihardcoder/p/3667372.html),我们知道

p.__proto__ = Person.prototype;

所以

p.constructor = p.__proto__.constructor = Person.prototype.constructor

这样就将问题追溯到Person的prototype指向问题。当用Person.prototype = {}的方式重新定义时,同样根据new的工作原理,其实产生如下改变:

Person.prototype.__proto__ = Object.prototype

从而

p.constructor
= Person.prototype.constructor
= Person.prototype.__proto__.constructor
= Object.prototype.constructor

此时

p.constructor === Object; //true

如何避免constructor属性的混乱,归根结底,我们需要做的是保证instance的constructor属性指向Person.prototype.constructor,而不是Person的父类,所以当修改Person.prototype时需要保证Person.prototype.constructor指向自己。

function Person(){
this.name = name;
}
Person.prototype = {
getName : function(){
return this.name;
}
}
Person.prototype.constructor = Person;
var p = new Person('Joe');
console.log(p.constructor === Person); //false
console.log(p.__proto__ === Person.prototype); //true

constructor属性解析的更多相关文章

  1. 【Spring源码深度解析学习系列】复杂标签属性解析(四)

    一.创建用于属性承载的BeanDefinition BeanDefiniton是一个接口,在Spring中存在三种实现:RootBeanDefinition.ChildBeanDefinition.G ...

  2. 揭开js之constructor属性的神秘面纱

    揭开 constructor 在 Javascript 语言中,constructor 属性是专门为 function 而设计的,它存在于每一个 function 的prototype 属性中.这个 ...

  3. CAGradientLayer的一些属性解析

    CAGradientLayer的一些属性解析 iOS中Layer的坐标系统: 效果: - (void)viewDidLoad { [super viewDidLoad]; CAGradientLaye ...

  4. 对象的constructor属性

    对象的constructor属性, 最初是用来标识对象类型的. 比如 ,我们定义一个 Person类,然后实例化两个对象. function Person(name, age, job){this.n ...

  5. JavaScript类型检测, typeof操作符与constructor属性的异同

    *#type.js function Person(name, age) { this.name = name; this.age = age; } var d = {an: 'object'}; v ...

  6. CAGradientLayer的一些属性解析-b

    CAGradientLayer的一些属性解析 iOS中Layer的坐标系统: 效果: - (void)viewDidLoad { [super viewDidLoad]; CAGradientLaye ...

  7. JavaScript 构造函数 prototype属性和_proto_和原型链 constructor属性 apply(),call()和bind() 关键字this

    1.构造函数: 通常构造函数首字母需要大写,主要是为了区别ECMAScript的其它函数.(高程三 P145) 构造函数与其他函数的唯一区别,就在于调用它们的方式不同.只要通过new来调用,任何函数都 ...

  8. Activity设置全屏显示的两种方式及系统自带theme属性解析

    转载说明:原贴地址:http://blog.csdn.net/a_running_wolf/article/details/50480386 设置Activity隐藏标题栏.设置Activity全屏显 ...

  9. constructor 属性,判断是否为数组

    <!--你可以使用 constructor 属性来查看是对象是否为数组 (包含字符串 "Array"):--><p>constructor属性返回变量或对象 ...

随机推荐

  1. Sqlite3数据库查看工具

    SQLiteSpy     小巧便捷,免安装,占空间小. 推荐 http://www.softpedia.com/get/Internet/Servers/Database-Utils/SQLiteS ...

  2. 第一天接触stm32

    1.先新建一个文件夹,里面分别键六个名为COMSIS.FWLIB.HARDWARE.MDK.OBJ.USER的空文件夹 2.创建好文件夹就可以往里面添加文件啦,这三个文件夹放置如图所示的文件,其余三个 ...

  3. C#中get和set属性的作用

    c#在定义类时,通常要把类中声明的对象封装起来,使得外界不能访问这个属性.上述代码中如果去掉set部分,则外界只能读取name的值,如果去掉get部分,则只能给name赋值.这样就可以控制外界对私有属 ...

  4. Redis的启动及配置

    在redis已经安装完成的情况下,进入redis/bin目录下,输入命令: ./redis-server,就可以直接启动redis了,效果如图所示: 但是此时终端无法进行任何操作,按CTRL+c命令, ...

  5. springcloud+zuul+swagger 分布式接口文档

    https://gitee.com/didispace/swagger-butler 1.引用上面项目中的swagger 工具包 2.zuul 网关配置 zuul.routes.api-apiserv ...

  6. vue学习-自动行合并的table

    测试的效果 测试的html源码截图 v-table在tableGroup.js中定义,以下就render方法,行的所有单元格都在tableGrouper.js中处理 render:function(h ...

  7. 打造自己Django博客日记

    本教程使用的开发环境 本教程写作时开发环境的系统平台为 Windows 10 (64 位),Python 版本为 3.5.2 (64 位),Django 版本为 1.10.6. 建议尽可能地与教程的开 ...

  8. python xss相关的编码解码小脚本

    1.功能分析: 实际工作中经常会遇到alert()之类的函数被防火墙过滤,而把alert()转化为ascii码放到String.fromCharCode()中就可以绕过,之前会一个一个查ascii表, ...

  9. Redis和memcached缓存技术

    缓存的定义:缓存就是在内存中存储的数据备份,当数据没有发生本质变化的时候,我们避免数据的查询操作直接连接数据库,而是去    内容中读取数据,这样就大大降低了数据库的读写次数,而且从内存中读数据的速度 ...

  10. cvpr2018(转发一篇头条)

    CVPR 2018:腾讯图像去模糊.自动人像操纵最新研究 新智元 2018-05-29 14:13:04 新智元报道 来源:腾讯优图 编辑:江磊.克雷格 [新智元导读]即将在6月美国盐湖城举行的计算机 ...