js運(yùn)行環(huán)境?
js運(yùn)行在瀏覽器內(nèi)核中的JS引擎
瀏覽器:
請求一個HTTP地址,將一個url地址封裝成一個請求報文非区,將響應(yīng)報文解析
響應(yīng)報文:
html ----->渲染html
css---->渲染css
image---->渲染圖片
js---->解釋執(zhí)行js
瀏覽器中的js可以做什么?
操作DOM盹廷,增刪改征绸,注冊事件
AJAX、跨域
BOM----頁面跳轉(zhuǎn)俄占、歷史記錄管怠、console.log()、alert()...
ECMAScript
瀏覽器中的js不能做什么缸榄?
文件操作----文件和文件夾的增刪改查
對操作系統(tǒng)的信息的操作
由于js運(yùn)行環(huán)境特殊排惨,為了安全,我們寫的代碼是在不認(rèn)識的人的瀏覽器中運(yùn)行
編程語言的能力取決于什么碰凶?
取決于這個語言的運(yùn)行平臺(環(huán)境)。
我們常說的JS實(shí)際是ES鹿驼,它的大部分能力都是由瀏覽器的執(zhí)行引擎決定欲低,BOM和DOM可以說是瀏覽器提供的接口
Java即是語言,也是平臺畜晰。Java運(yùn)行在Java虛擬機(jī)(跨操作系統(tǒng))
c#語言砾莱, 平臺是 .net framework(windows系統(tǒng))
PHP即是語言也是平臺
JS只能運(yùn)行在瀏覽器中嗎?
不是凄鼻,能運(yùn)行在哪腊瑟,取決于這個環(huán)境有沒有特定的平臺
Node.js建立在V8引擎(Chrome中的js引擎)上聚假,采用事件驅(qū)動、非阻塞的I/O模型闰非,通過自行開發(fā)的libuv庫膘格,調(diào)用操作系統(tǒng)資源。
Node.js----JS在服務(wù)端的運(yùn)行環(huán)境财松,類似于JAVA的虛擬機(jī)
Node.js----提供一些JS對文件的直接操作瘪贱、網(wǎng)絡(luò)操作、操作系統(tǒng)信息等
Node.js----選擇了JS語言
Node.js作用:
做網(wǎng)站辆毡,處理瀏覽器請求
分發(fā)數(shù)據(jù)請求:User Browser<-->node server<-->Application server(傳統(tǒng)java, .net, php..)提供服務(wù)接口
安裝
方式一:下載node.js安裝包直接安裝菜秦,不推薦,更新時比較麻煩
方式二:NVM方式----nvm是一個可以讓你在同一臺機(jī)器上安裝和切換不同版本node的工具舶掖,不同版本存在api不太一樣球昨,不同版本的系統(tǒng)對node的不同版本支持情況不同
下載nvm-windows,解壓到全英文路徑,建議開發(fā)相關(guān)的放在c盤
在根目錄下找到settings.txt文件(如果沒有眨攘,就自己創(chuàng)建)主慰,修改該文件
settings.txt:
root: C:\dev\nvm----nvm.exe的路徑
path: C:\dev----node.js快捷方式放在哪里
arch: 64----操作系統(tǒng)位數(shù)
proxy:----下載node先關(guān)文件時使用的代理
配置環(huán)境變量:
新建用戶變量:變量名:NVM_HOME;變量值:C:\dev\nvm
`NVM_HOME=當(dāng)前nvm.exe所在的目錄`
同理:`NVM_SYMLINK=node快捷方式所在的目錄`
添加進(jìn)PATH:`PATH += %NVM_HOME%;%NVM_SYMLINK%`
配置完期犬,打開cmd河哑,通過set命令查看是否配置成:set NVM_HOME 其他兩個也一樣
nvm use 5.7.0-----使用node5.7.0版本,創(chuàng)建該版本的快捷方式
環(huán)境變量:----變量名不區(qū)分大小寫龟虎,Linux系統(tǒng)例外
用戶變量的配置只對當(dāng)前登錄系統(tǒng)的用戶起作用
系統(tǒng)變量則對所有用戶起作用
命令行/Shell命令:
pwd獲取當(dāng)前路徑---windows下只能用在shell中
mkdir創(chuàng)建目錄璃谨,甚至可以創(chuàng)建以點(diǎn)開頭的文件夾
clear清空當(dāng)前控制臺
del 刪除文件,在shell/linux中是rm
echo輸出 echo 'hello' >> 1.txt
cat查看文件內(nèi)容
REPL環(huán)境鲤妥,在shell直接node就可進(jìn)入
可以測試js代碼佳吞, .exit可以退出這個環(huán)境,就是調(diào)用了process.exit()方法
node --use_strict進(jìn)入嚴(yán)格模式
_下劃線表示上次執(zhí)行結(jié)果
node編輯推薦使用Visual Studio Code----既是一個瀏覽器棉安,又是一個node環(huán)境模擬器
node不能做BOM/DOM操作底扳,但它也提供了console.log(),console.error(new Error('error'))打印錯誤對象
shell命令行
node demo.js執(zhí)行js文件
全局對象----global,類似于window對象
process----對進(jìn)程的操作
清空控制臺當(dāng)前顯示窗口:
做法一:
var height = process.stdout.getWindowSize();//[寬度,高度]
var height = process.stdout.getWindowSize()[1];//獲取當(dāng)前窗口的高度
for (var i = 0; i < height; i ++) {
process.stdout.write('\n')
}//用回車將當(dāng)前創(chuàng)窗口望上擠
做法二:
process.stdout.write('\033[2J');
process.stdout.write('\033[0f');
------------------------------------------------
setInterval(() => {
console.log("你好贡耽,這個世界衷模!");
}, 500);//每半秒輸出一次
//如果通過命令行來執(zhí)行該文件,下面實(shí)現(xiàn)按兩次control + c退出程序
let exiting = false;//用來判斷此時有沒有按下過^C
process.on('SIGINT', () => {//對該進(jìn)程注冊一個SIGINT事件蒲赂,該事件在按下^C的時候出發(fā)
if (exiting) {//exiting為真阱冶,表明已經(jīng)按下過一次
console.log("再見,這個世界滥嘴!");
process.exit();//退出當(dāng)前進(jìn)程
} else {
//第一次按下
console.log("第一次按下^C木蹬,再按一次退出");
exiting = true;
setTimeout(() => {
exiting = false;
}, 3000)//如果第一次按下^C超過3秒,這次按下不作數(shù)若皱,重新開始統(tǒng)計
}
})
---------------------------------------
on------用來注冊事件
process.stdin.on('data', (data) => {//當(dāng)有數(shù)據(jù)輸入的時候镊叁,回車后就觸發(fā)
process.stdout.write(data);
});
//用戶名和密碼驗(yàn)證
var q = "請輸入用戶名";
var users = {
'admin': '123',
'user1': '321',
'user2': '110'
};
//輸出第一個問題尘颓,提示用戶
process.stdout.write(q + '\n');
//設(shè)置一個標(biāo)志,用來指示此時輸入的是用戶名還是密碼
// var isInputUeserName = true;
var userName = '';//接受用戶輸入
// var res = process.stdin.readline();//用戶操作無狀態(tài)晦譬,所以不能認(rèn)為代碼執(zhí)行到這里用戶會輸入
//input其實(shí)是流疤苹,即二進(jìn)制數(shù)組
process.stdin.on('data', (input) => {
//獲得一個鍵值對集合中所有的鍵
//input內(nèi)容多加了一個回車符,要將這個回車符去掉
//trim()方法用來除去兩頭空格
//要知道到底input是用戶名還是密碼
input = input.toString().trim();
if (!userName) {//userName還沒有接受用戶名時
//Object.keys()獲取一個鍵值對(對象)中所有的鍵蛔添,得到鍵組成的數(shù)組
//arr.indexOf(要找的值)找一個數(shù)組中是否有某個元素痰催,如果存在,返回該元素的下標(biāo)迎瞧,如果不存在夸溶,返回-1
if(Object.keys(users).indexOf(input) === -1) {
//用戶名不存在
process.stdout.write("用戶名不存在" + '\n');
// isInputUeserName = true;
userName = '';
} else {
//用戶名存在
process.stdout.write("請輸入密碼\n");
// isInputUeserName = false;
userName = input;
}
} else {
//此時傳入密碼,此處拿不到上次的輸入,要先記錄
// console.log("此時傳入密碼");
if (input === users[userName]) {
console.log("登陸成功!");
} else {
process.stdout.write("請輸入密碼\n");
}
}
});
-------------------------
異步操作----當(dāng)需要等待一個無狀態(tài)的操作時
node中所有會發(fā)生阻塞的才做都是異步的
console.time('main')//代碼計時器
code
code
...
console.timeEnd('main');//打印中間code執(zhí)行時間
setTimeout(比較耗時的函數(shù)操作凶硅, 0);//功能是將該函數(shù)作為回調(diào)函數(shù)放在事件隊(duì)列的最后缝裁,但和其他操作有關(guān)聯(lián)時要注意
node中多采用回調(diào)函數(shù)的方式處理異步任務(wù)----當(dāng)資源獲取成功后再調(diào)取某函數(shù)執(zhí)行
回調(diào)函數(shù)放在函數(shù)參數(shù)的最后, function fun (path, callback回調(diào)函數(shù)) {}
回調(diào)函數(shù)錯誤優(yōu)先----回調(diào)函數(shù)的第一個參數(shù)是錯誤對象
在異步操作中如果發(fā)生異常足绅,無法通過try...catch拿到錯誤信息捷绑,那么就通過回調(diào)函數(shù)的第一個參數(shù)取到錯誤信息
舉例:判斷用戶名是否是字符串
let isString(username, callback) {
if (typeof username === 'string'){//如果得到的是字符串
callback(null, '是字符串')//沒有拋出錯誤信息
} else {
callback(new Error('不是字符串'))//拋出一個錯誤對象
}
}
//函數(shù)調(diào)用
isString('12ycni', (error, data) => {
if (error) throw error;//如果有錯誤信息,則拋出異常
console.log(data);
})
isString(1, (error, data) => {
if (error) throw error;//如果有錯誤信息氢妈,則拋出異常
console.log(data);
})
執(zhí)行結(jié)果:
F:\fore-end\materials\node.js\projs\proj2\error.js:16
if (error) throw error;//如果有錯誤信息粹污,則拋出異常
^
----上面是說明哪里拋出了異常,下面是我們新建的error對象的拋出----
Error: 不是字符串
at isString (F:\fore-end\materials\node.js\projs\proj2\error.js:5:12)
at Object.<anonymous> (F:\fore-end\materials\node.js\projs\proj2\error.js:15:1)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:389:7)
at startup (bootstrap_node.js:149:9)
解釋一下js中異常(出錯)的處理
JS中的錯誤類型:
1.SyntaxError: 語法錯誤
2.ReferenceError: 引用錯誤 要用的東西沒找到
3.RangeError: 范圍錯誤 專指參數(shù)超范圍
4.TypeError: 類型錯誤 錯誤的調(diào)用了對象的方法
5.EvalError: eval()方法錯誤的使用
6.URIError: url地址錯誤
當(dāng)發(fā)生錯誤時首量,JavaScript 引擎通常會停止壮吩,并生成一個錯誤消息,自動創(chuàng)建一個error對象加缘。
Error對象是封裝錯誤信息的對象鸭叙,在發(fā)生錯誤時,自動創(chuàng)建
兩個屬性:
err.name :錯誤的名稱/錯誤的類型
err.message: 錯誤的提示信息
使用方式有:Throw拣宏、Try 和 Catch
try
{
//在這里運(yùn)行代碼
}
catch(err)
{
//在這里處理錯誤
}
throw 語句允許我們創(chuàng)建自定義錯誤沈贝。
copy一個W3School上面的例子:
http://www.w3school.com.cn/tiy/t.asp?f=js_throw_error
<!DOCTYPE html>
<html>
<body>
<script>
function myFunction()
{
try
{
var x=document.getElementById("demo").value;
if(x=="") throw "值為空";
if(isNaN(x)) throw "不是數(shù)字";
if(x>10) throw "太大";
if(x<5) throw "太小";
}
catch(err)
{
var y=document.getElementById("mess");
y.innerHTML="錯誤:" + err + "。";
}
}
</script>
<h1>我的第一個 JavaScript 程序</h1>
<p>請輸入 5 到 10 之間的數(shù)字:</p>
<input id="demo" type="text">
<button type="button" onclick="myFunction()">測試輸入值</button>
<p id="mess"></p>
</body>
</html>
對于throw,如果我們單純的像上面例子里面勋乾,拋出一個字符串信息宋下,當(dāng)我們的程序比較長的時候,就很難定位出錯位置辑莫,所以杨凑,我們更多的使用一個自定義的錯誤對象,就如判斷用戶名是否是字符串例子一樣