摘要:實現(xiàn)類的步驟第一步是使用新建類,初始化的固定函數(shù)是,不能使用其它名稱子類也是使用新建,父類放在第一個參數(shù)中,如子類中與父類的同名方法,如果需要在父類的同名方法上拓展,在需要在第一個參數(shù)中使用,然后在方法體內(nèi)使用如果需要在類的外面增加方法,可
實現(xiàn)類的步驟
第一步是使用Class.create新建類,初始化的固定函數(shù)是initialize,不能使用其它名稱
子類也是使用Class.create新建,父類放在第一個參數(shù)中,如var Cat = Class.create(Animal,{});
子類中與父類的同名方法,如果需要在父類的同名方法上拓展,在需要在第一個參數(shù)中使用$super,然后在方法體內(nèi)使用$super(args);
如果需要在類的外面增加方法,可以使用addMethods方法
// 使用 Class.create 創(chuàng)建類 var Person = Class.create({ // 初始函數(shù)固定為 initialize, 如果不設(shè)置,會默認創(chuàng)建一個空函數(shù)給 initialize initialize:function(name) { this.name = name; this.friends = ["jack", "mark"]; }, getName: function(){ console.log("My name is " + this.name); }, setFriends:function(friend){ this.friends.push(friend); }, getFriends:function(){ console.log(this.friends) } }); // 使用 addMethods 給在類的初始構(gòu)建之外添加方法,子類可以繼承該方法 Person.addMethods({ getAge:function(age){ console.log("My age is " + age); } }) // 子類通過 Class.create 創(chuàng)建類,第一個參數(shù)為父類的名字 var Chinese = Class.create(Person,{ // 使用 $super 為第一個參數(shù),表示當(dāng)前函數(shù)在父類的同名函數(shù)上拓展 initialize:function($super, name, addr){ $super(name); this.addr = addr; }, getAddr:function(){ console.log("My address is " + this.addr); } }); var Japanese = Class.create(Person, { initialize:function($super, name){ $super(name); } }) // 實例化類 var men = new Chinese("allen", "BeiJing"); men.getName(); // My name is allen men.getAge(23); // My age is 23 men.getAddr(); // My address is BeiJing // 以下驗證 - 子類繼承父類的屬性,修改了之后,其他子類再次繼承父類,父類的屬性的值為何不會改變 var allen = new Person(); allen.getFriends(); // ["jack", "mark"] var women = new Japanese(); women.setFriends("lisa"); women.getFriends(); // ["jack", "mark", "lisa"] var men = new Chinese(); men.setFriends("peter"); men.getFriends(); //["jack", "mark", "peter"] var wallen = new Person(); wallen.getFriends(); //["jack", "mark"]
JS是如何實現(xiàn)類的方法,有幾個重要的問題需要搞清楚
JS是如何創(chuàng)建類的
子類是如何實現(xiàn)繼承父類屬性和方法的
子類繼承父類的屬性,修改了之后,其他子類再次繼承父類,父類的屬性的值為何不會改變
子類和父類的同名函數(shù),在同名函數(shù)中使用$super,是如何做到在子類中共存的
如何實現(xiàn),不在類中,而是使用addMethods往類中添加方法的
下面來通過prototype.js的class來具體分析
var Class = (function() { function subclass() {}; function create() { // ... } function addMethods(source) { // ... } // 暴露給外部的接口 return { create: create, Methods: { addMethods: addMethods } }; })();
內(nèi)部實現(xiàn)其實很簡單,Class是一個立即執(zhí)行函數(shù),里面只有三個函數(shù),而且subclass還是個空函數(shù)
/* Based on Alex Arnell"s inheritance implementation. */ /** * Refer to Prototype"s web site for a [tutorial on classes and * inheritance](http://prototypejs.org/learn/class-inheritance). **/ var Class = (function() { function subclass() {}; function create() { // $A 函數(shù)就是把參數(shù)轉(zhuǎn)化成數(shù)組 var parent = null, properties = $A(arguments); // 如果第一個參數(shù)是函數(shù),就把他當(dāng)作父類 if (Object.isFunction(properties[0])) parent = properties.shift(); function klass() { // klass 是新建的類,把傳入的參數(shù)都綁定到 klass 的 initialize 方法中 this.initialize.apply(this, arguments); } // 把通過 extend 方法,把 Class.Methods 的方法添加到 klass 中 Object.extend(klass, Class.Methods); // 這里有指定 klass 的父類是哪一個 klass.superclass = parent; klass.subclasses = []; if (parent) { // 這里通過把父類的原型方法,都繼承到當(dāng)前類中 // 通過中間變量 subclass 來傳遞 prototype 來防止由于子類的修改而導(dǎo)致父類的屬性或者方法也被修改 subclass.prototype = parent.prototype; // 每次子類都會創(chuàng)建一個新的中間變量來傳遞,所以無論子類怎么修改屬性,都不會影響到父類 klass.prototype = new subclass; // 把當(dāng)前類添加到父類的子類中 parent.subclasses.push(klass); } for (var i = 0, length = properties.length; i < length; i++) // 前面把 addMethods 方法添加到 klass 中,這里就可以使用 addMethods 把傳入?yún)?shù)中的方法,添加到 klass 中了 klass.addMethods(properties[i]); // 如果 klass 沒有初始化函數(shù),就設(shè)置一個空函數(shù) if (!klass.prototype.initialize) klass.prototype.initialize = Prototype.emptyFunction; // 把 klass 的構(gòu)造函數(shù)指向自身 klass.prototype.constructor = klass; return klass; } // source 是所有要添加進來方法的集合 function addMethods(source) { var ancestor = this.superclass && this.superclass.prototype, properties = Object.keys(source); for (var i = 0, length = properties.length; i < length; i++) { // value 就是單個的方法 var property = properties[i], value = source[property]; // 如果參數(shù)中的第一個參數(shù)是 $super,就需要把父類的同名方法,傳遞進來 if (ancestor && Object.isFunction(value) && value.argumentNames()[0] == "$super") { // 把最初的 value 使用 method 存起來 var method = value; // 繼承父類的同名方法,然后把當(dāng)前參數(shù)傳進去 value = (function(m) { return function() { return ancestor[m].apply(this, arguments); }; })(property).wrap(method); // wrap 是把父類的同名方法,添加當(dāng)前類的同名方法中 // We used to use `bind` to ensure that `toString` and `valueOf` // methods were called in the proper context, but now that we"re // relying on native bind and/or an existing polyfill, we can"t rely // on the nuanced behavior of whatever `bind` implementation is on // the page. // // MDC"s polyfill, for instance, doesn"t like binding functions that // haven"t got a `prototype` property defined. // 將 valueOf 的方法綁定到 method 中 value.valueOf = (function(method) { return function() { return method.valueOf.call(method); }; })(method); // 將 toString 的方法綁定到 method 中 value.toString = (function(method) { return function() { return method.toString.call(method); }; })(method); } this.prototype[property] = value; } return this; } // 暴露給外部的接口 return { create: create, Methods: { addMethods: addMethods } }; })();
上面使用到的wrap函數(shù),摘抄在下面
function wrap(wrapper) { var __method = this; return function() { var a = update([__method.bind(this)], arguments); return wrapper.apply(this, a); } } // 這里就是把 args 中的屬性,都添加到 array 中 function update(array, args) { var arrayLength = array.length, length = args.length; while (length--) array[arrayLength + length] = args[length]; return array; }
JS面向?qū)ο笙盗?/p>
《javascript高級程序設(shè)計》 繼承實現(xiàn)方式
Mootools.js 是如何實現(xiàn)類,以及類的相關(guān)屬性和作用
klass 是如何實現(xiàn)JS的類以及類的相關(guān)屬性和作用
總結(jié):prototype.js,Mootools.js和klass.js 實現(xiàn)類的方法的異同與優(yōu)劣
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/84535.html
摘要:前面介紹了和是如何實現(xiàn)類,及其類的屬性和作用的。今天介紹的就是單純的實現(xiàn)面向?qū)ο蟮膸?,只有多行,也照例分析吧? 前面介紹了prototype.js和Mootools.js是如何實現(xiàn)類,及其類的屬性和作用的。今天介紹的klass.js就是單純的實現(xiàn)面向?qū)ο蟮膸欤挥?0多行,也照例分析吧。 實現(xiàn)類的步驟 第一步是使用klass新建類,初始化的固定函數(shù)是initialize,不能使用其它...
摘要:實現(xiàn)類的步驟第一步是使用新建類,初始化的固定函數(shù)是,不能使用其它名稱子類也是使用新建,父類在子類中,使用來繼承,與子類的方法名,同一級別子類中與父類的同名方法,如果需要在父類的同名方法上拓展,需要在子類的同名方法內(nèi),使用如果需要在類的外面增 實現(xiàn)類的步驟 第一步是使用new Class新建類,初始化的固定函數(shù)是initialize,不能使用其它名稱 子類也是使用new Class新建...
摘要:構(gòu)建類的方法使用來構(gòu)建類使用來構(gòu)建類使用來構(gòu)建類繼承父類的方法使用子類方法構(gòu)建子類,繼承父類,在與父類同名的方法中,第一個參數(shù)為,方法體內(nèi)使用來拓展父類的同名方法使用正常構(gòu)建類后,第一個方法使用來繼承父類,在子類的方法體中,使用來拓展父類的 構(gòu)建類的方法 Prototype.js使用Class.create來構(gòu)建類 Mootools.js使用new Class來構(gòu)建類 klass.j...
摘要:寄生式繼承的思路與寄生構(gòu)造函數(shù)和工廠模式類似,即創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部已某種方式來增強對象,最后再像真的是它做了所有工作一樣返回對象。 這篇本來應(yīng)該是作為寫JS 面向?qū)ο蟮那白?,只是作為《javascript高級程序設(shè)計》繼承一章的筆記 原型鏈 code 實現(xiàn) function SuperType() { this.colors = [red,blu...
摘要:裝飾者要實現(xiàn)這些相同的方法繼承自裝飾器對象創(chuàng)建具體的裝飾器,也是接收作對參數(shù)接下來我們要為每一個功能創(chuàng)建一個裝飾者對象,重寫父級方法,添加我們想要的功能。 裝飾模式 僅僅包裝現(xiàn)有的模塊,使之 更加華麗 ,并不會影響原有接口的功能 —— 好比你給手機添加一個外殼罷了,并不影響手機原有的通話、充電等功能; 使用 ES7 的 decorator ES7 中增加了一個 decorator 屬性...
閱讀 1632·2021-11-22 15:33
閱讀 1793·2021-11-15 18:01
閱讀 727·2021-10-09 09:43
閱讀 2667·2021-09-22 16:03
閱讀 877·2021-09-03 10:28
閱讀 3639·2021-08-11 10:22
閱讀 2781·2019-08-30 15:54
閱讀 1813·2019-08-30 14:21