五月综合缴情婷婷六月,色94色欧美sute亚洲线路二,日韩制服国产精品一区,色噜噜一区二区三区,香港三级午夜理伦三级三

您現(xiàn)在的位置: 365建站網(wǎng) > 365文章 > JavaScript中的原型和對象機(jī)制

JavaScript中的原型和對象機(jī)制

文章來源:365jz.com     點(diǎn)擊數(shù):297    更新時(shí)間:2009-09-30 11:59   參與評論
主機(jī)網(wǎng)全新上線,買空間、服務(wù)器就上主機(jī)網(wǎng),安全有保障!CNIDC.COM

1 對象相關(guān)的一些語言特性

1.1 一切皆為對象

JavaScript里所有的東西都是對象。 對象是屬性的集合。 數(shù)字, 字符串, 布爾值等原始值是“偽對象”, 它們同樣擁有屬性, 但是是在棧上分配并按值傳遞。 而其他的對象是堆上分配并按引用傳遞。

一個(gè)很重要的概念是, 函數(shù)也是對象, 能夠作為變量的值, 返回值, 參數(shù)或者屬性的值。 函數(shù)對象特殊的地方是能通過“xxx()”語法執(zhí)行包含在xxx函數(shù)對象內(nèi)的代碼。 因?yàn)檫@一特殊性, typeof xxx 將會(huì)返回function, 但這只是一種便利設(shè)施。

1.2 對象的屬性可以動(dòng)態(tài)添加和刪除

以下為引用的內(nèi)容:

var foo = new Object();
// 為foo對象添加bar屬性
foo.bar = "foobar";
alert(foo.bar); 
//foobar
//
 刪除foo對象的bar屬性
delete foo.bar;
alert(foo.bar); 
//undefined

1.3 除了宿主對象, 其它對象皆由構(gòu)造函數(shù)創(chuàng)建

要有對象, 就先要有創(chuàng)建對象的方法。

在C++/Java等語言, 這個(gè)方法就是實(shí)例化XXX類的一個(gè)實(shí)例xxx.

而在JavaScript的世界里實(shí)際沒有類的東西, 當(dāng)然仍然可以用“類”和“實(shí)例”等慣用語來描述JavaScript中類似的行為, 但其機(jī)制是完全不同的。 JavaScript的對象是由構(gòu)造函數(shù)創(chuàng)建的, 每個(gè)對象都有constructor屬性表示創(chuàng)建該對象的構(gòu)造函數(shù):

以下為引用的內(nèi)容:

function Test() { this.a = "hello"; }
var test = new Test(); // 由Test構(gòu)造函數(shù)創(chuàng)建
alert(test.constructor);

var o = { a: "hello" };
//實(shí)際相當(dāng)于
var o_ = new Object();
o_.a 
= "hello"// 由Object構(gòu)造函數(shù)創(chuàng)建
alert(o.constructor);

構(gòu)造函數(shù)也是對象, 那構(gòu)造函數(shù)是由什么創(chuàng)建? 內(nèi)建的Function函數(shù):

以下為引用的內(nèi)容:

function Test(a, b)
{
    alert(a+b)
;
}
// 相當(dāng)于:
Test = new Function(["a""b"], "alert(a+b);");

Function函數(shù)又是由什么創(chuàng)建? 實(shí)際上Function是本機(jī)代碼實(shí)現(xiàn)的固有對象. 不過為了一致性, Function也有constructor屬性, 該屬性指向它自己. 接上面的代碼:

以下為引用的內(nèi)容:

/* 輸出 function Function(){
            [native code]
        }
*/
alert(Test.constructor);

alert(Test.constructor.constructor 
=== Test.constructor); // true
alert(Test.constructor === Object.constructor); // true

2 原型prototype

2.1 prototype的概念

prototype是構(gòu)造函數(shù)的一個(gè)屬性, 該屬性指向一個(gè)對象。 而這個(gè)對象將作為該構(gòu)造函數(shù)所創(chuàng)建的所有實(shí)例的基引用(base reference), 可以把對象的基引用想像成一個(gè)自動(dòng)創(chuàng)建的隱藏屬性。 當(dāng)訪問對象的一個(gè)屬性時(shí), 首先查找對象本身, 找到則返回; 若不, 則查找基引用指向的對象的屬性(如果還找不到實(shí)際上還會(huì)沿著原型鏈向上查找, 直至到根)。 只要沒有被覆蓋的話, 對象原型的屬性就能在所有的實(shí)例中找到。

原型默認(rèn)為Object的新實(shí)例, 由于仍是對象, 故可以給該對象添加新的屬性:

以下為引用的內(nèi)容:

// prototype默認(rèn)為new Object(); 為了方便, 記為p_obj
function Person(name) {
    
this.name = name;
}

// 為 p_obj 增加 sayName 屬性
Person.prototype.sayName = function(){
    alert(
this.name);
}

var john = new Person("John"); // john 的 base reference指向p_obj
var eric = new Person("Eric");  // eric 的 base reference也是指向p_obj

// 注意sayName代碼中的this將指向?qū)嵗蟮膶ο?this綁定)
john.sayName(); // john對象本身沒有sayName屬性, 于是訪問原型對象p_obj的sayName屬性
eric.sayName(); // 訪問同一個(gè)原型對象p_obj的sayName屬性


var tmp = Person.prototype;
tmp.boss 
= "David";
// 于這個(gè)運(yùn)行點(diǎn), p_obj已經(jīng)被修改
//
 根據(jù)上述屬性訪問流程, 新的修改(boss屬性)能反映到所有的實(shí)例, 包括已經(jīng)創(chuàng)建和即將創(chuàng)建的
alert("John's boss is " + john.boss);
alert(
"Eric's boss is " + eric.boss);


// hisCar和sayCar屬性將增加到j(luò)ohn對象而不是p_obj對象..
john.hisCar = "Audi";
john.sayCar 
= function(){
    alert(
this.name + " has a car of " + this.hisCar);
}
john.sayCar();
// ..因此下一句將錯(cuò)誤, 因?yàn)閑ric對象本身和原型p_obj都沒有sayName屬性
/*
 eric.sayCar(); */

2.2 原型鏈

除了能修改prototype指向的對象, 還能修改prototype指向哪一個(gè)對象, 即為prototype賦予一個(gè)不同的對象。 這可以實(shí)現(xiàn)一種簡單的繼承:

以下為引用的內(nèi)容:

function Superman() {}
Superman.prototype.sayHello 
= function(){
    alert(
"I'm a superman.");
}

function SupermanCan(skill){
    
this.skill = skill;
}
// 為prototype賦予Superman的實(shí)例..
SupermanCan.prototype = new Superman();
// ..再動(dòng)態(tài)添加新的屬性
SupermanCan.prototype.sayMore = function(){
    
this.sayHello(); // 調(diào)用"父類"的方法
    alert(
"I can " + this.skill);
}

var david = new SupermanCan("fly");
// output: I'm a superman. I can fly
david.sayMore();

如果先實(shí)例化出一個(gè)對象, 再為構(gòu)造函數(shù)prototype賦予一個(gè)不同的對象, 將會(huì): 已經(jīng)創(chuàng)建的對象的基引用不變, 將來創(chuàng)建的對象的基引用為新的原型對象:

以下為引用的內(nèi)容:

var f1 = {echo: function() { alert("sound"); } };
function Foo() {};
var foo = new Foo(); // foo的基引用指向Object實(shí)例
Foo.prototype = f1;
/* 未定義, 因?yàn)檫@是"foo對象自己或者基引用指向的對象有echo屬性嗎?"
   而不是"foo對象自己或者Foo.prototype指向的對象有echo屬性嗎?" 
*/
alert(foo.echo);

var foo2 = new Foo(); // foo2的基引用指f1對象
foo2.echo(); // output: sound

所有的構(gòu)造函數(shù)的prototype都不能為空, 就是說Superman.prototype = null 會(huì)被解釋引擎無視; 另一方面, Object構(gòu)造函數(shù)也有prototype屬性(該屬性是只讀的, 可以為原型增加屬性,但不能賦予不同的對象), 故因此可以有多層的原型鏈, 但原型鏈的根必定會(huì)是Object.prototype 。 這意味著給Object.prototype增加屬性影響到所有對象:

以下為引用的內(nèi)容:

Object.prototype.echo = function() {
    alert(
"hello");
}

// echo屬性將增加到所有對象固有對象和自定義對象

var arr = new Array();
arr.echo();
Array.echo();

function ObjCons()    {
    
this.dummy = "d";
}
var obj = new ObjCons();
obj.echo();
ObjCons.echo();

3. 構(gòu)造函數(shù)和new的實(shí)質(zhì)

構(gòu)造函數(shù)是一個(gè)地地道道的函數(shù), 一個(gè)函數(shù)之所以能成為構(gòu)造函數(shù), 是因?yàn)閚ew運(yùn)算符:

以下為引用的內(nèi)容:

this.msg = "window";

function Test()
{
    alert(
this.msg);
}

Test(); 
// window
var test = new Test(); // undefined. 因?yàn)閠est對象沒有定義msg屬性

二者區(qū)別在于如何切入對象: Test() 在某個(gè)對象(例子中為window)的上下文上執(zhí)行代碼, 即this指向這個(gè)對象; new Test()創(chuàng)建一個(gè)新對象, 并以這個(gè)新的對象為上下文(this指向新對象)執(zhí)行代碼, 然后返回這個(gè)新對象。

假如有個(gè)函數(shù):

以下為引用的內(nèi)容:

function Test() {
    
var dummy = "have money";
    
this.wish = dummy;
    doSomeThing();
    
}

結(jié)合以上的所有論述, 可以推測new Test()行為的偽代碼表示為:

以下為引用的內(nèi)容:

      創(chuàng)建一個(gè)新對象temp;
      temp.constructor = Test;
      temp.(base reference) = Test.prototype; // 這一句先于代碼體執(zhí)行, 意味著構(gòu)造函數(shù)里的this.xxx能訪問原型對象的屬性xxx
      bind: this = temp; // 將this綁定到temp對象
      // 開始執(zhí)行函數(shù)代碼
      var dummy = "have money";
      this.wish = dummy; // 為temp對象添加wish屬性
      doSomeThing();
      ....
      // 結(jié)束執(zhí)行函數(shù)代碼
      return temp;


這個(gè)未必會(huì)符合內(nèi)部的二進(jìn)制實(shí)現(xiàn), 但卻能很好地解釋了JavaScript的特性.

原文地址:http://www.cnblogs.com/FlyingCat/archive/2009/09/21/1570656.html

如對本文有疑問,請?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會(huì)為你解答!! 點(diǎn)擊進(jìn)入論壇

發(fā)表評論 (297人查看,0條評論)
請自覺遵守互聯(lián)網(wǎng)相關(guān)的政策法規(guī),嚴(yán)禁發(fā)布色情、暴力、反動(dòng)的言論。
昵稱:
最新評論
------分隔線----------------------------

其它欄目

· 建站教程
· 365學(xué)習(xí)

業(yè)務(wù)咨詢

· 技術(shù)支持
· 服務(wù)時(shí)間:9:00-18:00
365建站網(wǎng)二維碼

Powered by 365建站網(wǎng) RSS地圖 HTML地圖

copyright © 2013-2024 版權(quán)所有 鄂ICP備17013400號