顯示廣告
隱藏 ✕
Disp BBS guest 註冊 登入(i) 線上人數: 92
看板 Mesak
作者 mesak
標題 [JS] JavaScript 面向對象編程學習筆記
時間 2012年11月20日 Tue. AM 11:52:36



原始文章:http://www.veryued.org/2011/09/javascript-object/
1.原始模式

var Person = {
name: "",
sex: ""
}
 
var p1 = {}
p1.name = "xiaofei";
p1.sex = "boy";
 
var p2 = {}
p2.name = "xiaoxiao";
p2.sex = "girl";

問題:當要創建的實例多了就很麻煩,代碼不能重用
2.原始模式的升級版

function Person(name,sex){
return {
name:name,
sex:sex
}
}
 
var p1 = Person("xiaofei","boy");
var p2 = Person("xiaoxiao","girl");

問題:無法體現p1 p2是同一個原型的關係
3.構造函數模式

function Person(name,sex){
this.name = name;
this.sex = sex;
}
var p1 = new Person("xiaofei","boy");
var p2 = new Person("xiaoxiao","girl");
//每個實例都有一個屬性指向它的構造函數
alert(p1.constructor == Person);
alert(p2.constructor == Person);
//每個構造函數的原型都有一個屬性指向構造函數
alert(Person.prototype.constructor == Person);
 
alert(p1 instanceof Person);

問題:構造函數比較浪費內存,如果構造函數裡面有個通用方法的話,每次實例化的時候都要單獨複製一份
4.prototype模式

function Person(name,sex){
this.name = name;
this.sex = sex;
}
Person.prototype.method = function(){}

此時method方法被所有Person實例共享
二、構造函數繼承

function Animal(){
this.xx = "";
}
function Dog(name,color){
this.name = name;
this.color = color;
}
1.構造函數綁定

function Dog(name,color){
Animal.apply(this,arguments);
this.name = name;
this.color = color;
}
2.prototype 模式

var Dog.prototype = new Animal();
Dog.prototype.construtor = Dog;

因為每個構造函數的原型都有一個constructor屬性指向構造函數,重寫了原型,就要手動恢復construtor
3.直接繼承protoype

Dog.prototype = Animal.prototype;

問題:Animal.prototype.construtor = Dog;
原型指向相同,Dog任何的原型改變都會反映到Animal上
4.利用空對象作為中介

function extend(childObj,parentObj){
var F = function(){};
F.prototype = parentObj.prototype;
childObj.prototype = new F();
childObj.prototype.construtor = childObj;
 
childObj.uber = parentObj.prototype;//提供一個直接調用父級對象的方法的快捷方式
}
 
extend(Dog,Animal);
5.屬性拷貝繼承

function extend2(childObj, parentObj){
var c = childObj.prototype;
var p = parentObj.prototype;
 
for(i in p){
c[i] = p[i]
}
 
c.uber = p;
}

將不需要改變的屬性添加到Animal.prototype中
三、非構造函數繼承
1.object()方法

此方法是道格拉斯提出來的

function object(parentObj){
var F = function(){};
F.prototype = parentObj;
return new F();
}
 
var Dog = object(Animal);
 
//然後加獨有屬性
Dog.likepeople = true;

2.屬性的淺拷貝繼承

跟構造函數繼承中的屬性拷貝繼承基本一樣

function extendCopy(p){
var c = {};
 
for(i in p){
c[i] = p[i]
}
c.uber = p;
 
reuturn c;
}

問題:如果父對象的屬性類型是數組或者對象,c[i]拿到的是p[i]的地址,即c[i] p[i]指向同一塊內存地址,而不是
屬性的拷貝,所以如果有任何一方修改,都會影響到另一方

3.屬性的深拷貝繼承

function extendCopy(c,p){
var c = c || {};
 
for(i in p){
if(typeof p[i] == "object"){
c[i] = (p[i].constructor == "Array")? [] : {};
extendCopy(c[i],p[i]);
//因為argumengs.callee指向正在執行的函數 所以可以像下面這樣寫
//arguments.callee(c[i],p[i]);
}else{
c[i] = p[i];
}
}
c.uber = p;
 
return c;
}

四、對JavaScript繼承機制的理解
JavaScript並不是一門純面向對象的語言,所以它的繼承機制也只是一個閹割版本。
使用new創建一個實例,一旦實例創建,將自動引用prototype中的屬性和方法。
這樣構造函數就用於存儲本地屬性和方法,而prototype用於存儲公用屬性和方法,
理解這個機制,寫JavaScript的繼承就會清晰一些。

--
※ 作者: mesak 時間: 2012-11-20 11:52:36
※ 編輯: mesak 時間: 2012-11-20 11:57:11

※ 看板: Mesak 文章推薦值: 0 目前人氣: 0 累積人氣: 92 
※ 文章分類: JavaScript
分享網址: 複製 已複製
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇