读书人

javascript面向对象的几个定论(new,pr

发布时间: 2012-11-25 11:44:31 作者: rapoo

javascript面向对象的几个结论(new,prototype)
二. javascript面向对象的几个结论(new,prototype)
================================================================================================================
---------------------------
2.1 引子
---------------------------

因为javascript最初设计的面向对象存在缺陷,导致如果每一个对象关于"类的方法都进行一次硬拷贝"的问题:

function ShowText(text){this.word = text;this.sing = function singFunction() {alert("HelloWorld!~");};}obj1 = new ShowText("sb1");obj2 = new ShowText("sb2");

这样的话obj1和obj2在内存中分别有一份singFunction的方法代码,显然这很sb,有两种改进方式:
) 外部定义函数对象,
function ShowText(){this.sing = singFunction;}function singFunction(){    alert("HelloWorld!~"); }new ShowText().sing();


2) 利用函数对象的prototype属性
function ShowText(){}ShowText.prototype.sing = function(){ alert( "HelloWorld!~");}new ShowText().sing();

---------------------------
2.2 new关键字的作用
---------------------------

请对比如下的例子:
function ShowText(text){this.word = text;}var obj = new ShowText("hi,tomsui!~");alert(obj.word);                        // "hi,tomsui!~"var obj2 = new Object();obj2.constuct = ShowText;obj2.constuct("hi,tomsui!~");alert(obj2.word);                      // "hi,tomsui!~"

通过运行结果可以看出存在如下等价关系:
var ball0=new Ball("creating new Ball");<==>var ball0=new Object();ball0.construct=Ball;ball0.construct("creating new ball");

分析上述等价关系,可得到"new"关键字背后的实际动作如下:
a. 创建一个新的,空的object -- new Object()

b. 调用这个object的constructor;
obj.construct也是一个对象,对象都具备prototype属性,这是不必说的.

c. [补充] 拷贝这个object的construct的prototype属性到新生成的object中来(软拷贝引用)

说明: 1) "new"关键字让一个普通函数变为了构造器,可以把它理解为一种用于简化创建对象步骤的"约定"
2) 等价关系只能证明new的前两条作用,关于的prototype的叙述参见下边"2.3 prototype"

--------------------------
2.3 prototype
---------------------------

1. 首先注意:
1) prototype是函数对象才具备的属性,普通对象是没有的.
-- 我对一些sb书上说它是一切对象的属性(因为它是Object对象的属性)感到困惑

2) 构造函数prototype属性本身也是一个object,它具有如下特征:

a. 它存在一个constructor属性指向函数对象的代码 (死规定,记住就ok), 例如:
 function showText(text) { alert(test);}// 下面证明了showText的prototype属性是对象alert(typeof(showText.prototype));     // object// 下面说明了showText.prototype这个对象不能用默认toString()打印alert(showText.prototype);             // [object, Object]// 下面证明showText.prototype.constructor的存在性alert(showText.prototype.constructor); // function showText(text) { alert(test); }alert(typeof showText.prototype.constructor); // function

b. 它像其他对象一样可以添加属性,例如:
// 添加属性text属性function showText() {};showText.prototype.text = "HelloWorld!~";     // 添加shout()方法function showText() {}showText.prototype.shout = function(){alert("tomsui wants to smoke!~");};

2. prototype的内幕

  回想new关键字的幕后机制:
先用构造器生成一个对象, 然后"软拷贝构造器prototype属性的内容到新生成的object中来"。
下面,对引号中强调的内容有必要的两点解释:

1) "构造器prototype属性的内容"是什么?
构造器prototype属性是一个对象,那么它的内容包括两部分: a. 属性值 b. 方法

2) 什么是"软拷贝"?
就是仅仅拷贝内容的引用到新生成obj,并不是真正的prototype中的内容(软拷贝是tomsui借用linux中"ln -s"的说法,比较简洁吧~)
"软拷贝构造器prototype属性的内容到新生成的object中来"恐怕就是prototype的核心内幕了.

3. 引入prototype对javascript的影响

1) 为创建对象添加附加动作
为构造器的prototype新添加的任何"属性"和"方法",都会被new关键字在使用构造器创建对象时,附加到新的对象中去。
例如:
function ShowText() {};// 添加text属性ShowText.prototype.text = "HelloWorld!~";alert(new ShowText().text);                   // HelloWorld!~     // 添加shout()方法ShowText.prototype.shout = function(){alert("tomsui wants to smoke!~");};new ShowText().shout(); // tomsui wants to smoke!~

上例中,构造器ShowText()本来可是没有text属性和shout()方法的哦~

2) prototype 不会影响到构造器的动作
所以如果两者发生矛盾时,构造器生效, -- 这非常值得注意!

    例如:
function ShowText(){this.text = "tomsui is handsome!~";this.say = function(){alert("absolutely!")};}        ShowText.prototype.text = "J.J. is handsome!~";ShowText.prototype.say = function(){alert("perhaps?")};        var obj = new ShowText();alert(obj.text);         // tomsui is handsome!~obj.say();                        // absolutely!

结果是: prototype界定的"J.J. is handsome!~"没有生效,(毕竟是伪科学么);
构造器讲出了"tomsui is handsome!~","absolutely!", 因为这是真理,不是prototype可以推翻的

3) prototype的出现,让js发生了所谓的"极晚绑定"。
晚绑定("后期绑定")可以参考TIJ或其他面向对象的书吧,不说了。
"极晚绑定"让javascript的伪面向对象更加变态:即便已经new出了一个对象实例,你仍然可以为其添加新的行为和属性,
例如:
function Person(name){this.name = name;this.wordsInHeart = "tell Rora I love her~";}var tts = new Person("tomsui");  // tell Rora I love her~alert(tts.wordsInHeart);        Person.prototype.saySomeOtherWords = function(){alert("tell Rora I need her~")};tts.saySomeOtherWords();

看见没有:
名为tomsui的Person对象出现时本来只会说"tell Rora I love her~",
但自从他学会了prototype招数,泡妞技术更上一层楼,
于是补充他又会多说: "tell Rora I need her~"。

这个例子可见"极晚绑定"的好处,有得有失,这种动作多了,你的js成本会很高(就是慢贝),所以谨慎使用。

ps.
I. "极晚绑定"是官方用语,可放心使用; 不像"软拷贝"这词这土。
II. 并不是完整介绍js的伪面向对象,仅作为js做抛砖引玉用。


转自:http://hi.baidu.com/flvu/blog/item/3a343e677a154c29ab184cbf.html

读书人网 >JavaScript

热点推荐