JavaScript的面向對象特性初探

初步學習JS的面向對象特性,部分內容來自互聯網,感謝原作者,並對其進行了擴充,以下代碼在VS2010+IE9中調試通過:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
        //構造函數
        function myContructor(message) {
            //公有屬性
            this.myMessage = message;

            //私有屬性
            var separator ='-';
            var myOwner = this;

            //私有方法
            function alertMessage() {
                alert(myOwner.myMessage);
            }
            alertMessage();

            //特權方法
            this.appendToMessage = function (string) {
                this.myMessage += separator + string;
                alertMessage();
            }
            return this;
        };

        //原型定義的公有方法
        myContructor.prototype.clearMessage = function (string) {
            this.myMessage = 'clear!';
        }

        //靜態屬性
        myContructor.prototype.name2 = '';

        //靜態屬性
        myContructor.name = 'Jankerli';

        //靜態方法
        myContructor.alertName = function () {
            alert("類方法:"+this.name);
        }

        function fun()
        {
            var obj = myContructor("qzf");

            //(1)對象方法            
            alert("外部調用的公用屬性:" + obj.myMessage);  //能訪問;構造中調用的私有方法
            obj.appendToMessage("new");  //構造函數中定義的特權方法
            alert("對象外部訪問內部私有屬性:"+obj.myOwner);   //提示未定義
            //obj.alertMessage();  //私有方法,報錯提示不支持次方法;

            //(2)類方法,類屬性
            myContructor.name = "CBX";  //類的屬性(相當於C#的靜態屬性)
            myContructor.alertName();  //類的方法(相當於C#靜態方法)
            alert("用實例來訪問類的靜態成員:"+obj.name);  //能訪問,用實例來訪問類的靜態成員的結果是空;
            //obj.alertName();        //報錯,不能用實例來訪問類的靜態方法;

            //(3)原型方法,使用原型等於指向一個類的單例對象      
            alert(obj.name2);                   //這個對象不是用原型的渠道創建的,原型屬性未定義      
            //obj.clearMessage("OK");           //報錯:這個對象不是用原型的渠道創建的,原型方法不讓用
            //obj.prototype.clearMessage("OK"); //報錯:這個也不讓調用,類名後才能跟prototype;            

            myContructor.prototype.clearMessage("OK1"); //等於myContructor.prototype這是個匿名對象(其實用類名就可以找到它)
            var protoObj = myContructor.prototype;      //用變量抓下這個匿名對象,讓它有名
            protoObj.clearMessage("OK");                //這個對象變量是用原型的渠道創建的,可以使用原型方法
            protoObj.name2 = "-----";                   //這個用原型的渠道創建的對象,也能使用原型定義的公有屬性
            alert("原型渠道創建的對象能使用原型屬性:" + protoObj.name2);      
            alert("原型渠道創建的對象能使用原型方法:" + protoObj.myMessage); //用原型的渠道創建的對象,照樣能使用對象的公有屬性

            //protoObj和obj理論上都是myContructor的實例化對象
            //而protoObj.clearMessage可以,但obj.clearMessage不可以,要把obj氣死了,

            //不過沒關係也有原型對象訪問不了的:
            //protoObj.appendToMessage("NNew");   //這句報錯,用原型的渠道創建的對象,不能使用對象的特權方法!

            var protoObj2 = myContructor.prototype;  //讓用另一個變量也指向這個對象,myContructor.prototype被兩個對象引用了
            protoObj2.myMessage = "ABCD";

            alert("原型的單例對象在其它地方改了,一改所有以後引用的對象都改了,protoObj的屬性:" + protoObj.myMessage);
            alert("原型的單例對象在其它地方改了,一改所有以後引用的對象都改了,類.prototype的屬性:" + myContructor.prototype.myMessage);
            alert("非原型的渠道創建的對象不受影像:" + obj.myMessage);

            //用傳統面向對象(以C#/Java爲例)角度看,myContructor是基類/父類;
            //原型相當於擴展類/子類;
            //但是擴展類只能是單例;

            //與傳統面向對象不同的是:
            //(與基類相當的)myContructor類的對象能訪問的公有方法,而(與子類地位相當的)原型對象卻不能訪問appendToMessage方法
            //按照傳統面向對象的思路,子類不能基父類訪問的方法,那說明方法是私有的啊,
            //但是JS中父類中這個方法不是私有的,因爲父類的對象能訪問,這是不同的地方

            var cc = protoObj.prototype;  //未定義
        }
    </script>
</head>
<body>
    <input style="margin-top:10px" type="button" onclick="fun()" value="測試調用" />
</body>
</html>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章