constructor属性解析

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏HTML5学堂

JS实战开发经验!函数多参数传参技巧

HTML5学堂-码匠:掌握JavaScript代码的你,一定编写封装过函数,为了提升函数的控制性,必不可少的就是参数,必选可选的一大堆参数罗列出来,函数调用貌似...

3985
来自专栏nummy

Python 弱引用的使用

和许多其它的高级语言一样,Python使用了垃圾回收器来自动销毁那些不再使用的对象。每个对象都有一个引用计数,当这个引用计数为0时Python能够安全地销毁这个...

1902
来自专栏技术专栏

Scala入门与进阶(四)- Scala面向对象

1072
来自专栏pangguoming

java正则校验,密码必须由字母和数字组成

一个匹配数字和字母密码的正则表达式 2011 年 12 月 14 日 | Filed under: 正则表达式 and tagged with: 密码 , ...

6126
来自专栏TungHsu

这或许是对小白最友好的python入门了吧——15,嵌套

有些时候我们的数据可能会很复杂,单独的字典列表等可能无法满足我们的需求,这个时候我们就需要将字典列表等融合在一起,这个叫做嵌套。 (一)字典列表 我们上一期说的...

3574
来自专栏小樱的经验随笔

python学习笔记之运算符

目录 前言 软件环境 身份运算符 算术运算符 比较运算符 位移运算符 自变运算符 位运算符 逻辑运算符 成员关系运算符 Python真值表 最后 前言 在前面的...

3313
来自专栏Java爬坑系列

【Java】单词倒序输出

  如何将一段单词倒序输出?把“Hello Java Hello China”变成“China Hello Java Hello”?   看起来好像很简单,只需...

3288
来自专栏一“技”之长

Swift讲解专题八——闭包 原

        Swift中的闭包是有一定功能的代码块,这十分类似于Objective-C中的block语法。Swift中的闭包语法风格十分简洁,其作用和函数的...

592
来自专栏王亚昌的专栏

类模板学习总结

1.类模板就是给普通的类加上一个参数,参数可以是未知数据类型标识(如int, string,char, class等),也可以是已知数据类型的值,在下面的第二个...

1042
来自专栏搞前端的李蚊子

js取整并保留两位小数的方法

js 四舍五入函数 toFixed(),里面的参数 就是保留小数的位数。注意 toFixed()方法只针对数字类型,如果是字符类型需要使用Number()等方法...

4247

扫码关注云+社区

领取腾讯云代金券