JavaScript系列----面向对象的JavaScript(2)
2015-04-03 17:24
253 查看
本文中心:
这篇文章比较难懂,所以读起来比较晦涩。所以,我简单列一下提纲:
在第一部分,从函数原型开始谈起,目的是想搞明白,这个属性是什么,为什么存在,在创建对象的的时候起到了什么作用!
在第二部分,阅读的时候,请分清楚__proto__和内置对象的区别;搞清楚这点。然后,我们再一点点分析__proto__属性。
第三部分,本来不在我写作的范围,但是看到网上的很多文章在继承的时候,使用的方法五花八门。所以来谈一下,Object.create()这个方法的好处。
那么这个函数的原型到底是什么,它又有什么用呢?
函数的原型是什么?
用代码证明:函数原型是一个对象。
从上面的输出结果中,我们得出函数的原型是一个对象。那么,这个对象本身有什么属性呢?
我们知道,任何一个对象都具有最基本的方法,比如toString().valueof()...既然函数原型是对象类型,那么它肯定也具有这些基本的方法...
所以这些方法是从哪里来的呢?要想搞清楚这些,那么我们就必须要从Object()的原型谈起!
上面这幅图片,帮我们认清楚了Object()函数的原型,这个函数原型本身不具有任何属性,但是其具有一些很基本的方法,这些方法有什么用,这里暂且不论。但是到目前为此,请记住一点:函数原型是一个对象。因为只有知道了最基本的这一点,我们下面的讨论才具有意义。
函数原型有什么用?
只是知道函数原型是一个对象,才只是开始,因为我们想知道的是:函数的原型对象什么用,为什么要要设计这么个东东!!
看下面的一段代码,我们跟着代码来分析:
这里出现了一个很奇怪的现象...object对象没有toString()函数,这里在输出的时候为什么不报错呢?ok!看下面一副图片:
在object这个对象中,其具有一个__proto__属性,这个属性是哪里来的?......等等......有没有觉得__proto__的值和Object.prototype的值时惊人的相似呢。难道这是巧合吗,还是说他们本来就是同一个对象呢!!!我们来测试一下:
事实再一次证明,世上没那么多的巧合!!object.__ptoto__和Object.prototype真的指向的是同一个对象。
现在我们解决了一个问题,就是object.toSring()这个函数,真正的来源是Object.prototype。那么object对象为什么能访问Object.prototype中的方法呢...要回答这个问题,需要弄清楚两件事情:
第一,当newObject()到底发生了什么?
第二:__proto__这个属性起到了什么作用?
要想弄明白上面的两个问题,我们依然需要分析程序
当执行这句话的时候,解释器帮我们干了三样活:
(1).开辟了一些内存空间给object;
(2).将this指针指向object(暂且不论这点,this指针我们以后也会开单题来说).Ok.现在知道了new有什么用了;
(3).将object添加一个内置属性属性,__proto__的值和内置属性的值总是相等的;
知道了当newObject()的时候,解释器帮我们给对象添加了一个内置属性,接下来解决第二个问题,内置属性[[__proto__]]有什么用?
看下面的代码
在上面的例子中,object一直没有变,但是其属性__proto__是指向的对象变了。根据上例,我们可以得出结论,对象是可以访问到属性__proto__指向的对象所拥有的变量的,而且使用的时候就像是其自己的属性一样。
总结以上,我们可以得出结论:
每个函数都拥有一个属于自己的原型,这个原型的实质是一个对象,当该函数被当做构造函数使用(即new调用)的时候,所生成的实例会有一个内置的属性,当访问这个对象的时候,如果在实例中没有找到对应属性,则会根据内置属性,查找内置属性所指向的对象,一直到最上层若找不到则返回undefined.(严格模式的时候会报错).
看下面的一段代码:
上述代码,证明了constructor这个属性是真实存在的,且这个属性的值初始化为构造函数本身。那么这个属性有什么很重要的意义吗?再看下面的码:
由上面例子可以得出,constructor属性只是标识原型是归属于哪个函数的,这个属性虽然是解释器给我们默认的,但是相对来说没有那么重要,甚至说起来可以是一点用处都没有。对于一个函数,在刚创建的时候总是这个样子的。
根据1.1部分,我们知道函数的原型,在函数实例化的时候会被赋值给实例的内置属性的。假设有两个类A和B,代码如下:
A和B分别是两个类的构造函数,他们此时在内存中的结构如下图所示:
现在如果我们想让B类成为A的子类,该如何做呢?首先,我们应该认识到一点,如果B是A的子类,那么B就应该能访问A中的属性和方法。父类A中有属性a和方法getA(),那么子类B中也应该有属性a且能访问方法getA();如果我们能实现如下图所示的结构是否就能做到B类继承A类呢?
与上图相比,仅仅修改了B.prototype中的【【__proto__】】.然后一切的一切都自然而然的发生了。总之,子类B为了继承A做了两样活:子类B类通过A.call();这一步借用A的构造函数拥有的A类的变量,又通过修改原型中的【【__proto__】】才做到能访问A类中的函数..想到这里不得不说一句,好伟大的设计。如果只是为了实现继承,有N多种方法能实现,但是请注意,如果考虑内存中的分配情况以及效率和程序的健壮性,那么就只有一个函数能够完美的做到图中所示的那样。这个函数就是Object.create()函数,这个函数的宿命就是为了实现继承。
为什么这么说呢,请看第二部分慢慢解析!!
1.这个属性是什么性质的属性?访问器属性or数据属性?
2.这个属性存在在哪里?是每个对象都有,还是在整个内存中仅有一份。
3.这个属性与内置属性有什么关系?
如果你对上面的上个问题很困惑,或者你认为__proto__就是内置属性的话,那么我们还是花一点时间正正三观吧。
看到上面的输出结果,你是否已经接受了__proto__就是一个访问器属性呢....如果你还不相信..那么接着看,这只是践踏你世界观的开始!!!
请回答?为什么显示删除成功了,typeofobject.__proto__还是输出object呢?
ok!!要理解透彻这些,我们插入一些delete运算符的知识.
ECMAScript规定:delete运算符删除对以前定义的对象属性或方法的引用,而且delete运算符不能删除开发者未定义的属性和方法。
那么什么情况下,delete会起作用呢?
delelte运算如果想正常操作必须满足三个条件:1,该属性是我们写的,即该属性存在。2.删除的是一个对象的属性或方法。3.该属性在配置时是可以删除的,即(configurable=true)的情况下可以删除。
那么,上面的例题中,返回值为true.,它符合上面的三个条件吗?
对于1,该属性我们是可以访问的,所以,证明该属性存在。
对于2,__proto__是某个对象的属性。
对于3:因为configurable=true,所以也是符合的。
ok!上面的三点都符合,在返回值等于true的情况下,删除还是失败了呢!因为还有下面一种情况,就是在对象上删除一个根本不存在的于自身的属性也会返回true!
看到没有,这两个例子在输出结果上很相似呢?因为__proto__属性存在于该对象上的原型上面,所以,该对象可以访问。但是不能删除该属性。如果想删除该属性,那么请在Object.prototype上删除。这个保证能删除成功。
为了证实这一点,我们再看一下
我们可以发现,在Object.prototype删除__proto__属性后。object上也无法访问了。这是因为,所以对象都有一个共同的原型Object.prototype.在这个上面删除__proto__,那么所有的对象也都不具有这个__proto__属性了。
这也就证明了,内存中仅存一份__proto__属性,且该属性定义在Object.prototype对象上。
但是请记住两点:
1.内置对象不可见,但是内置对象总是存在的。
2.__proto__如果存在,那么它的值就是内置对象,但是这个__proto__并不总是存在的。
如果你一定认为__proto__就是内置对象,也可以,但是请保证两点:不要在程序的任何地方用__proto__属性。或者,如果你一定要用__proto__这个属性的话,请保证永远不要修改Object.prototype中的__proto__!!
如果你不能保证这两点,请远离__proto__.因为,一旦有人不遵守约定的话,这个bug的危害代价太大。比如,下面这样...
上面是一段,毫无问题的代码...但是如果有一个小白用户,在某一天执行了下面一句代码,
这个函数在W3C中这个函数是怎么定义的呢?
参数
prototype
必需。要用作原型的对象。可以为null。
descriptors
可选。包含一个或多个属性描述符的JavaScript对象。
“数据属性”是可获取且可设置值的属性。数据属性描述符包含value特性,以及writable、enumerable和configurable特性。如果未指定最后三个特性,则它们默认为false。只要检索或设置该值,“访问器属性”就会调用用户提供的函数。访问器属性描述符包含set特性和/或get特性。有关详细信息,请参阅Object.defineProperty函数(JavaScript)。
这是这个函数在W3C中的定义,我来举个例子来说明这个函数怎么用吧!!!
上述代码运行完毕之后,returnObject在内存中的结构如图所示:
看看上面这张图,在类比1.3中的最后一张图,如下:
发现是不是,惊人的相似...所以,知道Objece.create()的强大了吧!!我们分析过,下面这张图是实现继承的完美状态,而Object.create()就是为了做到这些,专业为继承而设计出来的函数。
下面是一段用Object.create()函数实现子类继承父类的代码;
varA=function(){
}
A.prototype.say=function(){
return'hello';
}
varB=function(){
}
extend(B,A);
varb=newB();
b.say();//hello
Ok!我知道,你能用N多种方法实现继承,但是请记住,在继承的时候请不要用__proto__这个属性,因为它没你想象中俺么可靠。如果你想获得一个对象的原型,那么这个方法可以做到,Object.getPrototypeOf。与之对应的是Object.setPrototypeOf方法。
也许你也会说,Object.setPrototypeOf方法可以在远离__proto__的情况下实现继承啊啊...如果你在看到它的源代码你还会这么说吗?
总结:
整篇文章,从prototype谈起,分析了函数的prototype的类型与作用(这个大家都在谈)。
在第二部分,我们分析了__proto__,得到的结果,内置属性和__proto__根本不是一回事。__proto__这个属性不可靠..撇开,这个属性是非标准属性不说,这个属性隐藏的bug就能致人于死地,所以,在写程序时,请谨记一点,珍爱生命,远离__proto__.
在最后,我们浅谈了一下,用Object.create()实现继承的好处。这个部分,很难讲的清楚,需要慢慢去体会。
在下一篇中,我们会分析,为什么会说JS中一切皆是对象!。。。
这篇文章比较难懂,所以读起来比较晦涩。所以,我简单列一下提纲:
在第一部分,从函数原型开始谈起,目的是想搞明白,这个属性是什么,为什么存在,在创建对象的的时候起到了什么作用!
在第二部分,阅读的时候,请分清楚__proto__和内置对象的区别;搞清楚这点。然后,我们再一点点分析__proto__属性。
第三部分,本来不在我写作的范围,但是看到网上的很多文章在继承的时候,使用的方法五花八门。所以来谈一下,Object.create()这个方法的好处。
1.函数原型
1.1.函数特有的prototype属性
标题中所谓的特有,指的是只有函数才具有prototype属性,ECMAScript标准规定每个函数都拥有一个属于自己的原型(prototype)。那么这个函数的原型到底是什么,它又有什么用呢?
函数的原型是什么?
用代码证明:函数原型是一个对象。
console.log(typeofObject.prototype);//"object",这里用到了Object()函数。 console.log(Object.prototypeinstanceofObject)//true
从上面的输出结果中,我们得出函数的原型是一个对象。那么,这个对象本身有什么属性呢?
我们知道,任何一个对象都具有最基本的方法,比如toString().valueof()...既然函数原型是对象类型,那么它肯定也具有这些基本的方法...
所以这些方法是从哪里来的呢?要想搞清楚这些,那么我们就必须要从Object()的原型谈起!
上面这幅图片,帮我们认清楚了Object()函数的原型,这个函数原型本身不具有任何属性,但是其具有一些很基本的方法,这些方法有什么用,这里暂且不论。但是到目前为此,请记住一点:函数原型是一个对象。因为只有知道了最基本的这一点,我们下面的讨论才具有意义。
函数原型有什么用?
只是知道函数原型是一个对象,才只是开始,因为我们想知道的是:函数的原型对象什么用,为什么要要设计这么个东东!!
看下面的一段代码,我们跟着代码来分析:
varobject=newObject();//new一个对象 console.log(object.toString());//输出这个对象,firefox控制台下输出结果[obejctobject]
这里出现了一个很奇怪的现象...object对象没有toString()函数,这里在输出的时候为什么不报错呢?ok!看下面一副图片:
在object这个对象中,其具有一个__proto__属性,这个属性是哪里来的?......等等......有没有觉得__proto__的值和Object.prototype的值时惊人的相似呢。难道这是巧合吗,还是说他们本来就是同一个对象呢!!!我们来测试一下:
varobject=newObject(); console.log(object.__proto__==Object.prototype);//true.
事实再一次证明,世上没那么多的巧合!!object.__ptoto__和Object.prototype真的指向的是同一个对象。
现在我们解决了一个问题,就是object.toSring()这个函数,真正的来源是Object.prototype。那么object对象为什么能访问Object.prototype中的方法呢...要回答这个问题,需要弄清楚两件事情:
第一,当newObject()到底发生了什么?
第二:__proto__这个属性起到了什么作用?
要想弄明白上面的两个问题,我们依然需要分析程序
varobject=newObject();
当执行这句话的时候,解释器帮我们干了三样活:
(1).开辟了一些内存空间给object;
(2).将this指针指向object(暂且不论这点,this指针我们以后也会开单题来说).Ok.现在知道了new有什么用了;
(3).将object添加一个内置属性属性,__proto__的值和内置属性的值总是相等的;
知道了当newObject()的时候,解释器帮我们给对象添加了一个内置属性,接下来解决第二个问题,内置属性[[__proto__]]有什么用?
看下面的代码
varobject=newObject(); varproto1={}; proto1.name='张三' object.__proto__=proto1; console.log(object.name);//张三 varproto2={}; proto2.name='李四' object.__proto__=proto2; console.log(object.name);//李四
在上面的例子中,object一直没有变,但是其属性__proto__是指向的对象变了。根据上例,我们可以得出结论,对象是可以访问到属性__proto__指向的对象所拥有的变量的,而且使用的时候就像是其自己的属性一样。
总结以上,我们可以得出结论:
每个函数都拥有一个属于自己的原型,这个原型的实质是一个对象,当该函数被当做构造函数使用(即new调用)的时候,所生成的实例会有一个内置的属性,当访问这个对象的时候,如果在实例中没有找到对应属性,则会根据内置属性,查找内置属性所指向的对象,一直到最上层若找不到则返回undefined.(严格模式的时候会报错).
1.2.函数原型prototype的constructor属性
在创建一个新的函数的时候,这个函数的原型中会有一个constructor属性,那么这个属性是否有存在的意义呢?看下面的一段代码:
varPerson=function(){}; console.log(Person.prototype.constructor);//functionconstructor是一个函数 console.log(Person.prototype.constructor===Person);//truePerson.prototype.constructor===Person
上述代码,证明了constructor这个属性是真实存在的,且这个属性的值初始化为构造函数本身。那么这个属性有什么很重要的意义吗?再看下面的码:
varPerson=function(){ }; varxiaoming=newPerson(); console.log(xiaominginstanceofPerson);//true Person.prototype.constructor=null; console.log(xiaominginstanceofPerson);//true
由上面例子可以得出,constructor属性只是标识原型是归属于哪个函数的,这个属性虽然是解释器给我们默认的,但是相对来说没有那么重要,甚至说起来可以是一点用处都没有。对于一个函数,在刚创建的时候总是这个样子的。
1.3prototype的宿命---用于继承
有些事情在你出生的那一刻就已经注定要发生。prototype在出生之初就已经注定其宿命。下面让我们来谈谈这所谓的宿命吧!!根据1.1部分,我们知道函数的原型,在函数实例化的时候会被赋值给实例的内置属性的。假设有两个类A和B,代码如下:
//A函数如下 varA=function(a){ this.a=a; } A.prototype.getA=function(){ returnthis.a; } //B函数如下 varB=function(a,b){ A.call(this,a);//借用A类构造函数,很重要的一点!!! this.b=b; } B.prototype.getB=function(){ returnthis.b; }
A和B分别是两个类的构造函数,他们此时在内存中的结构如下图所示:
现在如果我们想让B类成为A的子类,该如何做呢?首先,我们应该认识到一点,如果B是A的子类,那么B就应该能访问A中的属性和方法。父类A中有属性a和方法getA(),那么子类B中也应该有属性a且能访问方法getA();如果我们能实现如下图所示的结构是否就能做到B类继承A类呢?
与上图相比,仅仅修改了B.prototype中的【【__proto__】】.然后一切的一切都自然而然的发生了。总之,子类B为了继承A做了两样活:子类B类通过A.call();这一步借用A的构造函数拥有的A类的变量,又通过修改原型中的【【__proto__】】才做到能访问A类中的函数..想到这里不得不说一句,好伟大的设计。如果只是为了实现继承,有N多种方法能实现,但是请注意,如果考虑内存中的分配情况以及效率和程序的健壮性,那么就只有一个函数能够完美的做到图中所示的那样。这个函数就是Object.create()函数,这个函数的宿命就是为了实现继承。
为什么这么说呢,请看第二部分慢慢解析!!
2.__proto__属性和内置属性的区别
2.1.你真的了解__proto__这个属性吗?
如果你认为自己很了解这个属性,那么请思考以下几个问题?1.这个属性是什么性质的属性?访问器属性or数据属性?
2.这个属性存在在哪里?是每个对象都有,还是在整个内存中仅有一份。
3.这个属性与内置属性有什么关系?
如果你对上面的上个问题很困惑,或者你认为__proto__就是内置属性的话,那么我们还是花一点时间正正三观吧。
2.1.1.证明1:__proto__是访问器属性
看下面一段代码:vardescriptor=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__"); console.log(descriptor);//输出结果:
configurable | true |
enumerable | false |
get | function(){[nativecode]} |
set | function(){[nativecode]} |
看到上面的输出结果,你是否已经接受了__proto__就是一个访问器属性呢....如果你还不相信..那么接着看,这只是践踏你世界观的开始!!!
2.1.2.证明2:__proto__属性在内存中仅存一份
从证明1的输出结果中,我们知道configurable=true;这也就告诉我们这个对象是可以被删除的...下面看一段代码:varobject={}; varresult=deleteobject.__proto__; console.log(result);//true console.log(typeofobject.__proto__)//object.
请回答?为什么显示删除成功了,typeofobject.__proto__还是输出object呢?
ok!!要理解透彻这些,我们插入一些delete运算符的知识.
ECMAScript规定:delete运算符删除对以前定义的对象属性或方法的引用,而且delete运算符不能删除开发者未定义的属性和方法。
那么什么情况下,delete会起作用呢?
delelte运算如果想正常操作必须满足三个条件:1,该属性是我们写的,即该属性存在。2.删除的是一个对象的属性或方法。3.该属性在配置时是可以删除的,即(configurable=true)的情况下可以删除。
那么,上面的例题中,返回值为true.,它符合上面的三个条件吗?
对于1,该属性我们是可以访问的,所以,证明该属性存在。
对于2,__proto__是某个对象的属性。
对于3:因为configurable=true,所以也是符合的。
ok!上面的三点都符合,在返回值等于true的情况下,删除还是失败了呢!因为还有下面一种情况,就是在对象上删除一个根本不存在的于自身的属性也会返回true!
varobject={ }; Object.prototype.x={}; varresult=deleteobject.x; console.log(result);//true.console.log(object.x);//object
看到没有,这两个例子在输出结果上很相似呢?因为__proto__属性存在于该对象上的原型上面,所以,该对象可以访问。但是不能删除该属性。如果想删除该属性,那么请在Object.prototype上删除。这个保证能删除成功。
为了证实这一点,我们再看一下
varobject={};
console.log(typeofobject.__proto__);//object
deleteObject.prototype.__proto__;
console.log(typeofobject.__proto__);//undefined删除成功。
我们可以发现,在Object.prototype删除__proto__属性后。object上也无法访问了。这是因为,所以对象都有一个共同的原型Object.prototype.在这个上面删除__proto__,那么所有的对象也都不具有这个__proto__属性了。
这也就证明了,内存中仅存一份__proto__属性,且该属性定义在Object.prototype对象上。
2.1.3.这个属性与内置属性有什么关系
从某种程度上来说,__proto__如果存在,那么它总是等于该对象的内置属性。而且在上一篇文章中我们也点出了一点,改变__proto__的指向也能改变内置属性的指向。所以,如果你固执的把__proto__认为就是内置对象,那也无可厚非。但是请记住两点:
1.内置对象不可见,但是内置对象总是存在的。
2.__proto__如果存在,那么它的值就是内置对象,但是这个__proto__并不总是存在的。
如果你一定认为__proto__就是内置对象,也可以,但是请保证两点:不要在程序的任何地方用__proto__属性。或者,如果你一定要用__proto__这个属性的话,请保证永远不要修改Object.prototype中的__proto__!!
如果你不能保证这两点,请远离__proto__.因为,一旦有人不遵守约定的话,这个bug的危害代价太大。比如,下面这样...
varA=function(){
}
A.prototype.say=function(){
return'hello';
}
varB=function(){
}
//子类继承父类
functionextend(subClass,superClass){
varobject={
};
object.__proto__=superClass.prototype;
subClass.prototype=object;
subClass.prototype.constructor=subClass;
}
extend(B,A);//B继承A
varb=newB();
b.say();
上面是一段,毫无问题的代码...但是如果有一个小白用户,在某一天执行了下面一句代码,
varA=function(){
}
A.prototype.say=function(){
return'hello';
}
varB=function(){
}
functionextend(subClass,superClass){
varobject={
};
object.__proto__=superClass.prototype;
subClass.prototype=object;
subClass.prototype.constructor=subClass;
}
deleteObject.prototype.__proto__;//或则其他的等等
extend(B,A);
varb=newB();
b.say();//TypeError:b.sayisnotafunction报错...如果是这种错误,调试起来肯定会让你欲哭无泪的。所以,如果你想写出好的程序,请远离__proto__.
2.2.Object.create()应运而生
时无英雄,使竖子成名!JavaScript的今天的盛行,可以说就是这句话的写照。Object.create()也是这样,在继承时并不是我们非用它不可,只是在排除了使用__proto__之后,除了使用这个函数之外,我们没有其他更好的选择。这个函数在W3C中这个函数是怎么定义的呢?
Object.create函数(JavaScript)
创建一个具有指定原型且可选择性地包含指定属性的对象。Object.create(prototype,descriptors)
参数
prototype
必需。要用作原型的对象。可以为null。
descriptors
可选。包含一个或多个属性描述符的JavaScript对象。
“数据属性”是可获取且可设置值的属性。数据属性描述符包含value特性,以及writable、enumerable和configurable特性。如果未指定最后三个特性,则它们默认为false。只要检索或设置该值,“访问器属性”就会调用用户提供的函数。访问器属性描述符包含set特性和/或get特性。有关详细信息,请参阅
这是这个函数在W3C中的定义,我来举个例子来说明这个函数怎么用吧!!!
varA=function(name){
this.name=name;
};
A.prototype.getName=function(){
returnthis.name
}
varreturnObject=Object.create(A.prototype,{
name:{
value:'zhangsan',
configurable:true,
enumerable:false,
writable:true
}
});
上述代码运行完毕之后,returnObject在内存中的结构如图所示:
看看上面这张图,在类比1.3中的最后一张图,如下:
发现是不是,惊人的相似...所以,知道Objece.create()的强大了吧!!我们分析过,下面这张图是实现继承的完美状态,而Object.create()就是为了做到这些,专业为继承而设计出来的函数。
下面是一段用Object.create()函数实现子类继承父类的代码;
//子类继承父类,这段代码在执行deleteObject.prototype.__proto__;这段代码之后仍然可以正常运行。
functionextend(subClass,superClass){
varprototype=Object.create(superClass.prototype);
subClass.prototype=prototype;
subClass.prototype.constructor=subClass;}
varA=function(){
}
A.prototype.say=function(){
return'hello';
}
varB=function(){
}
extend(B,A);
varb=newB();
b.say();//hello
Ok!我知道,你能用N多种方法实现继承,但是请记住,在继承的时候请不要用__proto__这个属性,因为它没你想象中俺么可靠。如果你想获得一个对象的原型,那么这个方法可以做到,Object.getPrototypeOf。与之对应的是Object.setPrototypeOf方法。
也许你也会说,Object.setPrototypeOf方法可以在远离__proto__的情况下实现继承啊啊...如果你在看到它的源代码你还会这么说吗?
Object.setPrototypeOf=Object.setPrototypeOf||function(obj,proto){
obj.__proto__=proto; //也是用到了__proto__.
returnobj;
}
总结:
整篇文章,从prototype谈起,分析了函数的prototype的类型与作用(这个大家都在谈)。
在第二部分,我们分析了__proto__,得到的结果,内置属性和__proto__根本不是一回事。__proto__这个属性不可靠..撇开,这个属性是非标准属性不说,这个属性隐藏的bug就能致人于死地,所以,在写程序时,请谨记一点,珍爱生命,远离__proto__.
在最后,我们浅谈了一下,用Object.create()实现继承的好处。这个部分,很难讲的清楚,需要慢慢去体会。
在下一篇中,我们会分析,为什么会说JS中一切皆是对象!。。。
相关文章推荐
- JavaScript内核系列 第8章 面向对象的JavaScript(下)
- 面向对象的JavaScript系列二,继承
- JavaScript系列:面向对象 (好东西保存了)
- javascript面向对象系列第四篇——OOP中的常见概念
- javascript面向对象系列第三篇——实现继承的3种形式
- JavaScript系列----面向对象的JavaScript(1)
- javascript面向对象系列第四篇——选项卡的实现
- javascript面向对象系列第二篇——创建对象的5种模式
- <读书笔记>Javascript系列之6种继承(面向对象)
- 面向对象的JavaScript系列一,创建对象
- javascript面向对象系列第一篇——构造函数和原型对象
- 面向对象的javascript系列文章(2)封装——信息隐藏
- JavaScript进阶设计模式系列——基础篇——闭包(4)--闭包和面向对象的设计
- (二)我的JavaScript系列:JavaScript面向对象旅程(下)
- 面向对象的javascript系列文章(3)继承——代码重用
- JavaScript内核系列 第8章 面向对象的JavaScript(上)
- (一)我的Javascript系列:Javascript的面向对象旅程(上)
- <读书笔记>JavaScript系列之7种创建对象(面向对象)
- 面向对象的javascript系列文章(1)接口——是一个标准委员会
- JavaScript面向对象的支持(1)