顯示廣告
隱藏 ✕
看板 Mesak
作者 mesak (Mesak)
標題
 [JS] JavaScript 面向對象編程學習筆記

時間 2012年11月29日 Thu. PM 04:54:03


http://www.veryued.org/2011/09/javascript-object/

一、javascript 封裝

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.prototyp;
問題: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-29 16:54:03
※ 看板: Mesak 文章推薦值: 0 目前人氣: 0 累積人氣: 81 
e)編輯 d)刪除 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇