JS面向?qū)ο缶幊淘斀?/h1>
更新時(shí)間:2016年03月06日 08:24:31 作者:木的樹(shù)
這篇文章主要為大家詳細(xì)介紹了JS面向?qū)ο缶幊?,幫助大家更詳?xì)的對(duì)JS面向?qū)ο筮M(jìn)行學(xué)習(xí),感興趣的朋友可以參考一下
序言
在JavaScript的大世界里討論面向?qū)ο螅家岬絻牲c(diǎn):1.JavaScript是一門(mén)基于原型的面向?qū)ο笳Z(yǔ)言 2.模擬類(lèi)語(yǔ)言的面向?qū)ο蠓绞?。?duì)于為什么要模擬類(lèi)語(yǔ)言的面向?qū)ο?,我個(gè)人認(rèn)為:某些情況下,原型模式能夠提供一定的便利,但在復(fù)雜的應(yīng)用中,基于原型的面向?qū)ο笙到y(tǒng)在抽象性與繼承性方面差強(qiáng)人意。由于JavaScript是唯一一個(gè)被各大瀏覽器支持的腳本語(yǔ)言,所以各路高手不得不使用各種方法來(lái)提高語(yǔ)言的便利性,優(yōu)化的結(jié)果就是其編寫(xiě)的代碼越來(lái)越像類(lèi)語(yǔ)言中的面向?qū)ο蠓绞剑瑥亩惭谏w了JavaScript原型系統(tǒng)的本質(zhì)?! ?/p>
基于原型的面向?qū)ο笳Z(yǔ)言
原型模式如類(lèi)模式一樣,都是是一種編程泛型,即編程的方法論。另外最近大紅大紫的函數(shù)編程也是一種編程泛型。JavaScript之父Brendan Eich在設(shè)計(jì)JavaScript時(shí),從一開(kāi)始就沒(méi)打算為其加入類(lèi)的概念,而是借鑒了另外兩門(mén)基于原型的的語(yǔ)言:Self和Smalltalk。
既然同為面向?qū)ο笳Z(yǔ)言,那就得有創(chuàng)建對(duì)象的方法。在類(lèi)語(yǔ)言中,對(duì)象基于模板來(lái)創(chuàng)建,首先定義一個(gè)類(lèi)作為對(duì)現(xiàn)實(shí)世界的抽象,然后由類(lèi)來(lái)實(shí)例化對(duì)象;而在原型語(yǔ)言中,對(duì)象以克隆另一個(gè)對(duì)象的方式創(chuàng)建,被克隆的母體稱(chēng)為原型對(duì)象。
克隆的關(guān)鍵在于語(yǔ)言本身是否為我們提供了原生的克隆方法。在ECMAScript5中,Object.create可以用來(lái)克隆對(duì)象。
var person = {
name: "tree",
age: 25,
say: function(){
console.log("I'm tree.")
}
};
var cloneTree = Object.create(person);
console.log(cloneTree);
原型模式的目的并不在于得到一個(gè)一模一樣的對(duì)象,而提供了一種便捷的方式去創(chuàng)建對(duì)象(出自《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》)。但是由于語(yǔ)言設(shè)計(jì)的問(wèn)題,JavaScript的原型存在著諸多矛盾,它的某些復(fù)雜的語(yǔ)法看起來(lái)就那些基于類(lèi)的語(yǔ)言,這些語(yǔ)法問(wèn)題掩蓋了它的原型機(jī)制(出自《JavaScript語(yǔ)言精粹》)。如:
function Person(name, age){
this.name = name;
this.age = age;
}
var p = new Person('tree', 25)
實(shí)際上,當(dāng)一個(gè)函數(shù)對(duì)象唄創(chuàng)建時(shí),F(xiàn)unction構(gòu)造器產(chǎn)生的函數(shù)對(duì)象會(huì)運(yùn)行類(lèi)似這樣的一些代碼:
this.prototype = {constructor: this}
新的函數(shù)對(duì)象被賦予一個(gè)prototype屬性,它的值是一個(gè)包含constructor屬性且屬性值為該新函數(shù)的對(duì)象。當(dāng)對(duì)一個(gè)函數(shù)使用new運(yùn)算符時(shí),函數(shù)的prototype的屬性的值被作為原型對(duì)象來(lái)克隆出新對(duì)象。如果new運(yùn)算符是一個(gè)方法,它的執(zhí)行過(guò)程如下:
Function.prorotype.new = function() {
//以prototype屬性值作為原型對(duì)象來(lái)克隆出一個(gè)新對(duì)象
var that = Object.create(this.prorotype);
//改變函數(shù)中this關(guān)鍵指向這個(gè)新克隆的對(duì)象
var other = this.apply(that, arguments);
//如果返回值不是一個(gè)對(duì)象,則返回這個(gè)新克隆對(duì)象
return (other && typeof other === 'object') ? other : that;
}
從上面可以看出,雖然使用new運(yùn)算符調(diào)用函數(shù)看起來(lái)像是使用模板實(shí)例化的方式來(lái)創(chuàng)建對(duì)象,但本質(zhì)還是以原型對(duì)象來(lái)克隆出新對(duì)象。
由于新克隆的對(duì)象能否訪問(wèn)到原型對(duì)象的一切方法和屬性,加上new運(yùn)算符的特性,這便成了利用原型模擬類(lèi)式語(yǔ)言的基石。
利用原型模擬類(lèi)式語(yǔ)言
抽象
用原型模式來(lái)模擬類(lèi),首先是抽象方式。根據(jù)JavaScript語(yǔ)言的特點(diǎn),通常一個(gè)類(lèi)(實(shí)際上是偽類(lèi))通常是將字段放置于構(gòu)造函數(shù)(實(shí)際上是new 運(yùn)算符調(diào)用的函數(shù),JavaScript本身并沒(méi)有構(gòu)造函數(shù)的概念)中,而將方法放置于函數(shù)的prototype屬性里。
function Person(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.say = function(){
console.log("Hello, I'm " + this.name);
};
繼承
繼承是OO語(yǔ)言中的一個(gè)最為人津津樂(lè)道的概念。許多OO語(yǔ)言都支持兩種繼承方式:接口繼承和實(shí)現(xiàn)繼承。接口繼承之繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。但是ECMAScript中無(wú)法實(shí)現(xiàn)接口繼承,只支持實(shí)現(xiàn)繼承,而且其實(shí)現(xiàn)繼承主要是依靠原型鏈來(lái)實(shí)現(xiàn)的。(出自《JavaScript高級(jí)程序設(shè)計(jì)》 6.3節(jié)——繼承)在高三中作者探索了各種關(guān)于繼承的模擬,如:組合繼承、原型繼承、寄生繼承、寄生組合繼承,最終寄生組合式成為所有模擬類(lèi)式繼承的基礎(chǔ)。
function Person(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.say = function(){
console.log("Hello, I'm " + this.name);
};
function Employee(name, age, major) {
Person.apply(this, arguments);
this.major = major;
};
Employee.prototype = Object.create(Person.prototype);
Employee.prorotype.constructor = Employee;
Employee.prorotype.sayMajor = function(){
console.log(this.major);
}
高三中只給出了單繼承的解決方案,關(guān)于多繼承的模擬我們還得自己想辦法。由于多繼承有其本身的困難:面向?qū)ο笳Z(yǔ)言如果支持了多繼承的話,都會(huì)遇到著名的菱形問(wèn)題(Diamond Problem)。假設(shè)存在一個(gè)如左圖所示的繼承關(guān)系,O中有一個(gè)方法foo,被A類(lèi)和B類(lèi)覆寫(xiě),但是沒(méi)有被C類(lèi)覆寫(xiě)。那么C在調(diào)用foo方法的時(shí)候,究竟是調(diào)用A中的foo,還是調(diào)用B中的foo?

所以大多數(shù)語(yǔ)言并不支持多繼承,如Java支持單繼承+接口的形式。JavaScript并不支持接口,要在一個(gè)不支持接口的語(yǔ)言上去模擬接口怎么辦?答案是著名的鴨式辨型。放到實(shí)際代碼中就是混入(mixin)。原理很簡(jiǎn)單:
function mixin(t, s) {
for (var p in s) {
t[p] = s[p];
}
}
值得一提的是dojo利用MRO(方法解析順序(Method Resolution Order),即查找被調(diào)用的方法所在類(lèi)時(shí)的搜索順序)方式解決了多繼承的問(wèn)題?! ?/p>
到此,我們已經(jīng)清楚了模擬類(lèi)語(yǔ)言的基本原理。作為一個(gè)愛(ài)折騰的程序員,我希望擁有自己的方式來(lái)簡(jiǎn)化類(lèi)的創(chuàng)建:
- 提供一種便利的方式去創(chuàng)建類(lèi),而不暴露函數(shù)的prototype屬性
- 在子類(lèi)中覆蓋父類(lèi)方法時(shí),能夠像Java一樣提供super函數(shù),來(lái)直接訪問(wèn)父類(lèi)同名方法
- 以更方便的方式添加靜態(tài)變量和方法而不去關(guān)心prototype
- 像C#那樣支持Attribute
最終,在借鑒各位大牛的知識(shí)總結(jié),我編寫(xiě)了自己的類(lèi)創(chuàng)建工具O.js:
(function(global) {
var define = global.define;
if (define && define.amd) {
define([], function(){
return O;
});
} else {
global.O = O;
}
function O(){};
O.derive = function(sub) {
debugger;
var parent = this;
sub = sub ? sub : {};
var o = create(parent);
var ctor = sub.constructor || function(){};//如何調(diào)用父類(lèi)的構(gòu)造函數(shù)?
var statics = sub.statics || {};
var ms = sub.mixins || [];
var attrs = sub.attributes || {};
delete sub.constructor;
delete sub.mixins;
delete sub.statics;
delete sub.attributes;
//處理繼承關(guān)系
ctor.prototype = o;
ctor.prototype.constructor = ctor;
ctor.superClass = parent;
//利用DefineProperties方法處理Attributes
//for (var p in attrs) {
Object.defineProperties(ctor.prototype, attrs);
//}
//靜態(tài)屬性
mixin(ctor, statics);
//混入其他屬性和方法,注意這里的屬性是所有實(shí)例對(duì)象都能夠訪問(wèn)并且修改的
mixin(ctor.prototype, sub);
//以mixin的方式模擬多繼承
for (var i = 0, len = ms.length; i < len; i++) {
mixin(ctor.prototype, ms[i] || {});
}
ctor.derive = parent.derive;
//_super函數(shù)
ctor.prototype._super = function(f) {
debugger;
return parent.prototype[f].apply(this, Array.prototype.slice.call(arguments, 1));
}
return ctor;
}
function create(clazz) {
var F = function(){};
F.prototype = clazz.prototype;
//F.prototype.constructor = F; //不需要
return new F();
};
function mixin(t, s) {
for (var p in s) {
t[p] = s[p];
}
}
})(window);
類(lèi)創(chuàng)建方式如下:
var Person = O.derive({
constructor: function(name) {//構(gòu)造函數(shù)
this.setInfo(name);
},
statics: {//靜態(tài)變量
declaredClass: "Person"
},
attributes: {//模擬C#中的屬性
Name: {
set: function(n) {
this.name = n;
console.log(this.name);
},
get: function() {
return this.name + "Attribute";
}
}
},
share: "asdsaf",//變量位于原型對(duì)象上,對(duì)所有對(duì)象共享
setInfo: function(name) {//方法
this.name = name;
}
});
var p = new Person('lzz');
console.log(p.Name);//lzzAttribute
console.log(Person);
繼承:
var Employee = Person.derive({//子類(lèi)有父類(lèi)派生
constructor: function(name, age) {
this.setInfo(name, age);
},
statics: {
declaredClass: "Employee"
},
setInfo: function(name, age) {
this._super('setInfo', name);//調(diào)用父類(lèi)同名方法
this.age = age;
}
});
var e = new Employee('lll', 25);
console.log(e.Name);//lllAttribute
console.log(Employee);
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
您可能感興趣的文章:- javascript面向?qū)ο髣?chuàng)建對(duì)象的方式小結(jié)
- javascript面向?qū)ο笕筇卣髦鄳B(tài)實(shí)例詳解
- javascript面向?qū)ο笕筇卣髦^承實(shí)例詳解
- javascript面向?qū)ο笕筇卣髦庋b實(shí)例詳解
- JavaScript面向?qū)ο笾薪涌趯?shí)現(xiàn)方法詳解
- 淺談JavaScript面向?qū)ο?-繼承
- JavaScript碎片—函數(shù)閉包(模擬面向?qū)ο螅?/a>
- JS實(shí)現(xiàn)面向?qū)ο罄^承的5種方式分析
- JS面向?qū)ο蠡A(chǔ)講解(工廠模式、構(gòu)造函數(shù)模式、原型模式、混合模式、動(dòng)態(tài)原型模式)
- JS 面向?qū)ο笾衿娴膒rototype
- javascript面向?qū)ο蟪绦蛟O(shè)計(jì)實(shí)踐常用知識(shí)點(diǎn)總結(jié)
相關(guān)文章
-
JS中的提升機(jī)制變量提升函數(shù)提升實(shí)例詳解
這篇文章主要為大家介紹了JS中的提升機(jī)制變量提升函數(shù)提升實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪 2022-09-09
-
Jquery和JS用外部變量獲取Ajax返回的參數(shù)值的方法實(shí)例(超簡(jiǎn)單)
Jquery和JS用外部變量獲取Ajax返回的參數(shù)值的方法實(shí)例(超簡(jiǎn)單),需要的朋友可以參考一下 2013-06-06
-
一文詳解JSON.parse和JSON.stringify的用法
Json.stringify()和toString()兩者雖然都可以講目標(biāo)值轉(zhuǎn)為字符串,但是還是有本質(zhì)區(qū)別的,下面這篇文章主要給大家介紹了關(guān)于JSON.parse和JSON.stringify用法的相關(guān)資料,需要的朋友可以參考下 2023-01-01
-
JS關(guān)于for循環(huán)中使用setTimeout的四種解決方案
這篇文章主要介紹了JS關(guān)于for循環(huán)中使用setTimeout的四種解決方案,想深入了解JS的同學(xué),一定要看下 2021-05-05
-
解決Babylon.js中AudioContext was not allowed&nbs
這篇文章主要介紹了解決Babylon.js中AudioContext was not allowed to start異常問(wèn)題方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪 2023-04-04
-
JavaScript實(shí)現(xiàn)拖動(dòng)對(duì)話框效果的實(shí)現(xiàn)代碼
這篇文章主要介紹了JavaScript實(shí)現(xiàn)拖動(dòng)對(duì)話框效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下 2020-10-10
最新評(píng)論
序言
在JavaScript的大世界里討論面向?qū)ο螅家岬絻牲c(diǎn):1.JavaScript是一門(mén)基于原型的面向?qū)ο笳Z(yǔ)言 2.模擬類(lèi)語(yǔ)言的面向?qū)ο蠓绞?。?duì)于為什么要模擬類(lèi)語(yǔ)言的面向?qū)ο?,我個(gè)人認(rèn)為:某些情況下,原型模式能夠提供一定的便利,但在復(fù)雜的應(yīng)用中,基于原型的面向?qū)ο笙到y(tǒng)在抽象性與繼承性方面差強(qiáng)人意。由于JavaScript是唯一一個(gè)被各大瀏覽器支持的腳本語(yǔ)言,所以各路高手不得不使用各種方法來(lái)提高語(yǔ)言的便利性,優(yōu)化的結(jié)果就是其編寫(xiě)的代碼越來(lái)越像類(lèi)語(yǔ)言中的面向?qū)ο蠓绞剑瑥亩惭谏w了JavaScript原型系統(tǒng)的本質(zhì)?! ?/p>
基于原型的面向?qū)ο笳Z(yǔ)言
原型模式如類(lèi)模式一樣,都是是一種編程泛型,即編程的方法論。另外最近大紅大紫的函數(shù)編程也是一種編程泛型。JavaScript之父Brendan Eich在設(shè)計(jì)JavaScript時(shí),從一開(kāi)始就沒(méi)打算為其加入類(lèi)的概念,而是借鑒了另外兩門(mén)基于原型的的語(yǔ)言:Self和Smalltalk。
既然同為面向?qū)ο笳Z(yǔ)言,那就得有創(chuàng)建對(duì)象的方法。在類(lèi)語(yǔ)言中,對(duì)象基于模板來(lái)創(chuàng)建,首先定義一個(gè)類(lèi)作為對(duì)現(xiàn)實(shí)世界的抽象,然后由類(lèi)來(lái)實(shí)例化對(duì)象;而在原型語(yǔ)言中,對(duì)象以克隆另一個(gè)對(duì)象的方式創(chuàng)建,被克隆的母體稱(chēng)為原型對(duì)象。
克隆的關(guān)鍵在于語(yǔ)言本身是否為我們提供了原生的克隆方法。在ECMAScript5中,Object.create可以用來(lái)克隆對(duì)象。
var person = { name: "tree", age: 25, say: function(){ console.log("I'm tree.") } }; var cloneTree = Object.create(person); console.log(cloneTree);
原型模式的目的并不在于得到一個(gè)一模一樣的對(duì)象,而提供了一種便捷的方式去創(chuàng)建對(duì)象(出自《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》)。但是由于語(yǔ)言設(shè)計(jì)的問(wèn)題,JavaScript的原型存在著諸多矛盾,它的某些復(fù)雜的語(yǔ)法看起來(lái)就那些基于類(lèi)的語(yǔ)言,這些語(yǔ)法問(wèn)題掩蓋了它的原型機(jī)制(出自《JavaScript語(yǔ)言精粹》)。如:
function Person(name, age){ this.name = name; this.age = age; } var p = new Person('tree', 25)
實(shí)際上,當(dāng)一個(gè)函數(shù)對(duì)象唄創(chuàng)建時(shí),F(xiàn)unction構(gòu)造器產(chǎn)生的函數(shù)對(duì)象會(huì)運(yùn)行類(lèi)似這樣的一些代碼:
this.prototype = {constructor: this}
新的函數(shù)對(duì)象被賦予一個(gè)prototype屬性,它的值是一個(gè)包含constructor屬性且屬性值為該新函數(shù)的對(duì)象。當(dāng)對(duì)一個(gè)函數(shù)使用new運(yùn)算符時(shí),函數(shù)的prototype的屬性的值被作為原型對(duì)象來(lái)克隆出新對(duì)象。如果new運(yùn)算符是一個(gè)方法,它的執(zhí)行過(guò)程如下:
Function.prorotype.new = function() { //以prototype屬性值作為原型對(duì)象來(lái)克隆出一個(gè)新對(duì)象 var that = Object.create(this.prorotype); //改變函數(shù)中this關(guān)鍵指向這個(gè)新克隆的對(duì)象 var other = this.apply(that, arguments); //如果返回值不是一個(gè)對(duì)象,則返回這個(gè)新克隆對(duì)象 return (other && typeof other === 'object') ? other : that; }
從上面可以看出,雖然使用new運(yùn)算符調(diào)用函數(shù)看起來(lái)像是使用模板實(shí)例化的方式來(lái)創(chuàng)建對(duì)象,但本質(zhì)還是以原型對(duì)象來(lái)克隆出新對(duì)象。
由于新克隆的對(duì)象能否訪問(wèn)到原型對(duì)象的一切方法和屬性,加上new運(yùn)算符的特性,這便成了利用原型模擬類(lèi)式語(yǔ)言的基石。
利用原型模擬類(lèi)式語(yǔ)言
抽象
用原型模式來(lái)模擬類(lèi),首先是抽象方式。根據(jù)JavaScript語(yǔ)言的特點(diǎn),通常一個(gè)類(lèi)(實(shí)際上是偽類(lèi))通常是將字段放置于構(gòu)造函數(shù)(實(shí)際上是new 運(yùn)算符調(diào)用的函數(shù),JavaScript本身并沒(méi)有構(gòu)造函數(shù)的概念)中,而將方法放置于函數(shù)的prototype屬性里。
function Person(name, age) { this.name = name; this.age = age; }; Person.prototype.say = function(){ console.log("Hello, I'm " + this.name); };
繼承
繼承是OO語(yǔ)言中的一個(gè)最為人津津樂(lè)道的概念。許多OO語(yǔ)言都支持兩種繼承方式:接口繼承和實(shí)現(xiàn)繼承。接口繼承之繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。但是ECMAScript中無(wú)法實(shí)現(xiàn)接口繼承,只支持實(shí)現(xiàn)繼承,而且其實(shí)現(xiàn)繼承主要是依靠原型鏈來(lái)實(shí)現(xiàn)的。(出自《JavaScript高級(jí)程序設(shè)計(jì)》 6.3節(jié)——繼承)在高三中作者探索了各種關(guān)于繼承的模擬,如:組合繼承、原型繼承、寄生繼承、寄生組合繼承,最終寄生組合式成為所有模擬類(lèi)式繼承的基礎(chǔ)。
function Person(name, age) { this.name = name; this.age = age; }; Person.prototype.say = function(){ console.log("Hello, I'm " + this.name); }; function Employee(name, age, major) { Person.apply(this, arguments); this.major = major; }; Employee.prototype = Object.create(Person.prototype); Employee.prorotype.constructor = Employee; Employee.prorotype.sayMajor = function(){ console.log(this.major); }
高三中只給出了單繼承的解決方案,關(guān)于多繼承的模擬我們還得自己想辦法。由于多繼承有其本身的困難:面向?qū)ο笳Z(yǔ)言如果支持了多繼承的話,都會(huì)遇到著名的菱形問(wèn)題(Diamond Problem)。假設(shè)存在一個(gè)如左圖所示的繼承關(guān)系,O中有一個(gè)方法foo,被A類(lèi)和B類(lèi)覆寫(xiě),但是沒(méi)有被C類(lèi)覆寫(xiě)。那么C在調(diào)用foo方法的時(shí)候,究竟是調(diào)用A中的foo,還是調(diào)用B中的foo?
所以大多數(shù)語(yǔ)言并不支持多繼承,如Java支持單繼承+接口的形式。JavaScript并不支持接口,要在一個(gè)不支持接口的語(yǔ)言上去模擬接口怎么辦?答案是著名的鴨式辨型。放到實(shí)際代碼中就是混入(mixin)。原理很簡(jiǎn)單:
function mixin(t, s) { for (var p in s) { t[p] = s[p]; } }
值得一提的是dojo利用MRO(方法解析順序(Method Resolution Order),即查找被調(diào)用的方法所在類(lèi)時(shí)的搜索順序)方式解決了多繼承的問(wèn)題?! ?/p>
到此,我們已經(jīng)清楚了模擬類(lèi)語(yǔ)言的基本原理。作為一個(gè)愛(ài)折騰的程序員,我希望擁有自己的方式來(lái)簡(jiǎn)化類(lèi)的創(chuàng)建:
- 提供一種便利的方式去創(chuàng)建類(lèi),而不暴露函數(shù)的prototype屬性
- 在子類(lèi)中覆蓋父類(lèi)方法時(shí),能夠像Java一樣提供super函數(shù),來(lái)直接訪問(wèn)父類(lèi)同名方法
- 以更方便的方式添加靜態(tài)變量和方法而不去關(guān)心prototype
- 像C#那樣支持Attribute
最終,在借鑒各位大牛的知識(shí)總結(jié),我編寫(xiě)了自己的類(lèi)創(chuàng)建工具O.js:
(function(global) { var define = global.define; if (define && define.amd) { define([], function(){ return O; }); } else { global.O = O; } function O(){}; O.derive = function(sub) { debugger; var parent = this; sub = sub ? sub : {}; var o = create(parent); var ctor = sub.constructor || function(){};//如何調(diào)用父類(lèi)的構(gòu)造函數(shù)? var statics = sub.statics || {}; var ms = sub.mixins || []; var attrs = sub.attributes || {}; delete sub.constructor; delete sub.mixins; delete sub.statics; delete sub.attributes; //處理繼承關(guān)系 ctor.prototype = o; ctor.prototype.constructor = ctor; ctor.superClass = parent; //利用DefineProperties方法處理Attributes //for (var p in attrs) { Object.defineProperties(ctor.prototype, attrs); //} //靜態(tài)屬性 mixin(ctor, statics); //混入其他屬性和方法,注意這里的屬性是所有實(shí)例對(duì)象都能夠訪問(wèn)并且修改的 mixin(ctor.prototype, sub); //以mixin的方式模擬多繼承 for (var i = 0, len = ms.length; i < len; i++) { mixin(ctor.prototype, ms[i] || {}); } ctor.derive = parent.derive; //_super函數(shù) ctor.prototype._super = function(f) { debugger; return parent.prototype[f].apply(this, Array.prototype.slice.call(arguments, 1)); } return ctor; } function create(clazz) { var F = function(){}; F.prototype = clazz.prototype; //F.prototype.constructor = F; //不需要 return new F(); }; function mixin(t, s) { for (var p in s) { t[p] = s[p]; } } })(window);
類(lèi)創(chuàng)建方式如下:
var Person = O.derive({ constructor: function(name) {//構(gòu)造函數(shù) this.setInfo(name); }, statics: {//靜態(tài)變量 declaredClass: "Person" }, attributes: {//模擬C#中的屬性 Name: { set: function(n) { this.name = n; console.log(this.name); }, get: function() { return this.name + "Attribute"; } } }, share: "asdsaf",//變量位于原型對(duì)象上,對(duì)所有對(duì)象共享 setInfo: function(name) {//方法 this.name = name; } }); var p = new Person('lzz'); console.log(p.Name);//lzzAttribute console.log(Person);
繼承:
var Employee = Person.derive({//子類(lèi)有父類(lèi)派生 constructor: function(name, age) { this.setInfo(name, age); }, statics: { declaredClass: "Employee" }, setInfo: function(name, age) { this._super('setInfo', name);//調(diào)用父類(lèi)同名方法 this.age = age; } }); var e = new Employee('lll', 25); console.log(e.Name);//lllAttribute console.log(Employee);
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
- javascript面向?qū)ο髣?chuàng)建對(duì)象的方式小結(jié)
- javascript面向?qū)ο笕筇卣髦鄳B(tài)實(shí)例詳解
- javascript面向?qū)ο笕筇卣髦^承實(shí)例詳解
- javascript面向?qū)ο笕筇卣髦庋b實(shí)例詳解
- JavaScript面向?qū)ο笾薪涌趯?shí)現(xiàn)方法詳解
- 淺談JavaScript面向?qū)ο?-繼承
- JavaScript碎片—函數(shù)閉包(模擬面向?qū)ο螅?/a>
- JS實(shí)現(xiàn)面向?qū)ο罄^承的5種方式分析
- JS面向?qū)ο蠡A(chǔ)講解(工廠模式、構(gòu)造函數(shù)模式、原型模式、混合模式、動(dòng)態(tài)原型模式)
- JS 面向?qū)ο笾衿娴膒rototype
- javascript面向?qū)ο蟪绦蛟O(shè)計(jì)實(shí)踐常用知識(shí)點(diǎn)總結(jié)
相關(guān)文章
JS中的提升機(jī)制變量提升函數(shù)提升實(shí)例詳解
這篇文章主要為大家介紹了JS中的提升機(jī)制變量提升函數(shù)提升實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Jquery和JS用外部變量獲取Ajax返回的參數(shù)值的方法實(shí)例(超簡(jiǎn)單)
Jquery和JS用外部變量獲取Ajax返回的參數(shù)值的方法實(shí)例(超簡(jiǎn)單),需要的朋友可以參考一下2013-06-06一文詳解JSON.parse和JSON.stringify的用法
Json.stringify()和toString()兩者雖然都可以講目標(biāo)值轉(zhuǎn)為字符串,但是還是有本質(zhì)區(qū)別的,下面這篇文章主要給大家介紹了關(guān)于JSON.parse和JSON.stringify用法的相關(guān)資料,需要的朋友可以參考下2023-01-01JS關(guān)于for循環(huán)中使用setTimeout的四種解決方案
這篇文章主要介紹了JS關(guān)于for循環(huán)中使用setTimeout的四種解決方案,想深入了解JS的同學(xué),一定要看下2021-05-05解決Babylon.js中AudioContext was not allowed&nbs
這篇文章主要介紹了解決Babylon.js中AudioContext was not allowed to start異常問(wèn)題方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04JavaScript實(shí)現(xiàn)拖動(dòng)對(duì)話框效果的實(shí)現(xiàn)代碼
這篇文章主要介紹了JavaScript實(shí)現(xiàn)拖動(dòng)對(duì)話框效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10