js constructor的实际作用分析


Posted in Javascript onNovember 15, 2011
<script> Function.prototype.createInstance = function(){ 
var T = function(){}; 
T.prototype = this.prototype; 
T.constructor = this; 
var o = new T(); 
this.apply(o, arguments); 
return o; 
}</script>

说下上面代码里面 T.constructor = this这句话,我感觉这句话没有什么实际作用,
本身T.constructor应该是为Funtion,为什么要给它设定为Funtion的实例呢,
<script> 
Function.prototype.$extends = function(p){ 
this.$super = p; 
var fn = function(){}; 
fn.prototype = p.prototype; 
this.prototype = new fn(); 
//这句是我自己加的,保证构造出子类实例的constructor依然指向子类的构造器函数 
this.prototype.constructor=this; 
//----------------------------- 
return this; 
}; 
function Animal(){ 
} 
function Cat(){ 
} 
Cat.$extends(Animal); 
var bb=new Cat(); 
alert(bb.constructor); 
//但是(this.prototype.constructor=this)这种做法通过bb这个对象无法回朔到Animal的原型 
//下面语句依然返回Cat这个函数,而不是Animal 
alert(bb.constructor.prototype.constructor) 
</script>

还有上面这句代码,我自己加了1句,修正了子类构造器依然指向子类函数,但是对象的原型链的回朔不能到达父类原型,解决办法是
去掉this.prototype.constructor=this;既不给原型设置constructor属性,而是给实例设置一个constructor属性,如下代码
<script> 
Function.prototype.$extends = function(p){ 
this.$super = p; 
var fn = function(){}; 
fn.prototype = p.prototype; 
this.prototype = new fn(); 
return this; 
}; 
function Animal(){ 
} 
function Cat(){ 
this.constructor= arguments.callee; 
} 
Cat.$extends(Animal); 
var bb=new Cat(); 
alert(bb.constructor); 
//这种做法可以通过bb这个对象回朔到Animal的原型 
alert(bb.constructor.prototype.constructor) 
</script>

最后分析下constructor的实际作用
<script> 
//定义函数 
var f=function(){ 
} 
//这里显示true,因为f的构造器是Funtion,f内部的原型属性_proto_被赋值为构造器的prototype也就是Function的prototype 
//instanceof检查f内部的_proto_是否与Function.prototype有共同的结点,如果有则返回true 
alert(f instanceof Function) 
//obj是f的实例 
var obj=new f; 
//obj内部的原型属性_proto_在new f时被赋值为f.prototype,显然f.prototype与Function.prototype没有共同的结点,因此显示false 
alert(obj instanceof Function) 
//为了让obj成为Function的实例也就是(obj instanceof Function)显示true 
//只需要f.prototype=Function.prototype 
f.prototype=Function.prototype; 
//但是我不推荐上面这种做法,因为对f.prototype的修改会破坏了Function.prototype,例如f.prototype.name="51js"会给Function的原型也加上1个name属性 
//正确的做法应该是下面这样,这样诸如f.prototype.name的修改就不会破坏Function的原型了 
f.prototype=new Function(); 
f.prototype.name="zhouyang"; 
/**关键是这里,再次调整constructor属性为f,维护constructor这种做法是为了保证obj能够正确回朔原型链, 
*假如我们要获取obj内部的原型链,但只知道obj,不知道obj是怎么实例化来的,由于obj内部的_proto_属性不可见,那么我们要获取obj内部原形只能通过obj.constructor来获取构造器,然后再获取构造器的prototype 
*1.如果我们加下面这句(f.prototype.constructor=f),回朔obj原型链 
*只能回朔1层原型链也就是obj.constructor.prototype(子类原型)-->obj.constructor.prototype.constructor.prototype(依然是子类原型),这样只能回朔1层原型链 
**/ 
f.prototype.constructor=f; 
obj=new f; 
alert("找到子类了---"+obj.constructor+"\n" 
+"找到的还是子类,无法找到父类---"+obj.constructor.prototype.constructor) 
alert(obj instanceof Function) 
/**2.如果我们用下面的方法在f定义里设置f的实例的constructor,而不是f原型的constructor 
*就可以回朔2层原型链也就是 obj.constructor.prototype(子类原型)-->obj.constructor.prototype.constructor.prototype(父类原型) 
*显然这种情况是符合对象原型继承链的情况的 
*/ 
f=function(){ 
this.constructor=arguments.callee; 
} 
f.prototype=new Function(); 
f.prototype.name="zhouyang"; 
obj=new f; 
alert("找到子类了---"+obj.constructor+"\n" 
+"找到父类了---"+obj.constructor.prototype.constructor) 
alert(obj instanceof Function) 
</script>

<script> 
//定义函数 
var f=function(){ 
} 
//这里显示true,因为f的构造器是Funtion,f内部的原型属性_proto_被赋值为构造器的prototype也就是Function的prototype 
//instanceof检查f内部的_proto_是否与Function.prototype有共同的结点,如果有则返回true 
alert(f instanceof Function) 
//obj是f的实例 
var obj=new f; 
//obj内部的原型属性_proto_在new f时被赋值为f.prototype,显然f.prototype与Function.prototype没有共同的结点,因此显示false 
alert(obj instanceof Function) 
//为了让obj成为Function的实例也就是(obj instanceof Function)显示true 
//只需要f.prototype=Function.prototype 
f.prototype=Function.prototype; 
//但是我不推荐上面这种做法,因为对f.prototype的修改会破坏了Function.prototype,例如f.prototype.name="51js"会给Function的原型也加上1个name属性 
//正确的做法应该是下面这样,这样诸如f.prototype.name的修改就不会破坏Function的原型了 
f.prototype=new Function(); 
f.prototype.name="zhouyang"; 
/**关键是这里,再次调整constructor属性为f,维护constructor这种做法是为了保证obj能够正确回朔原型链, 
*假如我们要获取obj内部的原型链,但只知道obj,不知道obj是怎么实例化来的,由于obj内部的_proto_属性不可见,那么我们要获取obj内部原形只能通过obj.constructor来获取构造器,然后再获取构造器的prototype 
*1.如果我们加下面这句(f.prototype.constructor=f),回朔obj原型链 
*只能回朔1层原型链也就是obj.constructor.prototype(子类原型)-->obj.constructor.prototype.constructor.prototype(依然是子类原型),这样只能回朔1层原型链 
**/ 
f.prototype.constructor=f; 
obj=new f; 
alert("找到子类了---"+obj.constructor+"\n" 
+"找到的还是子类,无法找到父类---"+obj.constructor.prototype.constructor) 
alert(obj instanceof Function) 
/**2.如果我们用下面的方法在f定义里设置f的实例的constructor,而不是f原型的constructor 
*就可以回朔2层原型链也就是 obj.constructor.prototype(子类原型)-->obj.constructor.prototype.constructor.prototype(父类原型) 
*显然这种情况是符合对象原型继承链的情况的 
*/ 
f=function(){ 
this.constructor=arguments.callee; 
} 
f.prototype=new Function(); 
f.prototype.name="zhouyang"; 
obj=new f; 
alert("找到子类了---"+obj.constructor+"\n" 
+"找到父类了---"+obj.constructor.prototype.constructor) 
alert(obj instanceof Function) 
</script>结论constructor的作用就是维护对象的原型链

向果果和winter赐教一下,不知理解的是否正确哈,另外我看大家常说的原型的污染到底指的是什么??
作用的话下面这个或许可以说明
<script> 
var f = function(x){} 
f.prototype={}; 
alert((new f).constructor); 
f.prototype.constructor=f; 
alert((new f).constructor); 
</script>
Javascript 相关文章推荐
arguments对象
Nov 20 Javascript
通过DOM脚本去设置样式信息
Sep 19 Javascript
Javascript类定义语法,私有成员、受保护成员、静态成员等介绍
Dec 08 Javascript
jQuery Form 页面表单提交的小例子
Nov 15 Javascript
利用JS实现数字增长
Jul 28 Javascript
javascript简单写的判断电话号码实例
May 24 Javascript
简单谈谈require模块化jquery和angular的问题
Jun 23 jQuery
使用nvm管理不同版本的node与npm的方法
Oct 31 Javascript
微信小程序自定义弹窗wcPop插件
Nov 19 Javascript
详解如何更好的使用module vuex
Mar 27 Javascript
Vue按时间段查询数据组件使用详解
Aug 21 Javascript
使用JS实现简易计算器
Jun 14 Javascript
浅谈Javascript面向对象编程
Nov 15 #Javascript
js Html结构转字符串形式显示代码
Nov 15 #Javascript
Js 时间间隔计算的函数(间隔天数)
Nov 15 #Javascript
jQuery源码分析-05异步队列 Deferred 使用介绍
Nov 14 #Javascript
jQuery源码分析-04 选择器-Sizzle-工作原理分析
Nov 14 #Javascript
jQuery源码分析-03构造jQuery对象-工具函数
Nov 14 #Javascript
jQuery源码分析-03构造jQuery对象-源码结构和核心函数
Nov 14 #Javascript
You might like
PHP 采集程序中常用的函数
2009/12/09 PHP
PHP设计模式之装饰者模式
2012/02/29 PHP
分享PHP源码批量抓取远程网页图片并保存到本地的实现方法
2015/12/01 PHP
php模拟post上传图片实现代码
2016/06/24 PHP
php支付宝在线支付接口开发教程
2016/09/19 PHP
在php7中MongoDB实现模糊查询的方法详解
2017/05/03 PHP
[原创]PHP实现生成vcf vcard文件功能类定义与使用方法详解【附demo源码下载】
2017/09/02 PHP
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/02/09 Javascript
jQuery中after()方法用法实例
2014/12/25 Javascript
jQuery中DOM树操作之复制元素的方法
2015/01/23 Javascript
原生js和jQuery写的网页选项卡特效对比
2015/04/27 Javascript
JavaScript动态检验密码强度的实现方法
2016/11/09 Javascript
nodeJS微信分享
2017/12/20 NodeJs
在Bootstrap开发框架中使用dataTable直接录入表格行数据的方法
2018/10/25 Javascript
在Echarts图中给坐标轴加一个标识线markLine
2020/07/20 Javascript
vant时间控件使用方法详解
2020/12/24 Javascript
[01:32]寻找你心中的那团火 DOTA2 TI9火焰传递活动今日开启
2019/05/16 DOTA
Python实现遍历windows所有窗口并输出窗口标题的方法
2015/03/13 Python
用Python登录好友QQ空间点赞的示例代码
2017/11/04 Python
python Matplotlib画图之调整字体大小的示例
2017/11/20 Python
浅谈python数据类型及类型转换
2017/12/18 Python
Python中numpy模块常见用法demo实例小结
2019/03/16 Python
详解python中的线程与线程池
2019/05/10 Python
class类在python中获取金融数据的实例方法
2020/12/10 Python
css3实现书本翻页效果的示例代码
2021/03/08 HTML / CSS
加拿大便宜的隐形眼镜商店:Clearly
2016/09/15 全球购物
美国男装连锁零售商:Men’s Wearhouse
2016/10/14 全球购物
中职生自荐信
2013/10/13 职场文书
考博专家推荐信
2014/05/10 职场文书
学雷锋活动倡议书
2014/08/30 职场文书
2014年自愿离婚协议书范本
2014/09/25 职场文书
家长通知书家长意见
2014/12/30 职场文书
讲座开场白台词和结束语
2015/05/29 职场文书
2015年法律事务部工作总结
2015/07/27 职场文书
医学生自荐信范文(2016精选篇)
2016/01/28 职场文书
java中用float时,数字后面加f,这样是为什么你知道吗
2021/09/04 Java/Android