javascript---類與函數化

1.對象適合於收集和管理數據,容易造成樹型結構。
Javascript包括一個原型鏈特性,容許對象繼承另外一對象的屬性。正確的使用它能減小對象的初始化時間和內存消耗。
2.函數它們是javascript的基礎模塊單元,用於代碼複用、信息隱藏和組合調用。函數用於指定對象的行爲。通常來講,編程就是將一組需求分解成一組函數和數據結構的技能。
3.模塊咱們可使用函數和閉包來構造模塊。模塊是一個提供接口卻隱藏實現狀態和實現的函數或對象。javascript

1.自定義類型--構造函數模式(僞類模式)

在基於類的系統中,對象是這樣定義的:使用類來描述它是什麼樣的。假如建築是基於類的系統,則建築師會先畫出房子的藍圖,而後房子都按照該藍圖來建造。java

在使用自定義類型模式實現繼承的時候,咱們只須要將參數傳遞給構造函數,而後將參數掛載在實例對象上。其餘關於實例對象的方法都不用傳遞參數,由於經過 實例對象調用的方法內部的this均可以訪問到該參數。掛載在實例this對象上的變量稱爲實例變量。編程

組合--繼承

function Person (name, age, job) {
    // 實例變量
    this.name = name;
    this.age = age;
    this.job = job;
}
Person.prototype.sayName = function () {
    alert(this.name);
}

var person1 = new Person('Nicholas', 29, 'Software Engineer');
var person2 = new Person('Greg', 27, 'Doctor');
function SuperType (name) {
    this.name = name;
    this.colors = ['red','blue', 'green'];
}

SuperType.prototype.sayName = function () {
    console.log(this.name);
}

function SubType (name, age) {
    // 繼承屬性
    SuperType.call(this,name);
    this.age = age;
}

// 繼承方法
SubType.prototype = new SuperType();

SubType.prototype.sayAge = function () {
    console.log(this.age)
}

var instance1 = new SubType('Nicholas', 29);
instance1.colors.push('black')
console.log(instance1.colors);
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType('Greg', 27)
console.log(instance2.colors);
instance2.sayName();
instance2.sayAge();

在繼承屬性和繼承方法上,咱們一共調用了兩次超類構造函數,當經過new調用超類構造函數建立子類構造函數的原型時,有一個問題,子類構造函數的原型對象如今即是超類構造函數的實例,所以也會有在超類構造函數爲實例對象this添加的屬性,只是值爲undefined而已,也就是說經過new調用超類構造器函數來更改子類改造器的原型時,那麼在子類構造器的原型上便會有多餘的屬性。這便形成了浪費。而咱們須要的其實只是,子類構造器的原型可以繼承超類構造器原型的方法而已。所以咱們須要的,1.建立一個子類構造器原型對象。2.此子類構造器原型繼承自超類構造器的原型。3.由於咱們在1中改寫了子類構造器的原型對象,也就是從新建立了原型對象,所以咱們須要在新建立的原型對象上添加constructor屬性並將其賦值爲子類構造器函數。
將上面的代碼改寫一些,以下所示。數組

關於constructor屬性:只在構造器函數的原型上纔有的屬性並指向該構造器,改寫了的原型對象默認是沒有constructor屬性的。數據結構

寄生組合式--繼承

function inheritPrototype (subType,superType) {
    var prototype = Object.create(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
};

function SuperType (name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function () {
    console.log(this.name);
}
function SubType(name, age) {
    //繼承屬性
    SuperType.call(this,name);
    this.age = age;
}
//繼承方法
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function () {
    console.log(this.age);
}

var instance = new SubType();

經過隱藏那些所謂的prototype操做細節,如今看起來沒那麼怪異了。可是否真的有所發現:
沒有私有環境,全部屬性都是公開的。沒法訪問父類的方法。難以調試閉包

2.原型

在一個純粹的原型模式中,咱們會擯棄類,轉而專一對象。基於原型的繼承相比基於類的繼承在概念上更簡單:一個新對象能夠繼承一箇舊對象的屬性。你經過構造有用的對象開始,接着能夠構造更多和那個對象相似的對象。這就能夠徹底避免把一個應用拆解成一系列嵌套抽象類的分類過程app

在基於原型的系統中,咱們建立的對象,看起來要像咱們想要的全部這種類型的對象那樣,而後告訴javascript引擎,咱們想要更多像這樣的對象。若是建築是基於原型的,建築師會先建一所房子,而後將房子都建成像這種模樣的。函數

方法Object.creat()做爲new操做符的替代方案,使用它來建立javascript對象時,能增添一種更像是基於原型的感受。this

function myMammal = {
    name : 'Herb the Mammal',
    get_name : function () {
        return this.name;
    },
    says : function () {
        return this.saying || '';
    }
}

var myCat = Object.create(myMammal);
myCat.name = 'Henrietta';
myCat.saying = 'meow';
myCat.purr = function (n) {
    var i, s = '';
    for (i = 0;i < n; i += 1) {
        if(s) {
            s += '-'
        }
        s += 'r';
    }
    return s;
}

myCat.get_name = function () {
    return this.says + ' ' + this.name + this.says;
}

這是一種"差別化繼承"。經過定製一個新的對象,咱們指明它與所基於的基本對象的區別。
有時候,它對某些數據結構繼承於其餘數據結構的情形很是有用。prototype

3.函數化--工廠模式

在僞類模式裏,構造器函數Cat不得不重複構造器Mammal已經完成的工做。在函數化模式中那再也不須要了,由於構造器Cat將會調用構造器Mammal,讓Mammal去作對象建立中的大部分工做,全部Cat只關注自身的差別便可。

函數化模式有很大的靈活性。它相比僞類模式不只帶來的工做更少,還讓咱們獲得更好的封裝和信息隱藏,以及訪問父類方法的能力。
若是咱們用函數化得樣式去建立對象,而且該對象的全部方法都不用this或that,那麼該對象就是持久性的。一個持久性的對象就是一個簡單功能函數的集合。

私有變量:任何在函數中定義的變量,均可以認爲是私有變量,由於不能在函數外部訪問這些變量。

閉包

閉包是阻止垃圾回收器將變量從內存中移除的方法,使的在建立變量的執行環境的外面可以訪問到該變量。

請記住:閉包由函數建立。每次調用函數會建立一個惟一的執行環境對象。函數執行完後,執行對象就會被丟棄,除非調用者引用了它。固然,若是函數返回的是數字,就不能引用函數的執行環境對象。可是若是函數返回的是一個更復雜的結構,像是函數、對象或者數組,將返回值保存到一個變量上,就建立了一個對執行環境的引用。

Function.prototype.method = function (name,func) {
    this.prototype[name] = func;
    return this; 
}
// 工廠mammal函數
var mammal = function (spec) {
    var that = {};

    that.get_name = function () {
        return spec.name;
    }
    that.says = function (spec) {
        return spec.saying || '';
    } 

    return that;
}

// 工廠cat函數(基於mammal的函數)
var cat = function (spec) {
    spec.saying = spec.saying || 'meow';
    var that = mammal(spec);
    that.purr = function (n) {
        var i, s = '';
        for (i = 0; i < n; i += 1) {
            if(s) {
                s += '-';
            }
            s += 'r';
        }
    }
    that.get_name = function () {
        return that.says() + ' ' + spec.name + ' ' + that.says();
    }
    return that;
}

// 建立myCat對象
var myCat = cat({name: 'Henrietta'});

Object.method('superior',function (name) {
    var that = this,
        method = that[name];
    return function () {
        return method.apply(that, arguments)
    }
})

// 工廠coolcat函數(基於cat函數)
var coolcat = function (spec) {
    var that = cat(spec),
        super_get_name = that.superior('get_name');
    that.get_name = function (n) {
        return 'like ' + super_get_name() + ' baby';
    }
    return that;
}

var myCoolCat = coolcat({name : 'Bix'});

var name = myCoolCat.get_name();

函數化模塊模式有很大的靈活性。它相比構造函數模式不只帶來的工做更少,還讓咱們獲得更好的封裝休息和隱藏,以及訪問父類方法的能力。若是對象的全部狀態都是私有的,那麼該對象就成爲一個"防僞(tamper-proof)"對象。該對象的屬性是能夠被替換或者刪除,當該對象的完整性不會受到損壞。咱們用函數式的樣式建立一個對象,而且該對象的全部方法都不使用this或者that,那麼該對象就是持久性對象。一個持久性對象,就是一個簡單的函數功能的集合。
一個持久性的對象不會被入侵。訪問一個持久性的對象時,除非有方法受權,不然攻擊者不會訪問對象的內部狀態。

模塊模式

前面的模式是用於 自定義類型建立私有變量和特權方法的。而道格拉斯所說的模塊模式則是爲 單例建立私有變量和特權方法。所謂單例指的就是隻有一個實例的對象。(就是用對象字面量表示法建立的對象)

var singleton = function () {
    // 私有變量和函數
    var privateVariable = 10;

    function privateFunction () {
        return false;
    }
    //特權/公有方法和屬性
    return {
        publicProvperty: true;

        publicMethod: function () {
            privateVariable++;
            return privateFunction();
        }
    }
}

從本質上講,這個對象字面量定義的是單例的公共接口。這種模式在須要對單例進行某些初始化,同時又須要維護其私有變量時很是有用。簡言之,若是必須建立一個對象並以某些數據對其進行初始化,同時還要公開一些可以訪問這些私有數據的方法。

加強的模塊模式

這種加強的模塊模式適合那些單例必須是某種類型的實例,同時還必須添加某些屬性和方法對其加以加強的例子。

var singleton = function () {
    // 私有變量和函數
    var privateVariable = 10;

    function privateFunction () {
        return false
    }
    // 建立對象
    var object = new CustomType();

    // 添加特權/公有屬性和方法
    object.publicProperty = true;
    object.publicMethod = function () {
        privateVariable++;
        return privateFunction();
    }

    return object;
}()
相關文章
相關標籤/搜索