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 相关文章推荐
网页中CDATA标记的说明
Sep 12 Javascript
关于jQuery object and DOM element
Apr 15 Javascript
jquery live()调用不存在的解决方法
Feb 26 Javascript
60个很实用的jQuery代码开发技巧收集
Dec 15 Javascript
JavaScript中的pow()方法使用详解
Jun 15 Javascript
使用CoffeeScrip优美方式编写javascript代码
Oct 28 Javascript
js获取客户端操作系统类型的方法【测试可用】
May 27 Javascript
原生js实现旋转木马轮播图效果
Feb 27 Javascript
Vuejs实现带样式的单文件组件新方法
May 02 Javascript
vue.js通过路由实现经典的三栏布局实例代码
Jul 08 Javascript
vue.js 图片上传并预览及图片更换功能的实现代码
Aug 27 Javascript
vue实现公告栏文字上下滚动效果的示例代码
Jun 16 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 编写的日历
2006/10/09 PHP
测试php函数的方法
2013/11/13 PHP
PHP编程风格规范分享
2014/01/15 PHP
PHP+Mysql+Ajax+JS实现省市区三级联动
2014/05/23 PHP
PHP return语句另类用法不止是在函数中
2014/09/17 PHP
CI框架验证码CAPTCHA辅助函数用法实例
2014/11/05 PHP
php处理复杂xml数据示例
2016/07/11 PHP
理解JavaScript的caller,callee,call,apply
2009/04/28 Javascript
JavaScript实现信用卡校验方法
2015/04/07 Javascript
12种JavaScript常用的MVC框架比较分析
2015/11/16 Javascript
js编写当天简单日历效果【实现代码】
2016/05/03 Javascript
浅谈angular4 ng-content 中隐藏的内容
2017/08/18 Javascript
如何抽象一个Vue公共组件
2017/10/17 Javascript
vue 1.0 结合animate.css定义动画效果
2018/07/11 Javascript
vue项目打包部署_nginx代理访问方法详解
2018/09/20 Javascript
Vue Object.defineProperty及ProxyVue实现双向数据绑定
2020/09/02 Javascript
jquery实现拖拽小方块效果
2020/12/10 jQuery
Django的URLconf中使用缺省视图参数的方法
2015/07/18 Python
Python中的getopt函数使用详解
2015/07/28 Python
Python中list初始化方法示例
2016/09/18 Python
Python中xrange与yield的用法实例分析
2017/12/26 Python
python OpenCV学习笔记之绘制直方图的方法
2018/02/08 Python
python3中获取文件当前绝对路径的两种方法
2018/04/26 Python
Python使用线程来接收串口数据的示例
2019/07/02 Python
基于Python下载网络图片方法汇总代码实例
2020/06/24 Python
详解html5 shiv.js和respond.min.js
2018/01/24 HTML / CSS
小米旗下精品生活电商平台:小米有品
2018/12/18 全球购物
求职信范文英文版
2014/01/05 职场文书
外语系大学生自荐信范文
2014/03/01 职场文书
超越自我演讲稿
2014/05/21 职场文书
企业优秀团员事迹材料
2014/08/20 职场文书
房屋租赁合同解除协议书
2014/10/11 职场文书
诉讼授权委托书
2014/10/15 职场文书
2014年化验员工作总结
2014/11/18 职场文书
MySQL 使用事件(Events)完成计划任务
2021/05/24 MySQL
vue3使用vuedraggable实现拖拽功能
2022/04/06 Vue.js