JS面向?qū)ο?-基礎(chǔ)知識(shí)(2)

面向?qū)ο蟮奶匦裕?/p>

  • 封裝
  • 繼承
  • 多態(tài)

封裝
作用:方便代碼的維護(hù),提高代碼的復(fù)用性,更安全的訪問(wèn)數(shù)據(jù)的方式
注意:js中的封裝多了一層意思,就是使用對(duì)象來(lái)封裝變量和函數(shù)

繼承
現(xiàn)實(shí)生活中的繼承:繼承遺產(chǎn),一個(gè)人獲得另一個(gè)人所擁有的財(cái)富或者是資源的方式。
編程語(yǔ)言中的繼承:一個(gè)類(對(duì)象)獲得另外一個(gè)類(對(duì)象)的屬性和方法的一種方式。

多態(tài)

  • 多種表現(xiàn)形態(tài):
    對(duì)于相同的操作,不同的對(duì)象表現(xiàn)出不同的行為。

  • 實(shí)現(xiàn):
    js天生具備多態(tài)的特性(弱類型的語(yǔ)言)


創(chuàng)建對(duì)象的幾種方式

  • 字面量法
    結(jié)構(gòu)
    var 對(duì)象 = {
    屬性名01:屬性值,
    屬性名02:屬性值,
    方法01:function(){函數(shù)體}
    }
    適用場(chǎng)合:只需簡(jiǎn)單創(chuàng)建單個(gè)對(duì)象
    問(wèn)題:如果需要?jiǎng)?chuàng)建多個(gè)相似的對(duì)象,那么代碼中冗余度太高(重復(fù)的代碼太多)
    代碼:
var book1 = {
        name:"悟空傳",
        author:"今何在",
        press:"湖南文藝出版社",
        price:"28.00",
        logDes:function(){
            console.log("書名:" + this.name + "作者:" + this.author);
        }
    }
  • 內(nèi)置構(gòu)造函數(shù)法
 var book1 = new Object();
    //01 設(shè)置屬性
    book1.name = "花田半畝";
    book1.author = "田維";
    book1.price = "40.01";

    //02 設(shè)置方法
    book1.logDes = function (){
        console.log("書名:" + this.name);
    }

問(wèn)題:如果需要?jiǎng)?chuàng)建多個(gè)相似的對(duì)象,那么代碼中冗余度太高(重復(fù)的代碼太多)

  • 工廠法
    對(duì)于內(nèi)置法把固定的部分提取寫成函數(shù)的函數(shù)體,把變化的部分提取,作為參數(shù)傳遞
function createBook(name,author){
        //01 創(chuàng)建空的對(duì)象
        var o = new Object();
        //02 設(shè)置屬性和方法
        o.name = name;
        o.author = author;
        o.logDes = function(){
            console.log("作者是:" + this.author);
        }

        //04 返回新創(chuàng)建的對(duì)象
        return o;
    }

問(wèn)題:如果創(chuàng)建多個(gè)不同類型的對(duì)象,那么我們無(wú)法分辨

function createPerson(name,age){
        var o = new Object();
        o.name = name;
        o.age = age;
        return o;
    }

    function createDog(name,age)
    {
        var o = new Object();
        o.name = name;
        o.age = age;
        return o;
    }

    //創(chuàng)建具體的對(duì)象
    var obj1 = createPerson("張三",88);
    var obj2 = createDog("阿黃",6);

    
    console.log(obj1.constructor);  //Object
    console.log(obj2.constructor);  //Object

最終的返回值類型都是Object類型,只看結(jié)果不能夠準(zhǔn)確的辨認(rèn)obj1和obj2對(duì)應(yīng)的都是誰(shuí)

  • 構(gòu)造法
    001 提供一個(gè)構(gòu)造函數(shù)
    002 通過(guò)this指針來(lái)設(shè)置屬性和方法
    003 通過(guò)new操作符創(chuàng)建對(duì)象
function Person(name,age){
        // 默認(rèn) 創(chuàng)建對(duì)象
        //var o = new Object();

        //默認(rèn)會(huì)賦值給this
        //this = o;

        // 01 通過(guò)this指針來(lái)設(shè)置屬性和方法
        this.name = name;
        this.age = age;
        this.showName = function(){
            console.log(this.name);
        };
        this.showAge = function(){
            console.log(this.age);
        }

        //默認(rèn)返回
        //return this;
    }

    //03 使用new操作符來(lái)創(chuàng)建對(duì)象
    var p1 = new Person("張三",20);
    var p2 = new Person("張老漢",200);
    console.log(p1);
    console.log(p2);

自定義構(gòu)造函數(shù)方式創(chuàng)建對(duì)象內(nèi)部的實(shí)現(xiàn)細(xì)節(jié)
01 我們?cè)谑褂胣ew關(guān)鍵字調(diào)用構(gòu)造函數(shù)的時(shí)候,內(nèi)部默認(rèn)會(huì)創(chuàng)建一個(gè)空的對(duì)象
02 默認(rèn)會(huì)把這個(gè)空的對(duì)象賦值給this
03 通過(guò)this來(lái)設(shè)置新對(duì)象的屬性和方法
04 在構(gòu)造函數(shù)的最后,默認(rèn)會(huì)把新創(chuàng)建的對(duì)象返回

自定義構(gòu)造函數(shù)和工廠函數(shù)對(duì)比
001 函數(shù)的名稱不一樣,構(gòu)造函數(shù)首字母大寫
002 自定義構(gòu)造函數(shù)創(chuàng)建方式內(nèi)部會(huì)自動(dòng)的創(chuàng)建空對(duì)象并且賦值給this
003 默認(rèn)會(huì)自動(dòng)返回新創(chuàng)建的對(duì)象

返回值
01 沒(méi)有顯示的return ,默認(rèn)會(huì)把新創(chuàng)建的對(duì)象返回
02 顯示的執(zhí)行了return語(yǔ)句,就得看具體的情況
001 返回的是值類型,那么直接忽略該返回,把新創(chuàng)建的對(duì)象返回
002 返回的是引用類型的數(shù)據(jù),會(huì)覆蓋掉新創(chuàng)建的對(duì)象,直接返回引用數(shù)據(jù)類型的值

function Dog(name)
        {
            this.name = name;
            //return "demo";  忽略
            return function (){console.log(name);};最終返回的值
        }

        var dog = new Dog("阿黃");
        console.log(dog);

        //function (){console.log(name) -->返回值

當(dāng)然這也不是自定義構(gòu)造函數(shù)的最終類型,最終類型將在下面講解。


接下來(lái)的內(nèi)容均是建立在自定義構(gòu)造函數(shù)上的

instanceOf:判斷當(dāng)前對(duì)象是否是某個(gè)對(duì)象的實(shí)例

 function Person(){};
    function Dog(){};

 var p1 = new Person();
 var dog1 = new Dog();

 console.log(p1 instanceof Person);//true
 console.log(dog1 instanceof Dog);//true

constructor:構(gòu)造器屬性(獲取)
console.log(p1.constructor);//function Person(){}

構(gòu)造函數(shù)原型對(duì)象

  • 原型對(duì)象:在使用構(gòu)造函數(shù)創(chuàng)建對(duì)象的時(shí)候,默認(rèn)的會(huì)生成一個(gè)與之關(guān)聯(lián)的對(duì)象,這個(gè)對(duì)象就是原型對(duì)象。默認(rèn)情況下,該對(duì)象是一個(gè)空的對(duì)象({})

  • 原型對(duì)象的作用:使用構(gòu)造函數(shù)創(chuàng)建的對(duì)象,能夠自動(dòng)擁有原型對(duì)象中所有的屬性和方法

  • 如何訪問(wèn)原型對(duì)象
    ① 構(gòu)造函數(shù).prototype
    ② 對(duì)象.__proto__

  • 如何設(shè)置原型對(duì)象
    ① 可以像設(shè)置普通對(duì)象一樣來(lái)利用對(duì)象的動(dòng)態(tài)特性設(shè)置屬性和方法
    ② 使用字面量的方法來(lái)設(shè)置原型對(duì)象(直接替換)

  • 約定
    正確的說(shuō)法:該對(duì)象的構(gòu)造函數(shù)的原型對(duì)象
    構(gòu)造函數(shù)的原型
    構(gòu)造函數(shù)的原型對(duì)象
    對(duì)象的原型對(duì)象
    對(duì)象的原型
    以上四種說(shuō)法,她們的意思是一樣的,都是該對(duì)象的構(gòu)造函數(shù)的原型對(duì)象

原型對(duì)象的屬性和方法的設(shè)置:
構(gòu)造函數(shù).prototype.屬性

實(shí)例化
通過(guò)構(gòu)造函數(shù)創(chuàng)建對(duì)象的過(guò)程,就叫做實(shí)例化

實(shí)例
通過(guò)構(gòu)造函數(shù)創(chuàng)建的對(duì)象被稱為該構(gòu)造函數(shù)的實(shí)例。一般在說(shuō)實(shí)例的時(shí)候,需要指定構(gòu)造函數(shù)。也就是說(shuō),我們通常會(huì)說(shuō)這個(gè)對(duì)象是XXX構(gòu)造函數(shù)實(shí)例

 function Dog(){};
 Dog.prototype.des = "描寫信息";
 var dog = new Dog();

原型的使用方法
利用對(duì)象的動(dòng)態(tài)特性來(lái)設(shè)置原型對(duì)象

function Person(){
        this.name = "默認(rèn)的名稱";
    }

    //設(shè)置原型對(duì)象
    //成員= 屬性|方法
    //01 增加成員
    Person.prototype.des = "我是直立行走的人";
    Person.prototype.logName = function(){
        console.log(this.name);
    };

    //02 修改成員
    Person.prototype.des = "我是直立行走的人++++";
    //console.log(Person.prototype);

    var p1 = new Person();
    console.log(p1.des);
    p1.logName();

    //03 刪除成員
    //delete關(guān)鍵字
    //語(yǔ)法  delete 對(duì)象.屬性
    //console.log(delete p1.des);  //不能用這種方式刪除原型對(duì)象上面的屬性(刪除的是自己的屬性)

    delete Person.prototype.des ;
    console.log(p1.des);

替換原型對(duì)象(字面量)

注意點(diǎn):

  • 如果是替換了原型對(duì)象,那么在替換之前創(chuàng)建的對(duì)象和替換之后創(chuàng)建的對(duì)象她們指向的原型對(duì)象并不是同一個(gè)
  • 構(gòu)造器屬性:在替換之后創(chuàng)建的對(duì)象中,它的構(gòu)造器屬性指向的不是Person構(gòu)造函數(shù),而是Object的原型對(duì)象的構(gòu)造器屬性

建議
在設(shè)置完原型對(duì)象之后再統(tǒng)一的創(chuàng)建對(duì)象。

    function Person(){
        this.age = 40;
    }
    var p1 = new Person();
    Person.prototype.sayHi = function(){
        console.log("hi");
    };

    //設(shè)置原型對(duì)象
    Person.prototype = {
        name:"默認(rèn)的名稱",
        showName:function(){
            console.log(this.name);
        }
    };

    var p2 = new Person();

//    p1.sayHi();  //可以
//    p2.sayHi(); //不可以
//    console.log(p1.name);  //undefined
//    console.log(p2.name); //默認(rèn)的名稱
//    p1.showName();         //報(bào)錯(cuò)
//    p2.showName();         //默認(rèn)的名稱
    function Person(){
        this.age = 40;
    }
    var p1 = new Person();

    //var obj = new Object();
    Person.prototype = {
        //注意:如果替換了原型對(duì)象,那么需要在原型對(duì)象中修正構(gòu)造器屬性
        constructor:Person,//***
        sayHi:function (){
            console.log("hi");
        }
    };
    var p2 = new Person();
    //p2.constructor = Person;   //在p2對(duì)象上添加了一個(gè)屬性(constructor)

    //var p3 = new Person();


    //構(gòu)造器屬性
    console.log(p1.constructor == p2.constructor);  //如果不添加***所在句則false
//    console.log(p1.constructor);    //Person
//    console.log(p2.constructor);    //Object
//    console.log(p2.constructor == p2.__proto__.constructor);
//    console.log(p2.constructor == Object.prototype.constructor);

    console.log(p2);

構(gòu)造器:
屬性:constructor
值:與之關(guān)聯(lián)的構(gòu)造函數(shù)
注意點(diǎn):constructor是在原型對(duì)象身上的,我們通過(guò)對(duì)象.constructor訪問(wèn)得到的值其實(shí)就是原型對(duì)象中對(duì)應(yīng)的值

暫時(shí)先更新到這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容