reopen
不知道怎么翻譯好,如果按照reopen
翻譯過(guò)來(lái)應(yīng)該是“重新打開(kāi)”,但是總覺(jué)得不順,所以就譯成擴(kuò)展
了,如果有不妥請(qǐng)指正。
當(dāng)你想擴(kuò)展一個(gè)類(lèi)你可以直接使用reopen()
方法為一個(gè)已經(jīng)定義好的類(lèi)添加屬性、方法。如果是使用extend()
方法你需要重新定義一個(gè)子類(lèi),然后在子類(lèi)中添加新的屬性、方法。
前一篇所過(guò),調(diào)用create()
方法時(shí)候不能傳入計(jì)算屬性并且不推薦在此方法中新定義、重寫(xiě)方法,但是使用reopen()
方法可以彌補(bǔ)create()
方法的補(bǔ)足。與extend()
方法非常相似,下面的代碼演示了它們的不同之處。
Parent = Ember.Object.extend({
name: 'ubuntuvim',
fun1() {
console.log("The name is " + this.name);
},
common() {
console.log("common method...");
}
});
// 使用extend()方法添加新的屬性、方法
Child1 = Parent.extend({
// 給類(lèi)Parent為新增一個(gè)屬性
pwd: '12345',
// 給類(lèi)Parent為新增一個(gè)方法
fun2() {
console.log("The pwd is " + this.pwd);
},
// 重寫(xiě)父類(lèi)的common()方法
common() {
//console.log("override common method of parent...");
this._super();
}
});
var c1 = Child1.create();
console.log("name = " + c1.get('name') + ", pwd = " + c1.get('pwd'));
c1.fun1();
c1.fun2();
c1.common();
console.log("-----------------------");
// 使用reopen()方法添加新的屬性、方法
Parent.reopen({
// 給類(lèi)Parent為新增一個(gè)屬性
pwd: '12345',
// 給類(lèi)Parent為新增一個(gè)方法
fun2() {
console.log("The pwd is " + this.pwd);
},
// 重寫(xiě)類(lèi)本身common()方法
common() {
console.log("override common method by reopen method...");
//this._super();
},
// 新增一個(gè)計(jì)算屬性
fullName: Ember.computed(function() {
console.log("compute method...");
})
});
var p = Parent.create();
console.log("name = " + p.get('name') + ", pwd = " + p.get('pwd'));
p.fun1();
p.fun2();
p.common();
console.log("---------------------------");
p.get('fullName'); // 獲取計(jì)算屬性值,這里是直接輸出:compute method...
// 使用extend()方法添加新的屬性、方法
Child2 = Parent.extend({
// 給類(lèi)Parent為新增一個(gè)屬性
pwd: '12345',
// 給類(lèi)Parent為新增一個(gè)方法
fun2() {
console.log("The pwd is " + this.pwd);
},
// 重寫(xiě)父類(lèi)的common()方法
common() {
//console.log("override common method of parent...");
this._super();
}
});
var c2 = Child2.create();
console.log("name = " + c2.get('name') + ", pwd = " + c2.get('pwd'));
c2.fun1();
c2.fun2();
c2.common();
從執(zhí)行結(jié)果可以看到如下的差異:
同點(diǎn): 都可以用于擴(kuò)展某個(gè)類(lèi)。
異點(diǎn):
extend
需要重新定義一個(gè)類(lèi)并且要繼承被擴(kuò)展的類(lèi);reopen
是在被擴(kuò)展的類(lèi)本身上新增屬性、方法,可以擴(kuò)展計(jì)算屬性(相比create()
方法);
到底用那個(gè)方法有實(shí)際情況而定,reopen
方法會(huì)改變了原類(lèi)的行為(可以想象為修改了對(duì)象的原型對(duì)象的方法和屬性),就如演示實(shí)例一樣在reopen
方法之后調(diào)用的Child2
類(lèi)的common
方法的行為已經(jīng)改改變了,在編碼過(guò)程忘記之前已經(jīng)調(diào)用過(guò)reopen
方法就有可能出現(xiàn)自己都不知道怎么回事的問(wèn)題!
如果是extend
方法會(huì)導(dǎo)致類(lèi)越來(lái)越多,繼承樹(shù)也會(huì)越來(lái)越深,對(duì)性能、調(diào)試也是一大挑戰(zhàn),但是extend
不會(huì)改變被繼承類(lèi)的行為。
使用reopenClass()
方法可以擴(kuò)展static
類(lèi)型的屬性、方法。
Parent = Ember.Object.extend();
// 使用reopenClass()方法添加新的static屬性、方法
Parent.reopenClass({
isPerson: true,
username: 'blog.ddlisting.com'
//,name: 'test' //這里有點(diǎn)奇怪,不知道為何不能使用名稱(chēng)為name定義屬性,會(huì)提示這個(gè)是自讀屬性,使用username卻沒(méi)問(wèn)題?。」烙?jì)name是這個(gè)方法的保留關(guān)鍵字
});
Parent.reopen({
isPerson: false,
name: 'ubuntuvim'
});
console.log(Parent.isPerson);
console.log(Parent.name); // 輸出空
console.log(Parent.create().get('isPerson'));
console.log(Parent.create().get('name')); // 輸出 ubuntuvim
對(duì)于在reopenClass
方法中使用屬性name
的問(wèn)題下面的地址有解釋
博文完整代碼放在Github(博文經(jīng)過(guò)多次修改,博文上的代碼與github代碼可能又出入,不過(guò)影響不大?。?,如果你覺(jué)得博文對(duì)你有點(diǎn)用在github項(xiàng)目上給我個(gè)star
吧。您的肯定對(duì)我來(lái)說(shuō)是最大的動(dòng)力?。?/p>
更多建議: