構(gòu)造函數(shù)和原型模式

構(gòu)造函數(shù)

function Persion(name,age,job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = function(){
        console.log(this.name);
    }
}
var person1 = new Person('Joke',29,"Teacher");
var person2 = new Person('Greg',39,"Doctor");  

上例中 person1,person2都是構(gòu)造函數(shù)Person的實(shí)例。
構(gòu)造函數(shù)其實(shí)與一般函數(shù)并沒有什么不同,不過一般默認(rèn)構(gòu)造函數(shù)的首字母大寫。它與一般函數(shù)的唯一區(qū)別就是通過new操作符來調(diào)用,其實(shí)任何函數(shù)只要通過new操作符來調(diào)用,那么他就可以作為構(gòu)造函數(shù)。上面的Person可以通過下面任何一種方式調(diào)用
1.當(dāng)做構(gòu)造函數(shù)調(diào)用

var person1 = new Person('Joke',29,"Teacher");

2.作為普通函數(shù)調(diào)用

Person('Joke','30','Doctor');
window.sayName();

3.在另一個(gè)對(duì)象的作用域中調(diào)用

var o = new Object();
Persion.call(0,'Joke',29,"Teacher");
o.sayName();

構(gòu)造函數(shù)的問題

構(gòu)造函數(shù)模式雖然好用,但是也有問題。使用構(gòu)造函數(shù)的主要問題就是每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍。在上面的例子中person1,person2都有sayName方法,但它們兩個(gè)的方法并不是同一個(gè)方法。這明顯是沒有必要的。

function Persion(name,age,job){
            this.name = name;
            this.age = age;
            this.job = job;
            this.sayName = sayName;
        }
        
        function sayName(){
            console.log(this.name);
        }

這樣可以解決每個(gè)實(shí)例都有一個(gè)做相同事情的方法,但是又有了新的問題,sayName是在全局定義的,所以它可以在任何地方調(diào)用,但我們的本意是要只是對(duì)象調(diào)用。

原型模式

我們創(chuàng)建的每一個(gè)函數(shù)都有一個(gè)prototype屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象,而這個(gè)對(duì)象的用途是包含可以由特定類型的所有實(shí)例共享的屬性和方法。如果按照字面意思來理解,那么prototype就是通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的對(duì)象實(shí)例的原型對(duì)象。原型的好處是可以讓所有實(shí)例共享它所包含的屬性和方法。

function Person() {}
        Person.prototype.name = 'Nice';
        Person.prototype.age = 20;
        Person.prototype.job = 'Doctor';
        Person.prototype.sayName = function() {
            console.log(this.name)
        }
        // 也可以這樣寫
        // Person.prototype = {
        //  name:'Nice',
        //  age:20,
        //  job:'Doctor',
        //  sayName:function(){
        //   console.log(this.name)
        //  }
        // }
        var p1 = new Person();
        p1.sayName();
        //p1.sayJob();//p1.sayJob is not a function

無論什么時(shí)候,只要?jiǎng)?chuàng)建了一個(gè)新函數(shù),就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè)prototype 屬性,這個(gè)屬性指向函數(shù)的原型對(duì)象。在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)constructor屬性,這個(gè)屬性包含一個(gè)指向prototype屬性所在函數(shù)的指針。就拿前面的例子來說。

console.log(Person.prototype.constructor) //? Person(){}
        Person.prototype.sayJob = function() {
            console.log(this.job);
        }
        var p2 = new Person();
        p2.job = '老師';
        p2.sayJob();

原型的問題

原型模式也不是沒有缺點(diǎn),首先,它身略了為構(gòu)造函數(shù)傳遞初始化參數(shù)的環(huán)節(jié),結(jié)果所有的實(shí)例默認(rèn)情況下都有相同的屬性值。但這不是最大的問題,最大的問題還是共享的本質(zhì)導(dǎo)致的。原型中的所有屬性都是共享的,這種共享對(duì)函數(shù)時(shí)非常適合的,對(duì)于屬性也可以通過在實(shí)例中添加同名屬性覆蓋原型屬性。但是對(duì)于包含引用類型值的屬性來說,問題就比較突出了。

function Person() {}
        Person.prototype = {
            name: 'Nice',
            age: 20,
            job: 'Doctor',
            friends:['張勝男','李時(shí)'],
            sayName: function() {
                console.log(this.name)
            }
        }
        var p1 = new Person();
        var p2 = new Person();
        p1.friends.push('p1Friend');
        // 由于js 引用類型的特質(zhì)
        console.log(p2.friends)//["張勝男", "李時(shí)", "p1Friend"]

組合使用構(gòu)造函數(shù)和原型模式

//組合使用構(gòu)造函數(shù)和原型模式
        function Person(name,age,job){
            this.name = name;
            this.age = age;
            this.job = job;
            this.friends = ['李三','王二'];
        }
        Person.prototype = {
            constructor:Person,
            sayName:function(){
                console.log(this.name)
            }
        }
        var p1 = new Person('流氓',20,'盲流');
        var p2 = new Person('方子',23,'盲流');
        p1.friends.push('p1的新朋友');
        console.log(p1.friends)//["李三", "王二", "p1的新朋友"]
        console.log(p2.friends)// ["李三", "王二"]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容