js面向?qū)ο?/a>
面向?qū)ο蟮挠⑽娜Q叫做Object Oriented,簡(jiǎn)稱OO。OO其實(shí)包括OOA(Object Oriented Analysis,面向?qū)ο蠓治?、OOD(Object Oriented Design,面向?qū)ο笤O(shè)計(jì))和OOP(Object Oriented Programming,面向?qū)ο蟮某绦蛟O(shè)計(jì))。
通常所說(shuō)的面向?qū)ο笫侵窸OP, OOP是一種圍繞真實(shí)世界的概念來(lái)組織模型的程序設(shè)計(jì)方法,它采用對(duì)象來(lái)描述問(wèn)題空間的實(shí)體。在使用計(jì)算機(jī)解決問(wèn)題時(shí),對(duì)象是作為計(jì)算機(jī)模擬真實(shí)世界的一個(gè)抽象,一個(gè)對(duì)象就是一個(gè)物理實(shí)體或邏輯實(shí)體,它反映了系統(tǒng)為之保存信息和(或)與它交互的能力。使其具有自己的屬性和行為, 從而簡(jiǎn)化對(duì)復(fù)雜事物的描述,更有利于工程的可維護(hù)性和擴(kuò)展性。
OOP同結(jié)構(gòu)化程序設(shè)計(jì)相比最大的區(qū)別就在于: 前者首先關(guān)心的是所要處理的數(shù)據(jù),而后者首先關(guān)心的是功能。
【二】 面向?qū)ο笕齻€(gè)基本特征
封裝 (Encapsulation) 將數(shù)據(jù)以及相關(guān)的操作組織在一起,成為獨(dú)立的構(gòu)件。外部無(wú)法直接訪問(wèn)這些封裝了的數(shù)據(jù),從而保證了這些數(shù)據(jù)的正確性。封裝的目的是為了內(nèi)部數(shù)據(jù)表現(xiàn)形式和實(shí)現(xiàn)細(xì)節(jié)的隱藏,信息隱藏是為了減少系統(tǒng)各部分間的依賴性,各部分間必須通過(guò)明確的通道傳送信息,也就是對(duì)象間的接口.這樣一來(lái),隱藏了部分內(nèi)部的細(xì)節(jié),極大方便系統(tǒng)的開(kāi)發(fā),維護(hù)和擴(kuò)展。
繼承 (Inheritance) 繼承是一種聯(lián)結(jié)類的層次模型,并且允許和鼓勵(lì)類的重用,它提供了一種明確表述共性的方法。一個(gè)新類可以從現(xiàn)有的類中派生,這個(gè)過(guò)程稱為類的繼承。新類繼承了原始類的特性,新類稱為原始類的派生類(子類),而原始類稱為新類的基類(父類)。派生類可以從它的基類那里繼承方法和實(shí)例變量,并且派生類可以修改或增加新的方法使之更適合特殊的需求。繼承性很好地解決了軟件的可重用性問(wèn)題。
多態(tài) (Polymorphism) 多態(tài)是允許你將父對(duì)象設(shè)置成為和一個(gè)或更多的他的子對(duì)象相等的技術(shù),賦值之后,父對(duì)象就可以根據(jù)當(dāng)前賦值給它的子對(duì)象的特性以不同的方式運(yùn)作。簡(jiǎn)單的說(shuō),就是允許類與類之間相同方法名的指針得以調(diào)用, 這樣很好地解決了應(yīng)用程序函數(shù)同名問(wèn)題。實(shí)現(xiàn)多態(tài),有二種方式,覆蓋,重載。
【三】 Javascript 面向?qū)ο?/strong>
javascript本身是一種基于對(duì)象(object-based)的語(yǔ)言,我們?nèi)粘>幋a過(guò)程中用到的所有東西幾乎都是對(duì)象(Number, String, Boolean, etc.)。但是,相對(duì)于一些流行的面向?qū)ο笳Z(yǔ)言(C++, C#, java),它又不是一種真正的面向?qū)ο缶幊?OOP)語(yǔ)言,因?yàn)樗恼Z(yǔ)法中沒(méi)有class的概念。
Keyword: class, object, `this`, closure, constructor, prototype
幾種對(duì)象封裝的方法
- 繼承
- 多態(tài)體現(xiàn)
之一、幾種對(duì)象封裝的方法
1. 對(duì)象封裝 – 原始模式
假定我們把貓看成一個(gè)對(duì)象,它有”name”和”color”兩個(gè)屬性, “etc” 行為。
var Cat = { name: '' color: '', eat: function() {} };
現(xiàn)在,我們需要根據(jù)這個(gè)原型對(duì)象的規(guī)格(schema),生成兩個(gè)實(shí)例對(duì)象。
function eat() { console.log('I\'m eta fish'); } var cat1 = {name: 'Kitty', color: 'white', eat: eat}; var cat2 = {name: 'Smokey', color: 'black', eat: eat}; // var cat3, cat4 ,...
不方便創(chuàng)建多個(gè)實(shí)例對(duì)象,擴(kuò)展性差, 實(shí)例(cat1, cat2)之間找不到聯(lián)系。…
2. 對(duì)象封裝 – 構(gòu)造函數(shù)模式
“構(gòu)造函數(shù)”,就是一個(gè)普通函數(shù),但是內(nèi)部使用了 `this` 變量。對(duì)函數(shù)使用 `new` 運(yùn)算符,就能生成實(shí)例,并且 `this` 變量會(huì)綁定在實(shí)例對(duì)象上。
使用構(gòu)造器創(chuàng)建出來(lái)的對(duì)象會(huì)有一個(gè) `constructor` 屬性,指向它們的構(gòu)造函數(shù)。
`Class` 只是一個(gè)模板,創(chuàng)建出來(lái)的來(lái)實(shí)例都是由模板生成。
比如,貓的原型對(duì)象現(xiàn)在可以這樣寫(xiě):
function Cat(name,color){ this.name = name; this.color = color; this.eat = function() { console.log('eat fish'); }; } var cat1 = new Cat('Kitty', 'black'); console.log(cat1.name); // Kitty console.log(cat1 instanceof Cat); // TRUE // 這時(shí) cat1 實(shí)例會(huì)自動(dòng)含有一個(gè) `constructor` 屬性,指向它們的構(gòu)造函數(shù) `Cat`。 var cat2 = Cat('Smokey', 'white'); console.log(cat2); // undefined
3. 對(duì)象封裝 – Prototype 模式
`prototype` 是 `Function` 對(duì)象的一個(gè)屬性,這個(gè)屬性指向另一個(gè)對(duì)象。 這個(gè)對(duì)象的所有屬性和方法,都會(huì)被構(gòu)造函數(shù)的實(shí)例繼承。
同時(shí) `prototype` 又存在一個(gè)指向構(gòu)造函數(shù)的引用 `constructor`,這樣就成功的構(gòu)成一個(gè)循環(huán)引用的原型鏈結(jié)構(gòu)。
我們可以把那些不變的屬性和方法,直接定義在 `prototype` 對(duì)象上, 節(jié)省內(nèi)存開(kāi)銷。
function Cat(name, color) { this.name = name; this.color = color; } Cat.prototype.type = 'mammal'; Cat.prototype.eat = function() { console.log('eat fish'); }; var cat1 = new Cat('Kitty', 'white'); var cat2 = new Cat('Smokey', 'black'); console.log(cat1.type); // mammal console.log(cat1.eta === cat2.eta); // TRUE, same reference console.log(cat1.constructor === Cat) // TRUE, from Person.prototype
之二、繼承 (Inheritance)
將持有共性特點(diǎn)的屬性或行為抽象出一個(gè)基本類, 可以按不同層次結(jié)構(gòu)的業(yè)務(wù)分組抽象出多個(gè)基礎(chǔ)類。
Cat, Bird
1. 繼承 – 構(gòu)造函數(shù)綁定
使用call或apply方法,將父對(duì)象的構(gòu)造函數(shù)綁定在子對(duì)象上。
function Animal() { this.species = 'animal'; this.sleep = function() { console.log('I\'m sleep at night'); }; } function Cat(name, color) { this.name = name; this.color = color; }
讓`Cat` 繼承 `Animal` 的特性:
/** @class Cat */ function Cat(name, color) { Animal.apply(this); this.name = name; this.color = color; } var cat1 = new Cat('Kitty', 'white'); cat1.sleep(); // I am sleep at night
2. 繼承 – 原型鏈繼承
如果”貓”的prototype對(duì)象,指向一個(gè)Animal的實(shí)例,那么所有”貓”的實(shí)例,就能繼承Animal了。
/** @class Cat */ function Cat(name, color) { this.name = name; this.color = color; } Cat.prototype = new Animal; Cat.prototype.eta = function() { console.log('fish is my delicious'); };
它相當(dāng)于完全刪除了prototype 對(duì)象原先的值,然后賦予一個(gè)新值
// 任何一個(gè)prototype對(duì)象都有一個(gè)constructor屬性,指向它的構(gòu)造函數(shù) Cat.prototype.constructor = Cat; // fix prototype chains var cat = new Cat('Kitty', 'fish'); cat.eat(); // fish is my delicious cat.sleep(); // I'm sleep at night' console.log(cat instanceof Cat); // TRUE console.log(cat instanceof Animal); // TRUE
需要?jiǎng)?chuàng)建父類實(shí)列來(lái)實(shí)現(xiàn) `prototype` 繼承
3. 繼承 (Inheritance) – 利用空對(duì)象作為中介實(shí)現(xiàn)原型繼承
var F = function() {}; F.prototype = Animal.prototype; Cat.prototype = new F(); Cat.prototype.constructor = Cat;
我們將上面的方法,封裝成一個(gè)函數(shù),便于使用。
function extend(ctor, superctor, px) { if (!superctor || !ctor) throw Error('extend failed, verify dependencies'); var F = function() {}; F.prototype = superctor.prototype; ctor.prototype = new F(); ctor.prototype.constructor = ctor; ctor.superclass = superctor.prototype; // cache super class proto reference. if (px) { // extend class implements for (var k in px) { if (px.hasOwnProperty(k)) ctor.prototype[k] = px[k]; } } return ctor; }
4 繼承 – 借住工具方法實(shí)現(xiàn)繼承
/** @class Mammal */ extend(Cat, Animal, { eat: function() { Cat.superclass.eat.call(this); // call super method console.log('Also i like some ofther food, such as beef and more.'); } }); var cat = new Cat('Smokey', 'fish'); cat.sleep(); cat.eat(); console.log(cat instanceof Animal); console.log(cat instanceof Cat);
之三、多態(tài)
1. 多態(tài) – 通過(guò)重寫(xiě)原型方法來(lái)實(shí)現(xiàn)方法重名調(diào)用
/** @class Cat */ extend(Cat, Animal, { eat: function() { Cat.superclass.eat.call(this); // call super method console.log('Also i like some ofther food, such as beef and more.'); } });
2. 多態(tài) (Polymorphism) – 原型繼承 `prototype` 鏈上的方法、屬性查找
【四】總結(jié) Summary
Constructor
Prototype
Inheritance
posted on 2013-01-16 12:52 楊軍威 閱讀(346) 評(píng)論(0) 編輯 收藏