亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

javascript學習筆記(五)原型和原型鏈詳解

2019-11-20 14:04:01
字體:
來源:轉載
供稿:網友

私有變量和函數

在函數內部定義的變量和函數,如果不對外提供接口,外部是無法訪問到的,也就是該函數的私有的變量和函數。

復制代碼 代碼如下:

<script type="text/javascript">
    function Test(){
        var color = "blue";//私有變量
        var fn = function() //私有函數
        {

        }
    }
</script>

這樣在函數對象Test外部無法訪問變量color和fn,他們就變成私有的了:

復制代碼 代碼如下:

var obj = new Test();
    alert(obj.color);//彈出 undefined
    alert(obj.fn);//同上

靜態變量和函數

當定義一個函數后通過點號 “.”為其添加的屬性和函數,通過對象本身仍然可以訪問得到,但是其實例卻訪問不到,這樣的變量和函數分別被稱為靜態變量和靜態函數。

復制代碼 代碼如下:

<script type="text/javascript">
    function Obj(){

    }
    Obj.num = 72;//靜態變量
    Obj.fn = function()  //靜態函數
    {

    } 

    alert(Obj.num);//72
    alert(typeof Obj.fn)//function

    var t = new Obj();
    alert(t.name);//undefined
    alert(typeof t.fn);//undefined
</script>

實例變量和函數

在面向對象編程中除了一些庫函數我們還是希望在對象定義的時候同時定義一些屬性和方法,實例化后可以訪問,JavaScript也能做到這樣

復制代碼 代碼如下:

<script type="text/javascript">
    function Obj(){
                this.a=[]; //實例變量
                this.fn=function(){ //實例方法

                }
            }

            console.log(typeof Obj.a); //undefined
            console.log(typeof Obj.fn); //undefined

            var o=new Obj();
            console.log(typeof o.a); //object
            console.log(typeof o.fn); //function
</script>

為實例變量和方法添加新的方法和屬性

復制代碼 代碼如下:

<script type="text/javascript">
function Obj(){
                this.a=[]; //實例變量
                this.fn=function(){ //實例方法

                }
            }

            var o1=new Obj();
            o1.a.push(1);
            o1.fn={};
            console.log(o1.a); //[1]
            console.log(typeof o1.fn); //object

            var o2=new Obj();
            console.log(o2.a); //[]
            console.log(typeof o2.fn); //function
</script>

在o1中修改了a和fn,而在o2中沒有改變,由于數組和函數都是對象,是引用類型,這就說明o1中的屬性和方法與o2中的屬性與方法雖然同名但卻不是一個引用,而是對Obj對象定義的屬性和方法的一個復制。

這個對屬性來說沒有什么問題,但是對于方法來說問題就很大了,因為方法都是在做完全一樣的功能,但是卻又兩份復制,如果一個函數對象有上千和實例方法,那么它的每個實例都要保持一份上千個方法的復制,這顯然是不科學的,這可腫么辦呢,prototype應運而生。

基本概念

我們創建的每個函數都有一個prototype屬性,這個屬性是一個指針,指向一個對象,這個對象的用途是包含可以由特定類型的所有實例共享的屬性和方法。那么,prototype就是通過調用構造函數而創建的那個對象實例的原型對象。

使用原型的好處是可以讓對象實例共享它所包含的屬性和方法。也就是說,不必在構造函數中添加定義對象信息,而是可以直接將這些信息添加到原型中。使用構造函數的主要問題就是每個方法都要在每個實例中創建一遍。

在JavaScript中,一共有兩種類型的值,原始值和對象值。每個對象都有一個內部屬性 prototype ,我們通常稱之為原型。原型的值可以是一個對象,也可以是null。如果它的值是一個對象,則這個對象也一定有自己的原型。這樣就形成了一條線性的鏈,我們稱之為原型鏈。

含義

函數可以用來作為構造函數來使用。另外只有函數才有prototype屬性并且可以訪問到,但是對象實例不具有該屬性,只有一個內部的不可訪問的__proto__屬性。__proto__是對象中一個指向相關原型的神秘鏈接。按照標準,__proto__是不對外公開的,也就是說是個私有屬性,但是Firefox的引擎將他暴露了出來成為了一個共有的屬性,我們可以對外訪問和設置。

復制代碼 代碼如下:

<script type="text/javascript">
    var Browser = function(){};
    Browser.prototype.run = function(){
        alert("I'm Gecko,a kernel of firefox");
    }

    var Bro = new Browser();
    Bro.run();
</script>

當我們調用Bro.run()方法時,由于Bro中沒有這個方法,所以,他就會去他的__proto__中去找,也就是Browser.prototype,所以最終執行了該run()方法。(在這里,函數首字母大寫的都代表構造函數,以用來區分普通函數)

當調用構造函數創建一個實例的時候,實例內部將包含一個內部指針(__proto__)指向構造函數的prototype,這個連接存在于實例和構造函數的prototype之間,而不是實例與構造函數之間。

復制代碼 代碼如下:

<script type="text/javascript">
function Person(name){
                this.name=name;
            }

            Person.prototype.printName=function(){
                alert(this.name);
            }

            var person1=new Person('Byron');
            var person2=new Person('Frank');
</script>

Person的實例person1中包含了name屬性,同時自動生成一個__proto__屬性,該屬性指向Person的prototype,可以訪問到prototype內定義的printName方法,大概就是這個樣子的:

再舉個栗子:

復制代碼 代碼如下:

<script type="text/javascript">
    function Animal(name)   //積累構造函數
    {
        this.name = name;//設置對象屬性
    }

    Animal.prototype.behavior = function() //給基類構造函數的prototype添加behavior方法
    { 
        alert("this is a "+this.name);
    }

    var Dog = new Animal("dog");//創建Dog對象
    var Cat = new Animal("cat");//創建Cat對象

    Dog.behavior();//通過Dog對象直接調用behavior方法
    Cat.behavior();//output "this is a cat"

    alert(Dog.behavior==Cat.behavior);//output true;
</script>

可以從程序運行結果看出,構造函數的prototype上定義的方法確實可以通過對象直接調用到,而且代碼是共享的。(可以試一下將Animal.prototype.behavior 中的prototype屬性去掉,看看還能不能運行。)在這里,prototype屬性指向Animal對象。

數組對象實例

再看個數組對象的實例。當我們創建出array1這個對象的時候,array1實際在Javascript引擎中的對象模型如下:

復制代碼 代碼如下:

var array1 = [1,2,3];

array1對象具有一個length屬性值為3,但是我們可以通過如下的方法來為array1增加元素:

array1.push(4);
push這個方法來自于array1的__proto__成員指向對象的一個方法(Array.prototye.push())。正是因為所有的數組對象(通過[]來創建的)都包含有一個指向同一個具有push,reverse等方法對象(Array.prototype)的__proto__成員,才使得這些數組對象可以使用push,reverse等方法。

函數對象實例

復制代碼 代碼如下:

function Base() { 
    this.id = "base"
}  

復制代碼 代碼如下:

var obj = new Base();

這樣代碼的結果是什么,我們在Javascript引擎中看到的對象模型是:

new操作符具體干了什么呢?其實很簡單,就干了三件事情。

復制代碼 代碼如下:

var obj  = {}; 
obj.__proto__ = Base.prototype; 
Base.call(obj);

原型鏈

原型鏈:當從一個對象那里調取屬性或方法時,如果該對象自身不存在這樣的屬性或方法,就會去自己關聯的prototype對象那里尋找,如果prototype沒有,就會去prototype關聯的前輩prototype那里尋找,如果再沒有則繼續查找Prototype.Prototype引用的對象,依次類推,直到Prototype.….Prototype為undefined(Object的Prototype就是undefined)從而形成了所謂的“原型鏈”。

復制代碼 代碼如下:

<script type="text/javascript">
    function Shape(){
        this.name = "shape";
        this.toString = function(){
            return this.name;
        }
    }
    function TwoShape(){
        this.name = "2 shape";
    }
    function Triangle(side,height){
        this.name = "Triangle";
        this.side = side;
        this.height = height;
        this.getArea = function(){
            return this.side*this.height/2;
        }
    }

    TwoShape.prototype = new Shape();
    Triangle.prototype = new TwoShape();
</script>

這里,用構造器Shape()新建了一個實體,然后用它去覆蓋該對象的原型。

復制代碼 代碼如下:

<script type="text/javascript">
    function Shape(){
        this.name = "shape";
        this.toString = function(){
            return this.name;
        }
    }
    function TwoShape(){
        this.name = "2 shape";
    }
    function Triangle(side,height){
        this.name = "Triangle";
        this.side = side;
        this.height = height;
        this.getArea = function(){
            return this.side*this.height/2;
        }
    }

    TwoShape.prototype = new Shape();
    Triangle.prototype = new TwoShape();

    TwoShape.prototype.constructor = TwoShape;
    Triangle.prototype.constructor = Triangle;

    var my = new Triangle(5,10);
    my.getArea();
    my.toString();//Triangle
    my.constructor;//Triangle(side,height)
</script>

原型繼承

原型繼承:在原型鏈的末端,就是Object構造函數prototype屬性指向的那個原型對象。這個原型對象是所有對象的祖先,這個老祖宗實現了諸如toString等所有對象天生就該具有的方法。其他內置構造函數,如Function,Boolean,String,Date和RegExp等的prototype都是從這個老祖宗傳承下來的,但他們各自又定義了自身的屬性和方法,從而他們的子孫就表現出各自宗族的那些特征。

ECMAScript中,實現繼承的方法就是依靠原型鏈實現的。

復制代碼 代碼如下:

<script type="text/javascript">
    function Box(){             //被繼承的函數叫做超類型(父類,基類)
        this.name = "Jack";
    }

    function Tree(){          //繼承的函數叫做子類型(子類,派生類)
        this.age = 300;
    }
    //通過原型鏈繼承,賦值給子類型的原型屬性
    //new Box()會將box構造里的信息和原型里的信息都交給Tree
    Tree.prototype = new Box();//Tree繼承了Box,通過原型,形成鏈條

    var tree = new Tree();
    alert(tree.name);//彈出 Jack
</script>

原型鏈的問題:原型鏈雖然很強大,可以用它來實現繼承,但它也存在一些問題。其中最主要的問題來自包含引用類型的值原型。包含引用類型的原型屬性會被所有實例共享;而這也正是為什么要在構造函數中,而不是在原型對象中定義屬性的原因。在通過原型來實現繼承時,原型實際上回變成另一個類型的實例。于是,原先的實例屬性也就變成了原型的屬性。

在創建子類型的實例時,不能向超類型的構造函數中傳遞參數。實際上,應該說是沒有辦法在不影響所有對象實例的情況下,給超類型的構造函數傳遞參數。再加上剛剛討論的由于原型中包含引用類型值所帶來的問題,實踐中很少會單獨使用原型鏈。

再舉個栗子:

復制代碼 代碼如下:

<script type="text/javascript">
    function Person(name)
    {
        this.name = name;//設置對象屬性
    };

    Person.prototype.company = "Microsoft";//設置原型的屬性
    Person.prototype.SayHello = function() //原型的方法
    { 
        alert("Hello,I'm "+ this.name+ " of " + this.company);
    };

    var BillGates = new Person("BillGates");//創建person對象
    BillGates.SayHello();//繼承了原型的內容,輸出"Hello,I'm BillGates of Microsoft"

    var Jobs = new Person("Jobs");
    Jobs.company = "Apple";//設置自己的company屬性,掩蓋了原型的company屬性
    Jobs.SayHello = function()
    {
        alert("Hi,"+this.name + " like " + this.company);
    };
    Jobs.SayHello();//自己覆蓋的屬性和方法,輸出"Hi,Jobs like Apple"
    BillGates.SayHello();//Jobs的覆蓋沒有影響原型,BillGates還是照樣輸出
</script>

看下面一個原型鏈例子:

復制代碼 代碼如下:

<script type="text/javascript">
    function Year(){
        this.value = 21;
    }
    Year.prototype = {
        method:function(){

        }
    };

    function Hi(){

    };
    //設置Hi的prototype屬性為Year的實例對象
    Hi.prototype = new Year();
    Hi.prototype.year = 'Hello World';

    Hi.prototype.constructor = Hi;

    var test = new Hi();//創建一個Hi的新實例

    //原型鏈
    test [Hi的實例]
        Hi.prototype [Year的實例]
            {year:'Hello World'}
            Year.prototype
                {method:……};
                object.prototype
                    {toString:...};

</script>

從上面例子中,test對象從Hi.prototype和Year.prototype中繼承下來;因此他能訪問Year的原型方法method,同時他能訪問實例屬性value

__ptoto__屬性

__ptoto__屬性(IE瀏覽器不支持)是實例指向原型對象的一個指針,它的作用就是指向構造函數的原型屬性constructor,通過這兩個屬性,就可以訪問原型里的屬性和方法了。

Javascript中的對象實例本質上是由一系列的屬性組成的,在這些屬性中,有一個內部的不可見的特殊屬性――__proto__,該屬性的值指向該對象實例的原型,一個對象實例只擁有一個唯一的原型。

復制代碼 代碼如下:

<script type="text/javascript">
    function Box(){        //大寫,代表構造函數
        Box.prototype.name = "trigkit4";//原型屬性
        Box.prototype.age = "21";
        Box.prototype.run = function()//原型方法
        { 
            return this.name + this.age + 'studying';
        }
    }

    var box1 = new Box();
    var box2 = new Box();
    alert(box1.constructor);//構造屬性,可以獲取構造函數本身,
                            //作用是被原型指針定位,然后得到構造函數本身
</script>  

__proto__屬性和prototype屬性的區別

prototype是function對象中專有的屬性。
__proto__是普通對象的隱式屬性,在new的時候,會指向prototype所指的對象;
__ptoto__實際上是某個實體對象的屬性,而prototype則是屬于構造函數的屬性。__ptoto__只能在學習或調試的環境下使用。

原型模式的執行流程

1.先查找構造函數實例里的屬性或方法,如果有,就立即返回。
2.如果構造函數的實例沒有,就去它的原型對象里找,如果有,就立即返回

原型對象的

復制代碼 代碼如下:

<script type="text/javascript">
    function Box(){        //大寫,代表構造函數
        Box.prototype.name = "trigkit4";//原型屬性
        Box.prototype.age = "21";
        Box.prototype.run = function()//原型方法
        { 
            return this.name + this.age + 'studying';
        }
    }

    var box1 = new Box();
    alert(box1.name);//trigkit4,原型里的值
    box1.name = "Lee";
    alert(box1.name);//Lee,就進原則

    var box2 = new Box();
    alert(box2.name);//trigkit4,原型的值,沒有被box1修改
</script>

構造函數的

復制代碼 代碼如下:

<script type="text/javascript">
    function Box(){                
        this.name = "Bill";
    }

    Box.prototype.name = "trigkit4";//原型屬性
    Box.prototype.age = "21";
    Box.prototype.run = function()//原型方法
    { 
            return this.name + this.age + 'studying';
    }

    var box1 = new Box();
    alert(box1.name);//Bill,原型里的值
    box1.name = "Lee";
    alert(box1.name);//Lee,就進原則
</script>

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品亚洲网站| 国产美女被下药99| 97视频在线观看视频免费视频| 欧美色视频日本高清在线观看| 俺去亚洲欧洲欧美日韩| 亚洲一二在线观看| 日韩在线观看免费高清完整版| 精品国产一区久久久| 国产精品日本精品| 国内精品国产三级国产在线专| 成人妇女淫片aaaa视频| 亚洲影视中文字幕| 日韩av电影在线播放| 午夜精品久久久久久久久久久久久| 国产伊人精品在线| 亚洲日韩中文字幕| 国产精欧美一区二区三区| 欧美精品videos另类日本| 久久精品国产欧美亚洲人人爽| 久久av在线播放| 伊人久久久久久久久久| 欧美激情2020午夜免费观看| 91精品国产成人| 亚洲精品日韩激情在线电影| 日韩av一区在线| 国产精品中文在线| 欧美一级bbbbb性bbbb喷潮片| 日韩精品免费一线在线观看| 91久久久久久久久| 久久久久久久网站| 亚洲区在线播放| 国产精品高清免费在线观看| 精品亚洲精品福利线在观看| 国产日韩在线观看av| 亚洲自拍偷拍一区| 欧美激情va永久在线播放| 18一19gay欧美视频网站| 国产激情综合五月久久| 麻豆国产va免费精品高清在线| 国产精品人成电影在线观看| 国产一区私人高清影院| 久久久91精品国产一区不卡| 日韩在线观看免费av| 夜夜狂射影院欧美极品| 国产精品久久视频| 亚洲综合中文字幕在线观看| 亚洲久久久久久久久久| 国外成人性视频| 懂色av影视一区二区三区| 日本91av在线播放| 欧美猛交ⅹxxx乱大交视频| 国内精品久久久久| 日本久久久久久久久| 亚洲人成伊人成综合网久久久| 国产精品日本精品| 亚洲天堂av电影| 欧美精品久久久久久久| 国产成人精品av在线| 九九精品视频在线| 欧美理论片在线观看| 国产精品18久久久久久首页狼| 伊人久久五月天| 色诱女教师一区二区三区| 欧美伊久线香蕉线新在线| 久久久精品欧美| 日韩在线免费av| 成人免费激情视频| 欧美成aaa人片免费看| 久久6免费高清热精品| 欧美激情视频在线观看| 日韩性xxxx爱| 久久久亚洲影院| 国产中文字幕亚洲| 国产精品一区久久| 国产精品久久久久秋霞鲁丝| 亚洲欧美成人精品| 亚洲人av在线影院| 欧美日韩成人在线观看| 国产精品扒开腿爽爽爽视频| 国产在线播放不卡| 日韩理论片久久| 91亚洲精品在线观看| 91国产中文字幕| 欧美日韩午夜视频在线观看| 国产91精品最新在线播放| 国产做受69高潮| 黑人巨大精品欧美一区二区一视频| 中文字幕一区二区三区电影| 98精品国产高清在线xxxx天堂| 日本精品免费观看| 91精品视频在线| 日韩国产精品亚洲а∨天堂免| 亚洲黄色免费三级| 欧美在线视频在线播放完整版免费观看| 亚洲欧美国产日韩天堂区| 欧美日韩亚洲高清| 日韩精品在线免费播放| 高清一区二区三区日本久| 欧美日韩aaaa| 久久中文精品视频| 2021国产精品视频| 欧美xxxx14xxxxx性爽| 裸体女人亚洲精品一区| 成人午夜黄色影院| 韩国福利视频一区| 色偷偷噜噜噜亚洲男人| 69精品小视频| 77777少妇光屁股久久一区| 国产69精品久久久久99| 久久久噜噜噜久噜久久| 久久97久久97精品免视看| 日韩欧美中文字幕在线播放| 国产精品久久久久久久久久东京| 国产精品视频网站| 欧美国产第一页| 日韩大片免费观看视频播放| 亚洲国产成人av在线| 亚洲的天堂在线中文字幕| 国产精品男人的天堂| 日韩视频在线一区| 欧美高清视频在线观看| 国产日韩中文字幕| 欧美一区二区三区精品电影| 日韩视频―中文字幕| 国产精品成人品| 自拍偷拍亚洲区| 91夜夜未满十八勿入爽爽影院| 国产一区二区三区在线播放免费观看| 国产欧美日韩精品丝袜高跟鞋| 孩xxxx性bbbb欧美| 国产精品96久久久久久| 亚洲欧美日韩视频一区| 日本精品va在线观看| 国产成人精品国内自产拍免费看| 18一19gay欧美视频网站| 久久这里有精品| 欧美精品在线极品| 91产国在线观看动作片喷水| 亚洲欧美三级在线| 日韩在线视频线视频免费网站| 精品视频久久久| 久久久久久一区二区三区| 成人免费看黄网站| 中文字幕欧美专区| 欧美高清视频免费观看| 中文字幕亚洲情99在线| 九九热这里只有精品免费看| 国产精品444| 欧美视频在线观看免费网址| 欧美日韩成人网| 久久av中文字幕| 亚洲成人aaa| 久久精品最新地址| 在线观看欧美日韩国产| 精品高清一区二区三区| 欧美精品成人91久久久久久久| 亚洲另类xxxx| 国产精品草莓在线免费观看| 亚洲白拍色综合图区| www.美女亚洲精品| 欧美电影免费看| 欧美日韩精品在线| 欧美精品国产精品日韩精品| 97超碰蝌蚪网人人做人人爽|