javascript: 基於原型的物件導向程式設計

weixin_34391854發表於2018-01-15

Douglas Crockford指出javascript是世界上最被誤解的程式語言。由於javascript缺少常見的物件導向概念,許多程式猿認為javascript不是一個合適的語言。我在做第一個javascript專案時候也發現不能將程式碼放在一個類中。其實大部分程式猿不知道javascript可以物件導向。 
瀏覽器大戰時代,Netscape的執行官招來了一個叫Brendan Eich的聰明人,發明了livescript(就是現在的javascript)語言,用來執行在瀏覽器端。它不像c++和java一樣基於類,而是基於原型繼承模型設計的。 OOP非常適合livescript這種動態語言。 
由於當時市場影響,這種新的語言需要看起來像java。java在當時非常耀眼流行,Netscape的執行官希望新語言是”java的小兄弟“。這就是為啥新語言叫javascript。

JavaScript and prototype-based OOP

下面是javascript的oop例子,先來搞出一個animal的物件:

var genericAnimal = Object.create(null);
  • 1

Object.create(null)建立空物件。下面往這個新物件上新增新屬性和方法:

genericAnimal.name = 'Animal';
genericAnimal.gender = 'femal';
genericAnmal.description = function () {
    return 'Gender: ' + this.gender + '; Name: ' + this.name;
};
  • 1
  • 2
  • 3
  • 4
  • 5

genericAnimal就是一個物件,可以這樣使用:

console.log(genericAnimal.description());
  • 1

我們可以使用genericAnimal作為原型,建立其他物件,就像拷貝物件(cloning the object):

var cat = Object.create(genericAnimal);
  • 1

我們建立了cat物件,cat物件是genericAnimal的clone版。將cat物件作為原型,建立其他物件:

var colonel = Object.create(cat);
colonel.name = 'Colonel Meow';

var puff = Object.create(cat);
puff.name = 'Puffy';
  • 1
  • 2
  • 3
  • 4
  • 5

puff物件可以使用“父物件”繼承來的屬性和方法:

console.log(puff.description());
//Gender: female; Name: Puffy
  • 1
  • 2

The new keyword and the constructor function

javascript有new關鍵字和建構函式的感念。

function Person(name) {
    this.name = name;
    this.sayName = function() {
        return "Hi, I'm " + this.name;
    };
}
var adam = new Person('Adam');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

實現繼承有點複雜, Ninja物件繼承Person物件:

function Ninja(name, weapon) {
  Person.call(this, name);
  this.weapon = weapon;
}
Ninja.prototype = Object.create(Person.prototype);
Ninja.prototype.constructor = Ninja;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Understanding delegation and the implementation of prototypes

使用Object.create建立新物件時候,傳入的物件成了新物件的原型。每個物件都有預設的__proto__屬性來記錄原型。舉例說明:

var genericAnimal = Object.create(null); 
// genericAnimal.__proto__ points to null
  • 1
  • 2

使用genericAnimal作為原型建立一個新的空物件:

var rodent = Object.create(genericAnimal);
 rodent.size = 'S';
 var capybara = Object.create(rodent);
//capybara.__proto__ points to rodent
//capybara.__proto__.__proto__ points to genericAnimal
//capybara.__proto__.__proto__.__proto__ is null
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

capybara物件雖然沒有size屬性,但是它可以在原型鏈上查詢size屬性:當呼叫capybara.size時,首先在capybara物件的本身屬性上查詢,如果沒有找到,則會去capybara.__proto__所指向的原型上去查詢。如果在capybara.__proto__也沒有找到,則繼續在capybara.__proto__.__proto__上查詢。

Creating Object.create

如果有些瀏覽器不支援Object.create,那麼需要自己實現了:

 if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

http://blog.csdn.net/bdss58/article/details/51284944

相關文章