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. Sql 记录死锁

    记录死锁 DBCC errorlog DBCC TRACEON (1204, 1222, -1); DBCC tracestatus 关闭跟踪标记DBCC TRACEOFF

  2. 构建你的spring boot代码

    Spring boot不需要任何特定的代码布局来工作.然而,有一些最佳实践可以帮助您. 1.避免使用缺省包 当一个类不包含包声明时,它被认为是在“缺省包”中.“默认包”的使用通常是不鼓励的,应该避免. ...

  3. es6数值

    ES6在Number对象上,新提供了Number.isFinite()和Number.isNaN()两个方法,用来检查Infinite和NaN这两个特殊值. Number.isFinite(15); ...

  4. maple推导剑桥模型塑性势函数

    with(DEtools); Parameter(M); de := diff(q(p), p)+(M^*p^-q(p)^)/(*p*q(p)) = ; dsolve({de, q(px) = }, ...

  5. 学以致用三十-----pycharm创建django项目忘记添加app

    记忆力有时候真的不是很好.因此有些操作步骤还是记录下来好了. pycharm版本-----2018.2.4 创建django项目 file-----newproject----- 创建的时候,appl ...

  6. pdf流文件的展示、下载、打印;html转为pdf

    背景:合同(后台返回pdf流文件)展示.下载.打印,基于angular4 场景区分: 1.checkout页面 —— post接口,入参为offering.shippingInfo.invoice等( ...

  7. 使用IDEA进行版本控制

    1.使用IDEA进行版本控制 创建git repository add-添加到暂存区 commit-提交到本地库 push-推送指定远程库(自己的) idea上的pull指的是合并(merge),并非 ...

  8. ASCII、Unicode、UTF-8以及Python3编码问题

    编码问题,其实的确是个很烦人的问题,一开始觉得不需要看,到后来出现问题,真的是抓狂, 而像我们这些刚刚涉及到这些问题的小白来说,更是无从下手,所以查阅资料,总结理解下各个概念以及Python3的编码问 ...

  9. POJ 1067 威佐夫博弈

    点这里去看题 套公式,判断是否为奇异组合 #include<stdio.h> #include<algorithm> #include<math.h> #inclu ...

  10. kubernetes CRD学习笔记

    前言 最近在极客时间订阅了kubernetes的专栏,这篇文章是想记录一下自己学习CRD(custom resource definition)的过程,加深一下记忆. 准备工作 首先安装一下我们用的g ...