javascript 物件導向

來源:互聯網
上載者:User

標籤:

物件導向編程是用抽象方式建立基於現實世界模型的一種編程模式。它使用先前建立的範例,包括模組化,多態和封裝幾種技術。今天,許多流行的程式設計語言 (如Java,JavaScript,C#,C+ +,Python,PHP,Ruby和Objective-C)都支援物件導向編程(OOP)。

物件導向編程可以看作是使用一系列對象相互協作的軟體設計,相對於傳統觀念,一個程式只是一些函數的集合,或簡單的電腦指令列表。 在OOP中,每個對象能夠接收訊息,處理資料和發送訊息給其他對象。每個對象都可以被看作是一個擁有清晰角色或責任的獨立小機器。

物件導向程式設計的目的是在編程中促進更好的靈活性和可維護性,在大型軟體工程中廣為流行。憑藉其對模組化的重視,物件導向的代碼開發更簡單,更容易理解,相比非模組化編程方法 1, 它能更直接地分析, 編碼和理解複雜的情況和過程。
JavaScript物件導向編程

命名空間是一個容器,它允許開發人員在一個獨特的,特定於應用程式的名稱下捆綁所有的功能。 在JavaScript中,命名空間只是另一個包含方法,屬性,對象的對象。

創造的JavaScript命名空間背後的想法很簡單:一個全域對象被建立,所有的變數,方法和功能成為該對象的屬性。使用命名空間也最大程度地減少應用程式的名稱衝突的可能性。

我們來建立一個全域變數叫做 MYAPP

// 全域命名空間
var MYAPP = MYAPP || {};

在上面的程式碼範例中,我們首先檢查MYAPP是否已經被定義(是否在同一檔案中或在另一檔案)。如果是的話,那麼使用現有的MYAPP全域對象,否則,建立一個名為MYAPP的Null 物件用來封裝方法,函數,變數和對象。

var MYAPP = MYAPP || {};
MYAPP.commonMethod ={
    regExForName : "walter",
    regExForNameB:function(name){
        alert(this.regExForName);
    }
}
MYAPP.commonMethod.regExForNameB();    ====> "Walter";
標準內建對象

JavaScript有包括在其核心的幾個對象,例如,Math,Object,Array和String對象。下面的例子示範了如何使用Math對象使用其隨機()方法來獲得一個隨機數。
標準內建對象

JavaScript有包括在其核心的幾個對象,例如,Math,Object,Array和String對象。下面的例子示範了如何使用Math對象使用其隨機()方法來獲得一個隨機數。
自訂對象
類

function Person() { }
// 或
var Person = function(){ }

例子

function Person(firstname){
    this.lastName = firstname
};
var person1 = new Person("gavin");
var person2 = new Person("walter");
alert(person1.lastName);
alert(person2.lastName);

方法(對象屬性)

方法與屬性很相似, 不同的是:一個是函數,另一個可以被定義為函數。 調用方法很像存取一個屬性,  不同的是add () 在方法名後面很可能帶著參數. 為定義一個方法, 需要將一個函數賦值給類的 prototype 屬性; 這個賦值給函數的名稱就是用來給對象在外部調用它使用的。

在下面的樣本中,我們給Person類定義了方法 sayHello(),並調用了它.

function Person(firstName) {
  this.firstName = firstName;
}

Person.prototype.sayHello = function() {
  alert("Hello, I‘m " + this.firstName);
};

var person1 = new Person("Alice");
var person2 = new Person("Bob");

// call the Person sayHello method.
person1.sayHello(); // alerts "Hello, I‘m Alice"
person2.sayHello(); // alerts "Hello, I‘m Bob"

在JavaScript中方法通常是一個綁定到對象中的普通函數, 這意味著方法可以在其所在context之外被調用。 思考下面樣本中的代碼:

function Person(firstName) {
  this.firstName = firstName;
}

Person.prototype.sayHello = function() {
  alert("Hello, I‘m " + this.firstName);
};

var person1 = new Person("Alice");
var person2 = new Person("Bob");
var helloFunction = person1.sayHello;

person1.sayHello();                                 // alerts "Hello, I‘m Alice"
person2.sayHello();                                 // alerts "Hello, I‘m Bob"
helloFunction();                                    // alerts "Hello, I‘m undefined" (or fails
                                                    // with a TypeError in strict mode)
alert(helloFunction === person1.sayHello);          // alerts true
alert(helloFunction === Person.prototype.sayHello); // alerts true
helloFunction.call(person1);                        // alerts "Hello, I‘m Alice"

如上例所示, 所有指向sayHello函數的引用 ,包括 person1, Person.prototype, 和 helloFunction 等, 均引用了相同的函數.

在調用函數的過程中,this的值取決於我們怎麼樣調用函數.  在通常情況下,我們通過一個運算式person1.sayHello()來調用函數:即從一個對象的屬性中得到所調用的函數。此時this被設定為我們取得函數的對象(即person1)。這就是為什麼person1.sayHello() 使用了姓名“Alice”而person2.sayHello()使用了姓名“bob”的原因。

然而我們使用不同的調用方法時, this的值也就不同了。當從變數 helloFunction()中調用的時候, this就被設定成了全域對象 (在瀏覽器中即window)。由於該對象 (非常可能地) 沒有firstName 屬性, 我們得到的結果便是"Hello, I‘m undefined". (這是鬆散模式下的結果, 在 strict 模式中,結果將不同(此時會產生一個error)。 但是為了避免混淆,我們在這裡不涉及細節) 。另外,我們可以像上例末尾那樣,使用Function#call (或者Function#apply)顯式的設定this的值。

 
繼承

 

建立一個或多個類的專門版本類方式稱為繼承(Javascript只支援單繼承)。 建立的專門版本的類通常叫做子類,另外的類通常叫做父類。 在Javascript中,繼承通過賦予子類一個父類的執行個體並專門化子類來實現。在現代瀏覽器中你可以使用 Object.create 實現繼承.

JavaScript 並不檢測子類的 prototype.constructor (見 Object.prototype), 所以我們必須手動申明它.

在下面的例子中, 我們定義了 Student類作為 Person類的子類. 之後我們重定義了sayHello() 方法並添加了 sayGoodBye() 方法.

 

// 定義Person構造器
function Person(firstName) {
  this.firstName = firstName;
}

// 在Person.prototype中加入方法
Person.prototype.walk = function(){
  alert("I am walking!");
};
Person.prototype.sayHello = function(){
  alert("Hello, I‘m " + this.firstName);
};

// 定義Student構造器
function Student(firstName, subject) {
  // 調用父類構造器, 確保(使用Function#call)"this" 在調用過程中設定正確
  Person.call(this, firstName);

  // 初始化Student類特有屬性
  this.subject = subject;
};

// 建立一個由Person.prototype繼承而來的Student.prototype對象.
// 注意: 常見的錯誤是使用 "new Person()"來建立Student.prototype.
// 這樣做的錯誤之處有很多, 最重要的一點是我們在執行個體化時
// 不能賦予Person類任何的FirstName參數
// 調用Person的正確位置如下,我們從Student中來調用它
Student.prototype = Object.create(Person.prototype); // See note below

// 設定"constructor" 屬性指向Student
Student.prototype.constructor = Student;

// 更換"sayHello" 方法
Student.prototype.sayHello = function(){
  alert("Hello, I‘m " + this.firstName + ". I‘m studying " + this.subject + ".");
};

// 加入"sayGoodBye" 方法
Student.prototype.sayGoodBye = function(){
  alert("Goodbye!");
};

// 測試執行個體:
var student1 = new Student("Janet", "Applied Physics");
student1.sayHello();   // "Hello, I‘m Janet. I‘m studying Applied Physics."
student1.walk();       // "I am walking!"
student1.sayGoodBye(); // "Goodbye!"

// Check that instanceof works correctly
alert(student1 instanceof Person);  // true
alert(student1 instanceof Student); // true

 

 

對於“Student.prototype = Object.create(Person.prototype);”這一行,在不支援 Object.create方法的老JavaScript引擎中,可以使用一個"polyfill"(又名"shim",查看文章連結),或者使用一個function來獲得相同的傳回值,就像下面:

function createObject(proto) {
    function ctor() { }
    ctor.prototype = proto;
    return new ctor();
}

// Usage:
Student.prototype = createObject(Person.prototype);

更多相關資訊請參考 Object.create,串連中還有一個老JavaScript引擎的相容方案(shim)。
封裝

在上一個例子中,Student類雖然不需要知道Person類的walk()方法是如何?的,但是仍然可以使用這個方法;Student類不需要明確地定義這個方法,除非我們想改變它。 這就叫做封裝,對於所有繼承自父類的方法,只需要在子類中定義那些你想改變的即可。
抽象

抽象是允許類比工作問題中通用部分的一種機制。這可以通過繼承(具體化)或組合來實現。
JavaScript通過繼承實現具體化,通過讓類的執行個體是其他對象的屬性值來實現組合。

JavaScript Function 類繼承自Object類(這是典型的具體化) 。Function.prototype的屬性是一個Object執行個體(這是典型的組合)。

var foo = function(){};
alert( ‘foo is a Function: ‘ + (foo instanceof Function) );                  // alerts "foo is a Function: true"
alert( ‘foo.prototype is an Object: ‘ + (foo.prototype instanceof Object) ); // alerts "foo.prototype is an Object: true"

多態

就像所有定義在原型屬性內部的方法和屬性一樣,不同的類可以定義具有相同名稱的方法;方法是作用於所在的類中。並且這僅在兩個類不是父子關係時成立(繼承鏈中,一個類不是繼承自其他類)。
注意

本文中所展示的物件導向編程技術不是唯一的實現方式,在JavaScript中物件導向的實現是非常靈活的。

同樣的,文中展示的技術沒有使用任何語言hacks,它們也沒有模仿其他語言的對象理論實現。

JavaScript中還有其他一些更加先進的物件導向技術,但這些都超出了本文的介紹範圍。

 文章來源:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#The_Object_.28Class_Instance.29

使用Object.create實作類別式繼承
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create


 

javascript 物件導向

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.