Javascript的prototype的研究

Max_Mac原创,转载请注明出处。


前言:以下的例子的运行结果都来自chrome


先看几个例子:

例子1:

var A=function(){};
A.prototype.test=function(){};
var a1=new A();
var a2=new A();
a1.test="123";
alert(a1.test);//"123"
alert(a2.test);//"function(){}"

例子2:

var A=function(){};
A.prototype.test=function(){};
var a1=new A();
var a2=new A();
a1.test.text="123"";
alert(a1.test.text);//"123"
alert(a2.test.text);//"123"
alert(A.prototype.test.text);//"123"

例子3:

var A=function(){};
var B=function(){};
A.prototype.text="abc";
B.prototype.text="bcd";
B.prototype=A.prototype;
A.prototype.text="cba";
alert(B.prototype.text);//"cba",这个例子看似简单,但可以说明B继承A时,为什么不可以B.prototype=A.prototype

例子4:

Function.prototype.text="function";
var d=function(){};
alert(d.prototype.text);//"undefined"
alert(d.text);//"function"
alert(d.__proto__.text);//"function"
Function.prototype.text="function2";
alert(d.__proto__.text);//"function2",这个比较特殊

结合例子124可以得出结论,function A(){};var a=new A()进行了如下的操作:

a.__proto__={};
for(var name in A.prototype){
a.__proto__[name]=A.prototype[name];
}

回看这篇文章,这段理解是错误的。例子124并不能得出这样的结论。之所以得出这样错误的结论可能是由于1产生的误导(误认为修改a1.__proto__中的test,并没有影响a2.__proto__),事实上a1.__proto__a2._proto__都指向A.prototype,而a1.test="123";这样的语句实际为a1对象添加了新变量test并覆盖了a1.__proto__.test,并非是修改修改a1.__proto__中的test。以下代码可以证明:

var A=function(){};  
A.prototype.test="1";  
var a1=new A();  
alert(a1.test);//"1"
A.prototype.test="2";
alert(a1.test);//"2"
A.prototype.newProp="hello";
alert(a1.newProp);//"2"

所以下面一段理解也是错误的,图也是错误的。《前端开发必须知道的JS(一) 原型和继承这篇文章讲解的很透彻。(本段写于2017731日)


现在要使B继承A,可以定义function B(){};B.prototype=new A();var b=new B(),同样可知:

b.__proto__={};
for(var name in a){
b.__proto__[name]=a[name]//其中b.__proto__.__proto__=a.__proto__
}

A、Bab之间的关系图如下:



新图如下:(修改于2017731日)



看了以上的关系图有哪些启发呢?

1.toStringA.prototype中的一个引用类型的对象(函数),a.toString以及b.toString都是引用了这个对象,如果将来还有C继承Bc.toString也将引用这个对象;

2.NameA.prototy中的一个基本类型的变量,每一个A的实例a都有不同的拷贝,而B的实例b.name取决于B.prototypeA的实例a

3.A的代码中为a赋值的anum如果是一个引用类型的对象,每一个B的实例b都是指向这个对象;


再探讨一下Object.prototype

__defineGetter__: function __defineGetter__() { [native code] }
__defineSetter__: function __defineSetter__() { [native code] }
__lookupGetter__: function __lookupGetter__() { [native code] }
__lookupSetter__: function __lookupSetter__() { [native code] }
constructor: function Object() { [native code] }
hasOwnProperty: function hasOwnProperty() { [native code] }
isPrototypeOf: function isPrototypeOf() { [native code] }
propertyIsEnumerable: function propertyIsEnumerable() { [native code] }
toLocaleString: function toLocaleString() { [native code] }
toString: function toString() { [native code] }
valueOf: function valueOf() { [native code] }


要分清楚A.prototypeA.__proto__ A.prototype.__proto__a.__proto__a.__proto__.__proto__

A.prototype.__proto__===Object.prototype

A.__proto__==Function.prototype(是==,而不是===

a.__proto__===A.prototype

a.__proto__.__proto__===Object.prototype


A.__proto__===Function.prototype

验证方法很简单:

var A=function(){};  

alert(A.__proto__===Function.prototype)

其中比较特殊的的是Function.prototype,这是一个函数对象(而不是一个普通对象)function Empty(){},而所有函数的__proto__也是这个函数对象。


原本想再写一些关于为什么javascript使用基于prototype的继承,以及这样的继承有哪些优缺点。不过这样的论题似乎有点大,需要从很多方面去思考和探讨这个问题,所以暂时就不写了,等以后思考的多了,再细细把它写下来。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值