亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JavaScript設(shè)計(jì)模式

keke / 2581人閱讀

摘要:可能因?yàn)橄热霝橹?,在編程之中,往往不由自主地以的邏輯編程思路設(shè)計(jì)模式進(jìn)行開(kāi)發(fā)。這是原型模式很重要的一條原則。關(guān)于閉包與內(nèi)存泄露的問(wèn)題,請(qǐng)移步原型模式閉包與高階函數(shù)應(yīng)該可以說(shuō)是設(shè)計(jì)模式的基礎(chǔ)要領(lǐng)吧。在下一章,再分享一下的幾種常用設(shè)計(jì)模式。

在學(xué)習(xí)使用Javascript之前,我的程序猿生涯里面僅有接觸的編程語(yǔ)言是C#跟Java——忽略當(dāng)年在大學(xué)補(bǔ)考了N次的C與VB。

從靜態(tài)編程語(yǔ)言,轉(zhuǎn)到動(dòng)態(tài)語(yǔ)言JS,剛開(kāi)始的時(shí)候,遇到不少困難與錯(cuò)誤??赡芤?yàn)橄热霝橹?,在JS編程之中,往往不由自主地以C#的邏輯、編程思路、設(shè)計(jì)模式進(jìn)行JS開(kāi)發(fā)。

時(shí)間長(zhǎng)了,漸漸發(fā)現(xiàn)JS設(shè)計(jì)模式對(duì)于前端開(kāi)發(fā)的重要性,但在分享JS設(shè)計(jì)模式之前,希望首先分享幾點(diǎn)個(gè)人覺(jué)得很重要的JS設(shè)計(jì)模式基礎(chǔ)。有些地方,可能研究得也不是很深入,有什么錯(cuò)誤的話,望指正。

動(dòng)態(tài)類型語(yǔ)言

靜態(tài)類型語(yǔ)言,在編譯階段,就需要確定變量的類型。但動(dòng)態(tài)類型語(yǔ)言,只有程序運(yùn)行時(shí),根據(jù)當(dāng)時(shí)語(yǔ)言執(zhí)行環(huán)境,變量才會(huì)賦予其類型。

所以C#,不能拋開(kāi)runtime與編譯器多帶帶運(yùn)行,Java也離不開(kāi)JVM。同時(shí)也有一大堆問(wèn)題需要考慮的,跨平臺(tái)、類型轉(zhuǎn)換、反射、Ioc、接口編程、抽象化、動(dòng)態(tài)代理等等一大堆概念技術(shù)的產(chǎn)生,還不是因?yàn)殪o態(tài)語(yǔ)言的強(qiáng)類型特性,需要更多的手段讓其得到靈活多態(tài)的特性。

    public class Main
    {
        public void Function()
        {
            //在編譯的時(shí)候,.net runtime必須要知道dog是一只狗
            Dog dog = new Dog();
            Console.WriteLine(dog.Name);
        }
    }

但,JS只需要個(gè)文本編輯器,沒(méi)有編譯通過(guò)不通過(guò)的概念,加載了瀏覽器就能跑。

    var a = 1;
    console.log(typeof a);//number

    a = "a";
    console.log(typeof a);//string
原型模式

ECMAScript 5之前JS是沒(méi)有類的,W3C的大牛是有所發(fā)現(xiàn)的,所以ES6會(huì)新的類語(yǔ)法,但是各大瀏覽器(IE)猴年馬月才跟進(jìn)就不得而知了——絕對(duì)不是針對(duì)IE。

在靜態(tài)類型語(yǔ)言開(kāi)發(fā)中,類是任意實(shí)體的結(jié)構(gòu),當(dāng)需要這個(gè)實(shí)體的時(shí)候,系統(tǒng)依照這個(gè)結(jié)構(gòu),“畫(huà)”出這個(gè)==對(duì)象==。
譬如,要設(shè)計(jì)車,首先是要設(shè)計(jì)稿,設(shè)計(jì)稿就是類,然后照著設(shè)計(jì)稿生產(chǎn)的每一臺(tái)車就是具體的對(duì)象。
所以,靜態(tài)類型語(yǔ)言當(dāng)中,得到一個(gè)對(duì)象的最關(guān)鍵就是先有這個(gè)對(duì)象的設(shè)計(jì)稿(類),就是知道它的類型。

但是,JS不一樣。
JS是以原型模式作為設(shè)計(jì)基礎(chǔ)。得到一個(gè)對(duì)象之前,我們不關(guān)心對(duì)象屬于什么類型,它的設(shè)計(jì)稿是怎么樣的,JS是通過(guò)拷貝一個(gè)其他對(duì)象而獲得對(duì)象的。

    //定義超人是超人,超人可以飛
    var superman = {
        name: "superman",
        fly: function () {
            console.log(this.name + " is flying");
        }
    };
    superman.fly();//superman is flying

    //萬(wàn)一,想要個(gè)妹子呢,搞個(gè)女超人如何?女超人也會(huì)飛?要不就復(fù)制一個(gè)超人的對(duì)象吧。
    //通過(guò)Object.create復(fù)制一個(gè)超人,但定義它是女超人。
    var superwomen = Object.create(superman);

    superwomen.name = "superwomen";
    superwomen.fly();//superwomen is flying

    //DC的不喜歡,來(lái)個(gè)漫威吧,再搞個(gè)鋼鐵俠?鋼鐵俠也會(huì)飛
    var ironman = Object.create(superman);

    ironman.name = "ironman";
    ironman.fly();//ironman is flying

千萬(wàn)別誤解了superman就是類,而superwomen、ironman就是superman實(shí)例化得到的對(duì)象,superman、superwomen、ironman都是對(duì)象,superwomen、ironman都是superman對(duì)象拷貝的結(jié)果。

1、所有的數(shù)據(jù)都是對(duì)象

上面的例子,通過(guò)var obj={}創(chuàng)建對(duì)象,其等價(jià)于var obj=new Object()。Object對(duì)象可以創(chuàng)建對(duì)象,但不僅是Object才是對(duì)象,所有的數(shù)據(jù)都是對(duì)象,包括Number、Boolean、String、Function、Object。這是原型模式很重要的一條原則。
正是這一點(diǎn),我們也可以利用function定義對(duì)象:function obj(){};

不過(guò)與var obj=new Object()不同,function定義的對(duì)象,是一個(gè)帶構(gòu)造器的函數(shù),通過(guò)new關(guān)鍵字調(diào)用構(gòu)造器可以獲取其原型對(duì)象。參考以下例子。

    //定義一個(gè)對(duì)象
    var superman = {
        name: "superman",
        fly: function () {
            console.log(this.name + " is flying");
        }
    };
    superman.fly();//superman is flying

    //定義一個(gè)函數(shù),同時(shí)也是一個(gè)帶構(gòu)造器的函數(shù)
    function superman2() {
        this.name = "superman";
        this.fly = function () {
            console.log(this.name + " is flying");
        };
    };

    //錯(cuò)誤:superman2是函數(shù),fly()不是函數(shù)
    superman2.fly();//error:undefined is not a function

    //錯(cuò)誤:superman2()是調(diào)用函數(shù),但函數(shù)沒(méi)有返回帶fly()函數(shù)的對(duì)象
    superman2().fly();//error:Cannot read property "fly" of undefined

    //正確:new不是C#實(shí)例化關(guān)鍵字,new是調(diào)用superman2的構(gòu)造器并返回其對(duì)象
    var sm = new superman2();
    sm.fly();//superman is flying
2、對(duì)象的屬性請(qǐng)求,會(huì)從對(duì)象傳遞到對(duì)象原型

當(dāng)需要獲得對(duì)象屬性時(shí),會(huì)首先請(qǐng)求對(duì)象本身,如果,對(duì)象本身沒(méi)有屬性可以響應(yīng),則響應(yīng)其對(duì)象原型prototype;如果prototype也沒(méi)有屬性可以響應(yīng),則進(jìn)一步請(qǐng)求原型的原型,從而形成一條原型鏈。當(dāng)然,原型鏈的層級(jí)不能太長(zhǎng),具體長(zhǎng)度沒(méi)有研究過(guò),我覺(jué)得3級(jí)也差不多了。

    //定義人
    function human() {
        this.sexy = "male";
    };

    //定義所有英雄的原型
    function heroBase() {
        this.trait = "strong cool";
    };

    //英雄的原型是人
    heroBase.prototype = new human();

    //定義超人
    function superman() {
        this.fly = function () {
            console.log("superman");
        };
    };

    //超人的原型就是英雄
    superman.prototype = new heroBase();

    console.log(new superman().sexy);//male
    console.log(new superman().trait);//strong cool

這個(gè)步驟就是:

超人的性別是神馬?

光看超人不知道,要看超人原型:英雄

看英雄也不知道,要看英雄原型:人

人的sexy屬性告訴我們,他是男人

好吧,也許你發(fā)現(xiàn)了,上面例子是有bug的,超人是外星人;但你肯定發(fā)現(xiàn)了,這不就是繼承嗎?繼承都有了,多態(tài)還能遠(yuǎn)嗎?

3、JS就是通過(guò)原型模式實(shí)現(xiàn)繼承的,且是單一繼承

我個(gè)人的理解是,JS的繼承跟C#的繼承雖然實(shí)現(xiàn)形式不同,但有一點(diǎn)原則是相同的,單一繼承非多繼承。如上例子換成以下代碼:
superman.prototype = new heroBase();
superman.prototype = new human();
最終結(jié)果是,超人的原型首先定為英雄,但又被人所覆蓋了。符合單一繼承的原則。

4、特別補(bǔ)充:關(guān)于__proto__prototype的區(qū)別

之前一直以為搞懂了原型模式,最近看到一篇很好文章 [學(xué)習(xí)筆記](méi) 小角度看JS原型鏈 夢(mèng)禪,漲姿勢(shì)了。

在 segmentfault 上看到這樣一道題目:

var F = function(){};
Object.prototype.a = function(){};
Function.prototype.b = function(){};
var f = new F();

問(wèn):f 能取到a,b嗎?原理是什么?

關(guān)鍵理解:
prototype是對(duì)象原型
__proto__是對(duì)象構(gòu)造器的原型
關(guān)于兩者區(qū)別,推薦一遍博文,解釋非常詳細(xì),理解js中的原型鏈,prototype與__proto__的關(guān)系

自己列了例子,應(yīng)該比較容易理解

    var F = function () { };
    Object.prototype.a = function () {
        console.log("a");
    };
    Function.prototype.b = function () {
        console.log("b");
    };
    var f = new F();

    //注意:對(duì)象的__proto__屬性,指向?qū)ο蟮母讣?jí)構(gòu)造器的prototype原型

    console.log(f);

    console.log(f.__proto__);                         //F.prototype
    console.log(F.prototype.__proto__);               //Ojbect.prototype
    console.log(Object.prototype.a());                //a

    console.log(f.__proto__.__proto__.a());           //a

    /****************************************************************/

    console.log(f.constructor);                       //F
    console.log(F.__proto__);                         //Function.prototype
    console.log(Function.prototype.b());              //b

    console.log(f.constructor.__proto__.b());         //b

    //結(jié)論:所有對(duì)象的__proto__都指向其構(gòu)造器的prototype
    //結(jié)論:所有構(gòu)造器/函數(shù)的__proto__都指向Function.prototype,它是一個(gè)空函數(shù)(Empty function)
    //結(jié)論:Function.prototype的__proto__最終指向Object.prototype

所有對(duì)象的__proto__都指向其構(gòu)造器的prototype

所有構(gòu)造器/函數(shù)的__proto__都指向Function.prototype,它是一個(gè)空函數(shù)(Empty function)

Function.prototype的__proto__最終指向Object.prototype

多態(tài)

JS的多態(tài)是通過(guò)兩點(diǎn)實(shí)現(xiàn)的:1、原型模式實(shí)現(xiàn)繼承;2、動(dòng)態(tài)類型實(shí)現(xiàn)泛型

回想一下,我們剛學(xué)習(xí)C#的那個(gè)經(jīng)典例子

    public class Hero
    {
        public virtual void Fly()
        {
            Console.WriteLine("hero fly");
        }
    }

    public class SuperMan : Hero
    {
        public override void Fly()
        {
            base.Fly();
            Console.WriteLine("SuperMan fly");
        }
    }

    public class IronMan : Hero
    {
        public override void Fly()
        {
            base.Fly();
            Console.WriteLine("IronMan fly");
        }
    }

    public class Main
    {
        public void MainFunction()
        {
            LetsFly(new SuperMan());
            LetsFly(new IronMan());
        }

        public void LetsFly(Hero hero)
        {
            hero.Fly();
        }
    }

再來(lái)看看JS的實(shí)現(xiàn)

    function superman() {
        this.fly = function () {
            console.log("superman fly");
        };
    }

    function bird() {
        this.fly = function () {
            console.log("bird fly");
        };
    };

    function letsFly(hero) {
        hero.fly();
    }

    var sm = new superman();
    var b = new bird();
    letsFly(sm);//superman fly
    letsFly(b);//bird fly;

LetsFly()方法,C#跟JS接受的同樣都是Hero這個(gè)對(duì)象

對(duì)于C#而言,LetsFly方法要求不管是神馬Hero,只要實(shí)現(xiàn)了基類Hero的Fly,它就能執(zhí)行LetsFly方法,以后即使有再多的英雄,繼承Hero即可。

而JS,LetsFly方法要求不管是神馬對(duì)象,只要有Fly方法,它就能執(zhí)行LetsFly方法,以后即使有再多的英雄,英雄會(huì)Fly即可。

對(duì)比之下,優(yōu)缺點(diǎn)是顯而易見(jiàn)的,前者受到束縛,尤其在復(fù)雜類型之間繼承與引用提現(xiàn)的更加凸顯,但類型安全性高;

后者無(wú)拘無(wú)束,但類型安全性低,如上例子,LetsFly傳入的可能不是Hero,很可能是Bird。

閉包與高階函數(shù)

關(guān)于閉包“closure”,剛開(kāi)始接觸的時(shí)候,百度了N遍相關(guān)教程還是看得我一頭霧水,
聽(tīng)說(shuō)還會(huì)有內(nèi)存泄露的問(wèn)題,好吧,在開(kāi)發(fā)中干脆就不用吧。直到有一天,偶爾看到高階函數(shù),對(duì)于閉包以及整個(gè)JS語(yǔ)言的理解可以說(shuō)產(chǎn)生了翻天覆地的變化。

在這之前,先給大家回顧一下,閉包之所以成為閉包之前,有一個(gè)很重要的前提概念:變量的生命周期。
在函數(shù)體內(nèi),var定義的變量,變量屬于函數(shù)內(nèi),函數(shù)外無(wú)法訪問(wèn);反之如果沒(méi)有定義var的變量,像x=12,x屬于全局變量。
全局變量的生命周期是永久的,由頁(yè)面加載到關(guān)閉;而內(nèi)部變量,從函數(shù)執(zhí)行到結(jié)束,GC檢測(cè)到內(nèi)部變量沒(méi)有再被使用則會(huì)銷毀它。

    var fn = function () {
        var a = "a";
        b = "b";

        var fni = function () {
            c = "c";
        }();
    }();

    //console.log(a);//a is not defined
    console.log(b);//b
    console.log(c);//c

關(guān)鍵就在這,如果內(nèi)部變量在函數(shù)執(zhí)行結(jié)束后,仍然有被使用呢?

解決方案就是——高階函數(shù)。

高階函數(shù)名字看起來(lái)高端,實(shí)際很簡(jiǎn)單,滿足以下條件其一就是高階函數(shù):

1、函數(shù)的參數(shù)是函數(shù);

2、函數(shù)的返回值是函數(shù);

    function myFunction() {
        console.log("我是個(gè)函數(shù)");
    };
    //高階函數(shù)1——函數(shù)的參數(shù)是函數(shù)
    function fnHO1(fn) {
        fn();
    }
    //高階函數(shù)2——函數(shù)的返回值是函數(shù)
    function fnHO2() {
        return myFunction;
    };

    //調(diào)用高階函數(shù)1
    fnHO1(myFunction);//我是個(gè)函數(shù)

    //調(diào)用高階函數(shù)2
    fnHO2();//神馬都沒(méi)有發(fā)生

    //調(diào)用高階函數(shù)2,獲得的是它的內(nèi)部函數(shù)體
    var f2 = fnHO2();
    //再執(zhí)行,才是調(diào)用它的內(nèi)部函數(shù)
    f2();//我是個(gè)函數(shù)

在高階函數(shù)的基礎(chǔ),我們來(lái)看看,史上最經(jīng)典的閉包實(shí)例。

    function add_outer() {
        var i = 1;

        //返回值是內(nèi)部函數(shù),inner調(diào)用了其外部的變量
        //所以inner執(zhí)行結(jié)束時(shí),i沒(méi)有被銷毀
        return function inner() {
            i++;
            return i;
        };
    };

    //執(zhí)行add_outer獲取的是它的內(nèi)部函數(shù)體inner,但沒(méi)有執(zhí)行
    var inner = add_outer();

    //真正執(zhí)行的時(shí)候,變量i沒(méi)有被銷毀,形成遞增
    console.log(inner());//2
    console.log(inner());//3
    console.log(inner());//4

我對(duì)于閉包的理解很簡(jiǎn)單:==函數(shù)返回值是個(gè)內(nèi)部函數(shù),內(nèi)部調(diào)用了函數(shù)的內(nèi)部變量==。

兩個(gè)條件,缺一不可。如果將以上例子改一下,內(nèi)部有函數(shù),但不是返回值,就不是閉包了。

    function add_outer() {
        var i = 1;

        //返回值不是函數(shù),形成不了閉包
        function inner() {
            i++;
            console.log(i);
        };
        inner();
    };

    //執(zhí)行多次,值也不會(huì)變
    add_outer();//2
    add_outer();//2

也許大家會(huì)疑問(wèn),既然內(nèi)部變量i在函數(shù)結(jié)束后仍然使用,導(dǎo)致GC無(wú)法回收其內(nèi)存,那不就是內(nèi)存泄露嗎?
是的。其實(shí)我們反過(guò)來(lái)想,如果我們不使用閉包的方式實(shí)現(xiàn)以上累加的例子,改為使用全局變量存放變量i,全局變量i是否同樣也是不能被回收呢?!

    //function add_outer() {
        var i = 1;

        function inner() {
            i++;
            return i;
        };
    //};

    ////執(zhí)行add_outer獲取的是它的內(nèi)部函數(shù)體inner,但沒(méi)有執(zhí)行
    //var inner = add_outer();

    //真正執(zhí)行的時(shí)候,變量i沒(méi)有被銷毀,形成遞增
    console.log(inner());//2
    console.log(inner());//3
    console.log(inner());//4

因此,閉包與高階函數(shù),只是函數(shù)式編程的編寫(xiě)方式,即使并不是造成內(nèi)存泄露的原因。關(guān)于閉包與內(nèi)存泄露的問(wèn)題,請(qǐng)移步 http://www.cnblogs.com/yakun/p/3932026.h...

原型模式、閉包與高階函數(shù)應(yīng)該可以說(shuō)是JS設(shè)計(jì)模式的基礎(chǔ)要領(lǐng)吧。在下一章,再分享一下JS的幾種常用設(shè)計(jì)模式。

還是像前面所說(shuō)的,有什么地方說(shuō)錯(cuò),望大家指正。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/85927.html

相關(guān)文章

  • JS程序

    摘要:設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開(kāi)始接觸的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊蹋駝t只會(huì)讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識(shí)只有分享才有存在的意義。 是時(shí)候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評(píng)論0 收藏0
  • 2017年 最好的javascript 書(shū)籍

    摘要:請(qǐng)記住,這些書(shū)中的一些可能不是最新的,但概念和基礎(chǔ)仍應(yīng)適用。是最好的老師之一。的秘密由部分組成。在你完成這些書(shū)后,查看書(shū)籍和最好的本土?xí)? 我看過(guò)三本,第1本,第二本,第四本。第一本買(mǎi)的的實(shí)體書(shū),其他兩本看的是電子書(shū)。第一本是大名鼎鼎老道寫(xiě)的,書(shū)很薄,但是非常經(jīng)典。javascirpt忍者秘籍是jquery的作者寫(xiě)的,也是非常經(jīng)典。you dont kown js系列也是非常好??戳?..

    mingzhong 評(píng)論0 收藏0
  • 前端練級(jí)攻略(第二部分)

    摘要:是文檔的一種表示結(jié)構(gòu)。這些任務(wù)大部分都是基于它。這個(gè)實(shí)踐的重點(diǎn)是把你在前端練級(jí)攻略第部分中學(xué)到的一些東西和結(jié)合起來(lái)。一旦你進(jìn)入框架部分,你將更好地理解并使用它們。到目前為止,你一直在使用進(jìn)行操作。它是在前端系統(tǒng)像今天這樣復(fù)雜之前編寫(xiě)的。 本文是 前端練級(jí)攻略 第二部分,第一部分請(qǐng)看下面: 前端練級(jí)攻略(第一部分) 在第二部分,我們將重點(diǎn)學(xué)習(xí) JavaScript 作為一種獨(dú)立的語(yǔ)言,如...

    BWrong 評(píng)論0 收藏0
  • 理解JavaScript的核心知識(shí)點(diǎn):原型

    摘要:首先,需要來(lái)理清一些基礎(chǔ)的計(jì)算機(jī)編程概念編程哲學(xué)與設(shè)計(jì)模式計(jì)算機(jī)編程理念源自于對(duì)現(xiàn)實(shí)抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過(guò)程式和函數(shù)式編程。 JavaScript 中的原型機(jī)制一直以來(lái)都被眾多開(kāi)發(fā)者(包括本人)低估甚至忽視了,這是因?yàn)榻^大多數(shù)人沒(méi)有想要深刻理解這個(gè)機(jī)制的內(nèi)涵,以及越來(lái)越多的開(kāi)發(fā)者缺乏計(jì)算機(jī)編程相關(guān)的基礎(chǔ)知識(shí)。對(duì)于這樣的開(kāi)發(fā)者來(lái)說(shuō) J...

    iKcamp 評(píng)論0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函數(shù)式編程前端掘金引言面向?qū)ο缶幊桃恢币詠?lái)都是中的主導(dǎo)范式。函數(shù)式編程是一種強(qiáng)調(diào)減少對(duì)程序外部狀態(tài)產(chǎn)生改變的方式。 JavaScript 函數(shù)式編程 - 前端 - 掘金引言 面向?qū)ο缶幊桃恢币詠?lái)都是JavaScript中的主導(dǎo)范式。JavaScript作為一門(mén)多范式編程語(yǔ)言,然而,近幾年,函數(shù)式編程越來(lái)越多得受到開(kāi)發(fā)者的青睞。函數(shù)式編程是一種強(qiáng)調(diào)減少對(duì)程序外部狀態(tài)產(chǎn)生改變的方式。因此,...

    cfanr 評(píng)論0 收藏0
  • JavaScript進(jìn)階之路

    摘要:前端入門(mén)的門(mén)檻相對(duì)較低,學(xué)習(xí)曲線是越來(lái)越陡峭,由淺入深,可以分為四個(gè)階段。第二階段高級(jí)程序設(shè)計(jì)有的書(shū)是用來(lái)成為經(jīng)典的,比如犀牛書(shū)還有些書(shū)是用來(lái)超越經(jīng)典的,顯然這本書(shū)就是。接下來(lái)可以看看教程,看看源代碼,嘗試著寫(xiě)一寫(xiě)這些效果。 前端入門(mén)的門(mén)檻相對(duì)較低,學(xué)習(xí)曲線是越來(lái)越陡峭,由淺入深,可以分為四個(gè)階段。 第一階段:《JavaScript DOM編程藝術(shù)》    看這本書(shū)之前,請(qǐng)先確認(rèn)你對(duì)J...

    Lowky 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<