三天node入門(day1)

1.前言

目錄:

  1. 安裝(就不說(shuō)了谤祖,網(wǎng)上去找)
  2. 模塊
  3. 代碼的組織和部署
  4. 文件操作

本文的命令行為

$ node node_test.js test.py test.py1

process.argv[2]test.py可婶。

有疑問(wèn)或是文章中有錯(cuò)誤的地方岔乔,請(qǐng)?jiān)谠u(píng)論區(qū)指出來(lái),如果私信的話別人就看不到了,加油一起進(jìn)步~~(゜▽゜*)?

2.模塊

每一個(gè)文件就是一個(gè)模塊尉咕,文件的路徑就是模塊名。在每個(gè)模塊中璃岳,都有require年缎、exportsmodule這三個(gè)變量可以使用铃慷。

一個(gè)模塊的代碼只在初始化時(shí)執(zhí)行一次单芜,之后被緩存以供重復(fù)調(diào)用。

a.require

一個(gè)方法犁柜,用于在一個(gè)模塊中洲鸠,加載另一個(gè)模塊的,返回一個(gè)導(dǎo)出對(duì)象馋缅。建議傳入相對(duì)路徑而不是絕對(duì)路徑扒腕。

const foo1 = require('./foo') // .js文件擴(kuò)展名可以忽略
const data = require('./data.json') //也可以加載json文件

b.exports

一個(gè)對(duì)象,是當(dāng)前模塊的導(dǎo)出對(duì)象萤悴,用于導(dǎo)出方法或?qū)傩择渌K使用require方法可以調(diào)用當(dāng)前模塊的導(dǎo)出對(duì)象。

exports.sayName=function(name){
    console.log('Hi' +name)
}

c.module

一個(gè)對(duì)象覆履,可以訪問(wèn)當(dāng)前模塊的相關(guān)信息蹋盆,點(diǎn)擊查看他的相關(guān)屬性费薄。最多的用途是用來(lái)替換當(dāng)前模塊的導(dǎo)出模塊,他的默認(rèn)導(dǎo)出值為空對(duì)象栖雾,這時(shí)我們來(lái)將他改成一個(gè)函數(shù)楞抡。

module.exports = function () {
    console.log('test');
};

d.主模塊

node只有一個(gè)入口文件稱為主模塊,需要調(diào)用命令行來(lái)啟用的析藕。

node main.js

在一個(gè)文件中多次調(diào)用相同模塊時(shí)召廷,被引入的模塊的內(nèi)部變量只初始化一次,不會(huì)開辟新的內(nèi)存噪径。

3.代碼的組織和部署

a.模塊的路徑解析規(guī)則

從上一章我們知道了require支持相對(duì)路徑和絕對(duì)路徑柱恤。但這種引入方式在后期維護(hù)上如果修改了某個(gè)文件的存放位置,在引用它的文件中也要隨之修改相關(guān)路徑找爱,牽一發(fā)而動(dòng)全身梗顺。require還有第三種的路徑寫法。

內(nèi)置模塊

內(nèi)置模塊沒有路徑解析车摄,直接返回模塊的導(dǎo)出對(duì)象

const fs=require('fs')

node_modules

大部分第三方模塊都安裝于此目錄下寺谤,在引入時(shí)直接忽略node_modules文件夾之前的路徑,直接引入就好吮播。

比如該路徑為:

/mytac/node_modules/app

引入時(shí)

const app=require('app')

NODE_PATH環(huán)境變量

定義NODE_PATH環(huán)境變量变屁,如

NODE_PATH=/a/b/c

當(dāng)引用require('file')時(shí),node會(huì)嘗試以下路徑

/a/b/c/file

b.包

由多個(gè)子模塊組成的模塊稱為包意狠,把所有子模塊放在同個(gè)目錄下粟关,寫過(guò)npm包的人會(huì)知道,這個(gè)大模塊需要一個(gè)入口文件环戈。如果入口文件名為index的話闷板,在引入時(shí)直接寫之前的路徑就好了,如:

const app=require('application')
// 等價(jià)于
const app=require('application/index')

c.命令行

舉個(gè)栗子院塞,希望有一個(gè)命令行程序遮晚,傳入相關(guān)參數(shù),并將他打印出來(lái)

$ node myapp/src/util/node-echo.js Hello world
Hello world

這種使用方法不太像是一個(gè)命令行程序拦止,下面才是我們期望的方式

$ node-echo Hello world

Linux

在Linux下县遣,我們可以把js文件當(dāng)作shell腳本來(lái)執(zhí)行,為了達(dá)到上述效果汹族,步驟:

  1. 在shell腳本中萧求,通過(guò)#!注釋指定當(dāng)前腳本的解釋器,首先在node-echo.js文件頂部增加這條注釋顶瞒,證明該腳本需要node來(lái)解析夸政。
#! /myapp/src/util/env node
  1. 賦予node-echo.js文件執(zhí)行權(quán)限
$ chmod +x /myapp/src/util/node-echo.js
  1. 在PATH環(huán)境變量下指定某個(gè)目錄,比如要在/myapp/src/util/下創(chuàng)建一個(gè)軟鏈文件搁拙,文件名與我們希望使用的終端命令同名秒梳,命令如下:
$ sudo ln -s /myapp/src/util/node-echo.js /myapp/src/util/node-echo

這樣處理過(guò)后,可以在任意目錄下使用node-echo命令咯~

Windows

windows下與Linux完全不同箕速,需要.cmd文件來(lái)解決問(wèn)題酪碘。假如node-echo.js存放在C:\myapp\src\util目錄,并且該目錄已經(jīng)添加到PATH環(huán)境變量里盐茎,接下來(lái)需要在該目錄下新建一個(gè)名為node-echo.cmd文件兴垦,如下:

@node "C:\myapp\src\util\node-echo.js" %*

這樣處理過(guò)后,可以在任意目錄下使用node-echo命令咯~

工程目錄標(biāo)準(zhǔn)樣例

- /home/user/workspace/node-echo/   # 工程目錄
    - bin/                          # 存放命令行相關(guān)代碼
        node-echo
    + doc/                          # 存放文檔
    - lib/                          # 存放API相關(guān)代碼
        echo.js
    - node_modules/                 # 存放三方包
        + argv/
    + tests/                        # 存放測(cè)試用例
    package.json                    # 元數(shù)據(jù)文件
    README.md                       # 說(shuō)明文件

d.NPM

下載第三方包

# 下載安裝并將依賴寫入package.json文件中
$ npm install package --save
# 安裝指定版本
$ npm install package1.0.1

發(fā)布自己的包

先要在npm注冊(cè)個(gè)賬號(hào)字柠,然后按照npm init的提示填寫相關(guān)信息探越,最后使用npm publish發(fā)布就好。

3.文件操作

a.fs模塊

node只提供了基本的文件操作api窑业,但沒有文件拷貝這種高級(jí)操作钦幔,這里我們先練個(gè)手

小文件拷貝

var fs = require('fs');

function copy(src, dst) {
    fs.writeFileSync(dst, fs.readFileSync(src));
}

function main(argv) {
    copy(argv[0], argv[1]);
}

main(process.argv.slice(2));

進(jìn)入該目錄下,如果想要復(fù)制該目錄下的test.py文件到該文件夾下test2.py常柄,鍵入命令:

$ node node-echo.js test.py test2.py

以上程序通過(guò)fs.readFileSync從源路徑讀取文件內(nèi)容鲤氢,并使用fs.writeFileSync將文件寫入到目標(biāo)路徑。process是一個(gè)全局變量西潘,通過(guò)process.argv獲得命令行參數(shù)卷玉。值得注意的是argv[0]始終為node執(zhí)行程序的絕對(duì)路徑,argv[1]為主模塊的絕對(duì)路徑喷市,所以傳入的參數(shù)需要從argv[2]這個(gè)位置取相种。

大文件拷貝

上面的文件拷貝小文件沒有什么大問(wèn)題,但是讀取大文件內(nèi)存會(huì)爆倉(cāng)品姓,要讀取大文件只能讀一點(diǎn)寫一點(diǎn)寝并,直至完成,對(duì)于上面的程序需要進(jìn)行如下改造缭黔。

var fs=require('fs')

function copy(src,dist){
    fs.createReadStream(src).pipe(fs.createWriteStream(dist))
}

function main(argv){
    copy(argv[0],argv[1])
}

main(process.argv.slice(2))

使用fs.createReadStream創(chuàng)建一個(gè)源文件只讀數(shù)據(jù)流食茎,使用fs.createWriteStream創(chuàng)建一個(gè)只寫數(shù)據(jù)流,并用pipe方法將兩個(gè)數(shù)據(jù)流連接起來(lái)馏谨。

b.Buffer

js中沒有二進(jìn)制數(shù)據(jù)類型别渔,node提供了一個(gè)與String對(duì)等的全劇構(gòu)造函數(shù)Buffer來(lái)對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行操作。除了可以讀取文件得到Buffer的實(shí)例惧互,還能夠直接構(gòu)造哎媚,如:

var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]);

Buffer與String類型差不多,可以用length屬性讀取字節(jié)長(zhǎng)度喊儡,也可以通過(guò)[index]方式讀取文件位置拨与。也可與String相互轉(zhuǎn)化,如:

var str=bin.toString('utf-8') // 指定編碼
var bin=new Buffer('hello','utf-8') //<Buffer 68 65 6c 6c 6f>

當(dāng)然艾猜,他們兩者也是有區(qū)別的买喧。字符串是只讀的捻悯,他的意思不是說(shuō)這個(gè)字符串不會(huì)被修改,而是單獨(dú)修改某個(gè)字節(jié)位置淤毛,這個(gè)位置并不會(huì)改變今缚,而Buffer則不同,修改Buffer更像是修改數(shù)組低淡,可以直接修改某個(gè)位置的值姓言。

使用slice方法也不是返回一個(gè)新Buffer,而是返回了某個(gè)位置的指針,修改該指針的值會(huì)作用于原buffer蔗蹋。比如:

var bin =new Buffer([0x68,0x65,0x6c])
var bin2=bin.slice(1)
bin2[0]=0x68
console.log(bin) // 68 68 6c

所以何荚,如果想要拷貝一份buffer,需要?jiǎng)?chuàng)建一個(gè)新buffer猪杭,通過(guò)copy方法將buffer中的數(shù)據(jù)復(fù)制過(guò)去餐塘。

var bin =new Buffer([0x68,0x65,0x6c])
var dup=new Buffer(bin.length)
bin.copy(dup)
bin[0]=0x65
console.log(bin) //65 65 6c
console.log(dup) // 68 65 6c

c.Stream

當(dāng)內(nèi)存中無(wú)法一次裝下需要處理的數(shù)據(jù),或是需要一邊讀一邊處理時(shí)皂吮,我們就需要用到數(shù)據(jù)流唠倦。Node中通過(guò)各種Stream來(lái)提供對(duì)數(shù)據(jù)流的操作。比如涮较,對(duì)數(shù)據(jù)創(chuàng)建一個(gè)只讀流:

var fs=require('fs')
var rs=fs.createReadStream(process.argv[2])

rs.on('data',function(chunk){
   // do something
    console.log(chunk) 
})

rs.on('end',function(){
    console.log('end')
})

Stream基于事件機(jī)制工作稠鼻,所有Stream的實(shí)例都繼承于NodeJS提供的EventEmitter。
上面的data事件會(huì)不斷被觸發(fā)狂票,然而data事件中的函數(shù)并不會(huì)每次都執(zhí)行得過(guò)來(lái)候齿,可以按照如下方法來(lái)解決這個(gè)問(wèn)題。

var fs=require('fs')
var rs=fs.createReadStream(process.argv[2])

function print(data,func){
    console.log(data)
    func()
}

rs.on('data',function(chunk){
    rs.pause()
    print(chunk,function(){
        rs.resume()
    })
})

rs.on('end',function(){
    console.log('end')
})

創(chuàng)建一個(gè)只寫數(shù)據(jù)流

var fs=require('fs')
var rs=fs.createReadStream(process.argv[2])
var ws=fs.createWriteStream(process.argv[3])

rs.on('data',function(chunk){
    ws.write(chunk)
})

rs.on('end',function(){
    ws.end()
    console.log('end')
})

但上面的程序有個(gè)問(wèn)題是闺属,寫入速度跟不上讀取速度的話慌盯,內(nèi)部緩存會(huì)爆倉(cāng)。我們根據(jù).write方法的返回值來(lái)判斷傳入的數(shù)據(jù)是寫入目標(biāo)文件還是臨時(shí)放在了緩存中掂器,通過(guò)drain事件亚皂,drain的意思是排干,意思是用來(lái)判斷什么時(shí)候只寫數(shù)據(jù)流已經(jīng)將緩存中的數(shù)據(jù)寫入目標(biāo)国瓮,可以傳入下一個(gè)待寫數(shù)據(jù)了灭必。

var fs=require('fs')
const argvs=process.argv
var rs=fs.createReadStream(argvs[2])
var ws=fs.createWriteStream(argvs[3])

rs.on('data',function(chunk){
    if(ws.write(chunk)===false){
        rs.pause()
    }
})

rs.on('end',function(){
    ws.end()
})

ws.on('drain',function(){ // 防爆倉(cāng)控制
    rs.resume()
})

d.其他文件操作

(a)文件屬性的讀寫

獲取文件屬性

fs.stat

var fs=require('fs')
const argvs=process.argv
fs.stat(argvs[2],function(err,stats){
    if(err){
        throw err
    }else{
        console.log(stats)
    }
})

修改讀寫權(quán)限

fs.chmod

關(guān)于設(shè)置權(quán)限707、777

var fs=require('fs')
const argvs=process.argv
function getState(path,str){
    fs.stat(path,function(err,stat){
            if(err){
                throw err
            }else{
                console.log(str+stat.mode)
            }
        })
}

getState(argvs[2],'原權(quán)限')

fs.chmod(argvs[2],0777,function(err){
    if(err){
        throw err
        console.log('讀寫失敗')
    }else{
        getState(argvs[2],'現(xiàn)權(quán)限')
    }
})

更改文件所有權(quán)

fs.chown

var fs=require('fs')
const path=process.argv[2]
function getState(path){
    fs.stat(path,function(err,stat){
            if(err){
                throw err
            }else{
                const {gid,uid}=stat
                console.log(`gid:${gid},uid:${uid}`)
            }
        })
}

getState(path)
fs.chown(path,1,0,function(err){ // 1,0分別對(duì)應(yīng)uid乃摹、gid
    if(err){
        throw err
    }else{
        console.log('changed')
        getState(path)
    }
})

(b)文件內(nèi)容讀寫

讀取文件內(nèi)容

fs.readFile

var fs=require('fs')
const path=process.argv[2]
fs.readFile(path,'utf-8',function(err,data){ // 不指定編碼的情況下禁漓,以buffer形式輸出
    if(err){
        throw err
    }else{
        console.log(data)
    }
})

讀取文件目錄

fs.readdir

fs.readdir('../',function(err,files){ //傳入目錄
    if(err){
        throw err
    }
        console.log(files)
})

寫入文件

如果文件存在,則被覆蓋

fs.writeFile

fs.writeFile('test.txt','test message~~~',function(err){
    if(err){
        throw err
    }
        console.log('saved file')
})

創(chuàng)建目錄

如果目錄存在孵睬,則拋出異常

fs.mkdir

fs.mkdir('newdir',0777,err=>{
    if(err) throw err
        console.log('created!')
})

(c)底層文件操作

打開/關(guān)閉文件

fs.open
fs.close

var fs=require('fs')
const path=process.argv[2]
fs.open(path,'w',(err,fd)=>{
    if(err) throw err
    fs.futimes(fd,1388648322,1388648322,err=>{
        if(err) throw err
        console.log('futimes done')
    fs.close(fd,()=>{
        console.log('done')
    })
    })
})

讀取文件數(shù)據(jù)

fs.read
根據(jù)指定的文件描述符fd來(lái)讀取文件數(shù)據(jù)并寫入buffer指向的緩沖區(qū)對(duì)象播歼。相對(duì)于readFile提供了更底層的接口.

一般情況下不建議使用這種方式來(lái)讀取文件,因?yàn)樗竽闶謩?dòng)管理緩沖區(qū)和文件指針掰读,尤其是在 你不知道文件大小的時(shí)候秘狞,這將會(huì)是一件很麻煩的事情叭莫。

var fs = require('fs')
const path = process.argv[2]
fs.open(path, 'r', (err, fd) => {
    if (err) throw err
    let buf = new Buffer(8)
    fs.read(fd, buf, 1, 15, null, (err, bytesRead, buffer) => { // 0為偏移量  100為讀取的字結(jié)束  null為開始讀取的位置,null只從讀取位置讀取
        if (err) throw err
        console.log('bytesRead', bytesRead)
        console.log(buffer)
    })
})

根據(jù)文件描述符寫入文件

fs.write
該方法提供更底層的操作烁试,實(shí)際應(yīng)用中建議使用多 fs.writeFile()

var fs = require('fs')
const path = process.argv[2]
fs.open(path, 'w', (err, fd) => {
    if (err) throw err
    const data='# hello python!'
    const buf=new Buffer(data,'utf-8')
    fs.write(fd,buf,0,data.length,0,(err,bytesWritten,buffer)=>{
        if(err) throw err
        console.log(bytesWritten)
        console.log(buffer)

        fs.close(fd,err=>{
            if(err) throw err
                console.log('file closed')
        })
    })
}

以上介紹的方法都是以異步的方式調(diào)用的食寡,也分別都有對(duì)應(yīng)的同步方法,拿readFileSync舉例:

var fs = require('fs')
const path = process.argv[2]
try{
    const data=fs.readFileSync(path)
    console.log(data)
}catch(err){
    console.log(err)
}

e.Path

node中提供了幾個(gè)內(nèi)置模塊來(lái)簡(jiǎn)化路徑相關(guān)操作廓潜,并提升代碼可讀性。

路徑標(biāo)準(zhǔn)化

path.normalize(path)
將傳入的路徑轉(zhuǎn)換為標(biāo)準(zhǔn)的路徑善榛,可以去掉多余的斜杠辩蛋。但在不同操作系統(tǒng)下,解析后的斜杠不一樣移盆。

var path=require('path')
const url = process.argv[0]
console.log(path.normalize(url))

連接路徑分隔符

將path片段連接在一起并將路徑規(guī)范化悼院。
path.join

var path=require('path')
console.log(path.join('/foo','//bar','abc','../abc')) // \foo\bar\abc

獲取path的擴(kuò)展名

返回文件的擴(kuò)展名,從最后一個(gè).截取咒循,沒有.則返回空字符串据途。
path.extname

const url = process.argv[2]
var path=require('path')
console.log(path.extname(url)) // .py
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市叙甸,隨后出現(xiàn)的幾起案子颖医,更是在濱河造成了極大的恐慌,老刑警劉巖裆蒸,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熔萧,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡僚祷,警方通過(guò)查閱死者的電腦和手機(jī)佛致,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)辙谜,“玉大人俺榆,你說(shuō)我怎么就攤上這事∽岸撸” “怎么了罐脊?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蜕琴。 經(jīng)常有香客問(wèn)我爹殊,道長(zhǎng),這世上最難降的妖魔是什么奸绷? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任梗夸,我火速辦了婚禮,結(jié)果婚禮上号醉,老公的妹妹穿的比我還像新娘反症。我一直安慰自己辛块,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布铅碍。 她就那樣靜靜地躺著润绵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胞谈。 梳的紋絲不亂的頭發(fā)上尘盼,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音烦绳,去河邊找鬼卿捎。 笑死,一個(gè)胖子當(dāng)著我的面吹牛径密,可吹牛的內(nèi)容都是我干的午阵。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼享扔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼底桂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起惧眠,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤籽懦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后氛魁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猫十,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年呆盖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拖云。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡应又,死狀恐怖宙项,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情株扛,我是刑警寧澤尤筐,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站洞就,受9級(jí)特大地震影響盆繁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜旬蟋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一油昂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦冕碟、人聲如沸拦惋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)厕妖。三九已至,卻和暖如春挑庶,著一層夾襖步出監(jiān)牢的瞬間言秸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工迎捺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留举畸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓破加,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親雹嗦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子范舀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測(cè)試 ...
    KeKeMars閱讀 6,305評(píng)論 0 6
  • Node.js是目前非常火熱的技術(shù)了罪,但是它的誕生經(jīng)歷卻很奇特锭环。 眾所周知,在Netscape設(shè)計(jì)出JavaScri...
    w_zhuan閱讀 3,609評(píng)論 2 41
  • 個(gè)人入門學(xué)習(xí)用筆記泊藕、不過(guò)多作為參考依據(jù)辅辩。如有錯(cuò)誤歡迎斧正 目錄 簡(jiǎn)書好像不支持錨點(diǎn)、復(fù)制搜索(反正也是寫給我自己看...
    kirito_song閱讀 2,451評(píng)論 1 37
  • Node.js是目前非惩拊玻火熱的技術(shù)玫锋,但是它的誕生經(jīng)歷卻很奇特尿招。 眾所周知李命,在Netscape設(shè)計(jì)出JavaScri...
    Myselfyan閱讀 4,064評(píng)論 2 58
  • 看別人寫的怎么學(xué)英語(yǔ)的文章,什么聽說(shuō)讀寫盟蚣,聽播客悦屏,看外國(guó)大片节沦,和老外聊天,我想說(shuō)能不能結(jié)合點(diǎn)實(shí)際的础爬,大家都要工作沒...
    羅蓁蓁閱讀 376評(píng)論 2 4