日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

悟透Javascript

系統(tǒng) 2920 0

感覺挺經(jīng)典的js文章,傳個附件。張軍博客  

 JavaScript 中沒有‘類’,類已化于無形,與對象融為一體。正是由于放下了‘類’這個概念,JavaScript的對象才有了其他編程語言所沒有的活力。 ”這句看了很有感悟,也許這就是Javascript強(qiáng)大之所在吧。Javascript因此具有了動態(tài)增刪對象功能的能力。

 

function myfunc(){
	alert("hello");
} 
myfunc();//這里調(diào)用myfunc,輸出 yeah 而不是 hello
function myfunc(){
	alert("yeah");
}
myfunc();//這里調(diào)用myfunc,當(dāng)然輸出yeah

 

 JavaScript 執(zhí)行引擎并非一行一行地分析和執(zhí)行程序,而是      一段一段地分析執(zhí)行         的。而且,在同一段程序的分析執(zhí)行中,定義式的函數(shù)語句會被提取出來優(yōu)先執(zhí)行。函數(shù)定義執(zhí)行完之后,才會按順序執(zhí)行其他語句代碼。也就是說,在第一次調(diào)用myfunc之前,第一個函數(shù)語句定義的代碼邏輯,已被第二個函數(shù)定義語句覆蓋了。所以,兩次都調(diào)用都是執(zhí)行最后一個函數(shù)邏輯了。  

 

如果把這個 JavaScript 代碼分成兩段,例如將它們寫在一個 html 中,并用<script/>標(biāo)簽將其分成這樣的兩塊:

<script> 
    function myfunc () 
    { 
        alert("hello"); 
    }; 
    myfunc(); //這里調(diào)用myfunc,輸出 hello 
</script> 
 
<script> 
    function myfunc () 
    { 
        alert("yeah"); 
    };     
    myfunc(); //這里調(diào)用myfunc,輸出 yeah 
</script>

 

 這時,輸出才是各自按順序來的,  也證明了JavaScript的確是一段段地執(zhí)行的 。
 
    一段代碼中的定義式函數(shù)語句會優(yōu)先執(zhí)行,這似乎有點(diǎn)象靜態(tài)語言的編譯概念。所以,這一特征也被有些人稱為:JavaScript的“預(yù)編譯”。

 

大多數(shù)情況下,我們也沒有必要去糾纏這些細(xì)節(jié)問題。只要你記住一點(diǎn):  JavaScript 里的代碼也是一種數(shù)據(jù),同樣可以被任意賦值和修改的,而它的值就是代碼的邏輯 。只是,與一般數(shù)據(jù)不同的是,  函數(shù)是可以被調(diào)用執(zhí)行的

 

JavaScript 函數(shù)的神奇之處還體現(xiàn)在另外兩個方面:一是  函數(shù) function類型本身也具有對象化的能力 ,二是  函數(shù)function與對象 object超然的結(jié)合能力

 

 在JavaScript函數(shù)中,你只能把this看成當(dāng)前要服務(wù)的“這個”對象。this是一個特殊的內(nèi)置參數(shù),根據(jù)this參數(shù),您可以訪問到“這個”對象的屬性和方法,但卻不能給this參數(shù)賦值。在一般對象語言中,方法體代碼中的this可以省略的,成員默認(rèn)都首先是“自己”的。但JavaScript卻不同,由于不存在“自我”,當(dāng)訪問“這個”對象時,this不可省略!  

 

我們已經(jīng)知道,用 var anObject = new aFunction() 形式創(chuàng)建對象的過程實(shí)際上可以分為三步:
 第一步是建立一個新對象 ;  第二步將該對象內(nèi)置的原型對象設(shè)置為構(gòu)造函數(shù)prototype引用的那個原型對      
  象
 第三步就是將該對象作為this參數(shù)調(diào)用構(gòu)造函數(shù),完成成員設(shè)置等初始化工作 。對象建立之后,對象
上的任何訪問和操作都只與對象自身及其原型鏈上的那串對象有關(guān),與構(gòu)造函數(shù)再扯不上關(guān)系了。換句話
說,  構(gòu)造函數(shù)只是在創(chuàng)建對象時起到介紹原型對象和初始化對象兩個作用

 

那么,我們能否自己定義一個對象來當(dāng)作原型,并在這個原型上描述類,然后將這個原型設(shè)置給新創(chuàng)建
的對象,將其當(dāng)作對象的類呢?我們又能否將這個原型中的一個方法當(dāng)作構(gòu)造函數(shù),去初始化新建的對象
呢?例如,我們定義這樣一個原型對象:

var Person =  //定義一個對象來作為原型類
    {
        Create: function(name, age)  //這個當(dāng)構(gòu)造函數(shù)
        {
  28

            this.name = name;
            this.age = age;
        },
        SayHello: function()  //定義方法
        {
            alert("Hello, I'm " + this.name);
        },
        HowOld: function()  //定義方法
        {
            alert(this.name + " is " + this.age + " years old.");
        }
    };

   

    這個JSON形式的寫法多么象一個C#的類??!既有構(gòu)造函數(shù),又有各種方法。如果可以用某種形式來
創(chuàng)建對象,并將對象的內(nèi)置的原型設(shè)置為上面這個“類”對象,不就相當(dāng)于創(chuàng)建該類的對象了嗎?
 
    但遺憾的是,我們幾乎不能訪問到對象內(nèi)置的原型屬性!盡管有些瀏覽器可以訪問到對象的內(nèi)置原型,
但這樣做的話就只能限定了用戶必須使用那種瀏覽器。這也幾乎不可行。
 
    那么,我們可不可以通過一個函數(shù)對象來做媒介,利用該函數(shù)對象的prototype 屬性來中轉(zhuǎn)這個原型,
并用new操作符傳遞給新建的對象呢?
 
    其實(shí),象這樣的代碼就可以實(shí)現(xiàn)這一目標(biāo):

function anyfunc(){};           //定義一個函數(shù)軀殼
anyfunc.prototype = Person;     //將原型對象放到中轉(zhuǎn)站 prototype
var BillGates = new anyfunc();  //新建對象的內(nèi)置原型將是我們期望的原型對象

   

    不過,這個 anyfunc 函數(shù)只是一個軀殼,在使用過這個軀殼之后它就成了多余的東西了,而且這和直
接使用構(gòu)造函數(shù)來創(chuàng)建對象也沒啥不同,有點(diǎn)不爽。

    可是,如果我們將這些代碼寫成一個通用函數(shù),而那個函數(shù)軀殼也就成了函數(shù)內(nèi)的函數(shù),這個內(nèi)部函數(shù)
不就可以在外層函數(shù)退出作用域后自動消亡嗎?而且,我們可以將原型對象作為通用函數(shù)的參數(shù),讓通用
函數(shù)返回創(chuàng)建的對象。我們需要的就是下面這個形式:

function New(aClass, aParams)    //通用創(chuàng)建函數(shù)
    {
        function new_()     //定義臨時的中轉(zhuǎn)函數(shù)殼
        {
            aClass.Create.apply(this, aParams);   //調(diào)用原型中定義的的構(gòu)造函數(shù),中轉(zhuǎn)構(gòu)造邏輯及構(gòu)造參數(shù)
        };
        new_.prototype = aClass;    //準(zhǔn)備中轉(zhuǎn)原型對象
        return new new_();          //返回建立最終建立的對象
    };
    
    var Person =        //定義的類
    {
        Create: function(name, age)
        {
            this.name = name;
            this.age = age;
        },
        SayHello: function()
        {
            alert("Hello, I'm " + this.name);
        },
        HowOld: function()
        {
            alert(this.name + " is " + this.age + " years old.");
        }

    };
    
    var BillGates = New(Person, ["Bill Gates", 53]);  //調(diào)用通用函數(shù)創(chuàng)建對象,并以數(shù)組形式傳遞構(gòu)造參數(shù)
    BillGates.SayHello();
    BillGates.HowOld();
 
    alert(BillGates.constructor == Object);     //輸出:true

   

    這里的通用函數(shù) New()就是一個“語法甘露”!這個語法甘露不但中轉(zhuǎn)了原型對象,還中轉(zhuǎn)了構(gòu)造函數(shù)
邏輯及構(gòu)造參數(shù)。
 
    有趣的是,每次創(chuàng)建完對象退出New函數(shù)作用域時,臨時的new_函數(shù)對象會被自動釋放。由于new
_的 prototype 屬性被設(shè)置為新的原型對象,其原來的原型對象和 new_之間就已解開了引用鏈,臨時函
數(shù)及其原來的原型對象都會被正確回收了。上面代碼的最后一句證明,新創(chuàng)建的對象的constructor屬性
返回的是 Object 函數(shù)。其實(shí)新建的對象自己及其原型里沒有 constructor 屬性,那返回的只是最頂層原
型對象的構(gòu)造函數(shù),即Object。

 

當(dāng)然,這個代碼僅僅展示了“語法甘露”的概念。我們還需要多一些的語法甘露,才能實(shí)現(xiàn)用簡潔而優(yōu)雅
的代碼書寫類層次及其繼承關(guān)系。好了,我們再來看一個更豐富的示例吧:

//語法甘露:
    var object =    //定義小寫的 object 基本類,用于實(shí)現(xiàn)最基礎(chǔ)的方法等
    {
        isA: function(aType)   //一個判斷類與類之間以及對象與類之間關(guān)系的基礎(chǔ)方法
        {
            var self = this;

            while(self)
            {
                if (self == aType)
                  return true;
                self = self.Type;
            };
            return false;
        }
    };
    
    function Class(aBaseClass, aClassDefine)    //創(chuàng)建類的函數(shù),用于聲明類及繼承關(guān)系
    {
        function class_()   //創(chuàng)建類的臨時函數(shù)殼
        {
            this.Type = aBaseClass;    //我們給每一個類約定一個 Type屬性,引用其繼承的類
            for(var member in aClassDefine)
                this[member] = aClassDefine[member];    //復(fù)制類的全部定義到當(dāng)前創(chuàng)建的類
        };
        class_.prototype = aBaseClass;
        return new class_();
    };
    
    function New(aClass, aParams)   //創(chuàng)建對象的函數(shù),用于任意類的對象創(chuàng)建
    {
        function new_()     //創(chuàng)建對象的臨時函數(shù)殼
        {
            this.Type = aClass;    //我們也給每一個對象約定一個 Type 屬性,據(jù)此可以訪問到對象所屬的類

            if (aClass.Create)
              aClass.Create.apply(this, aParams);   //我們約定所有類的構(gòu)造函數(shù)都叫Create,這和DELPHI比較相似
        };
        new_.prototype = aClass;
        return new new_();
    };
 
    //語法甘露的應(yīng)用效果:    
    var Person = Class(object,      //派生至 object 基本類
    {
        Create: function(name, age)
        {
            this.name = name;
            this.age = age;
        },
        SayHello: function()
        {
            alert("Hello, I'm " + this.name + ", " + this.age + " years old.");
        }
    });
    
    var Employee = Class(Person,    //派生至 Person 類,是不是和一般對象語言很相似?
    {
        Create: function(name, age, salary)
        {
            Person.Create.call(this, name, age);  //調(diào)用基類的構(gòu)造函數(shù)
            this.salary = salary;
        },
        ShowMeTheMoney: function()
        {
            alert(this.name + " $" + this.salary);
        }
    });
 
    var BillGates = New(Person, ["Bill Gates", 53]);
    var SteveJobs = New(Employee, ["Steve Jobs", 53, 1234]);
    BillGates.SayHello();
    SteveJobs.SayHello();
    SteveJobs.ShowMeTheMoney();
    
    var LittleBill = New(BillGates.Type, ["Little Bill", 6]);   //根據(jù) BillGate 的類型創(chuàng)建LittleBill
    LittleBill.SayHello();
    
    alert(BillGates.isA(Person));       //true
    alert(BillGates.isA(Employee));     //false
    alert(SteveJobs.isA(Person));       //true
    alert(Person.isA(Employee));        //false
    alert(Employee.isA(Person));        //true

   

    “語法甘露”不用太多,只要那么一點(diǎn)點(diǎn),就能改觀整個代碼的易讀性和流暢性,從而讓代碼顯得更優(yōu)雅。
有了這些語法甘露,JavaScript就很像一般對象語言了,寫起代碼了感覺也就爽多了!
 
    令人高興的是,受這些甘露滋養(yǎng)的 JavaScript 程序效率會更高。因為其原型對象里既沒有了毫無用處
的那些對象級的成員,而且還不存在constructor屬性體,少了與構(gòu)造函數(shù)間的牽連,但依舊保持了方法
的共享性。這讓JavaScript 在追溯原型鏈和搜索屬性及方法時,少費(fèi)許多工夫啊。
 
    我們就把這種形式稱為“甘露模型”吧!其實(shí),這種“甘露模型”的原型用法才是符合prototype概念的本
意,才是的JavaScript原型的真諦!


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 浠水县| 柳州市| 玉龙| 徐闻县| 勃利县| 行唐县| 张北县| 怀化市| 潜江市| 上蔡县| 黄龙县| 秀山| 乌拉特前旗| 论坛| 青铜峡市| 淮南市| 石城县| 将乐县| 潜山县| 山阴县| 奇台县| 永仁县| 咸宁市| 西昌市| 思茅市| 安康市| 林州市| 和田县| 崇义县| 上犹县| 丰城市| 蓬安县| 刚察县| 西乡县| 龙海市| 虞城县| 航空| 嘉禾县| 日土县| 虞城县| 富宁县|