strict mode優點:更嚴格的檢查、刪除了一些有問題的語言特性。less
把 "use strict" 放在文件頂部(必須是文件頂部,放在其它地方就被當成字符串了)或者函數頂部開啓js strict模式。dom
示例1:沒啓用strict模式,js就會給你悄摸摸地加一個let上去...函數
function canYouSpotTheProblem() { "use strict"; for (counter = 0; counter < 10; counter++) { console.log("Happy happy"); } } canYouSpotTheProblem(); // → ReferenceError: counter is not defined
示例2:沒啓用strict模式,name被悄悄地綁定到一個全局對象上而沒報錯。oop
function Person(name) { this.name = name; } let ferdinand = Person("Ferdinand"); // oops console.log(name); // → Ferdinand console.log(window.name); // → Ferdinand // - -- - --修改↓分割線------------------------------------ "use strict"; function Person(name) { this.name = name; } let ferdinand = Person("Ferdinand"); // forgot new // → TypeError: Cannot set property 'name' of undefined
PS. 上述狀況,用class定義類具備和採用strict模式同樣的效果,因此儘可能用class定義類。測試
js在在運行時纔會涉及到類型。許多語言在編譯期就考慮類型了。spa
爲了減小js類型帶來的一些問題,有兩個簡單的解決方案:
① 註釋
// (VillageState, Array) → {direction: string, memory: Array} function goalOrientedRobot(state, memory) { // ... }
能夠進行類型檢查,並編譯成js
採用第三方測試套件或者以下所示:
function test(label, body) { if (!body()) console.log(`Failed: ${label}`); } test("convert Latin text to uppercase", () => { return "hello".toUpperCase() == "HELLO"; }); test("convert Greek text to uppercase", () => { return "Χαίρετε".toUpperCase() == "ΧΑΊΡΕΤΕ"; }); test("don't convert case-less characters", () => { return "مرحبا".toUpperCase() == "مرحبا"; });
console.log或者debugger關鍵字:
function add(a, b) { console.log(`add ${a} and ${b}`); return a + b; } debugger; // 從這一行開始進入瀏覽器debug模式 let x = add(1, 3); prompt("只有在開發者模式下,debug模式才生效");
異常的一大優點:幾乎無耦合地在多個函數中(調用棧)傳遞,中間函數什麼都不須要知道,僅在最外層處理就好了。
function promptDirection(question) { let result = prompt(question); if (result.toLowerCase() == "left") return "L"; if (result.toLowerCase() == "right") return "R"; throw new Error("Invalid direction: " + result); } function look() { if (promptDirection("Which way?") == "L") { return "a house"; } else { return "two angry bears"; } } try { console.log("You see", look()); } catch (error) { console.log("Something went wrong: " + error); }
function transfer(from, amount) { if (accounts[from] < amount) return; let progress = 0; try { accounts[from] -= amount; progress = 1; accounts[getAccount()] += amount; progress = 2; } finally { if (progress == 1) { accounts[from] += amount; } } } //Writing programs that operate reliably //even when exceptions pop up in unexpected places //is hard. Many people simply don’t bother, //and because exceptions are typically reserved //for exceptional circumstances, the problem may //occur so rarely that it is never even noticed. //Whether that is a good thing or a really bad thing //depends on how much damage the software will do when it fails.
js不支持catch分支,而在try-catch的時候,一樣會捕獲undefined.call等形成的異常。
有些人可能會想只要比對e裏面的信息就能夠知道哪兒出現問題了,可是異常信息不是一個穩定的東西,一旦拋出的異常信息的表達改變,程序就不會正常工做,更可靠的解決方案以下(自定義空異常,只爲了利用class區分,不加任何東西):
class InputError extends Error {} function promptDirection(question) { let result = prompt(question); if (result.toLowerCase() == "left") return "L"; if (result.toLowerCase() == "right") return "R"; throw new InputError("Invalid direction: " + result); } for (;;) { try { let dir = promptDirection("Where?"); console.log("You chose ", dir); break; } catch (e) { if (e instanceof InputError) { console.log("Not a valid direction. Try again."); } else { throw e; } } }
class MultiplicatorUnitFailure extends Error {} function primitiveMultiply(a, b) { if(Math.random() < 0.2) { return a * b; } else { throw new MultiplicatorUnitFailure("Klunk"); } } function reliableMultiply(a, b) { let result = undefined; for (; result == undefined;) { try { result = primitiveMultiply(a, b); } catch(e) { if (e instanceof MultiplicatorUnitFailure) { } else { throw e; } } } return result; } console.log(reliableMultiply(8, 8)); // → 64
————-- - --- -- - - -------—-- - -—-- - -
const box = { locked: true, unlock() { this.locked = false; }, lock() { this.locked = true; }, _content: [], get content() { if (this.locked) throw new Error("Locked!"); return this._content; } }; function withBoxUnlocked(body) { let locked = box.locked; if (!locked) { return body(); } box.unlock(); try { return body(); } finally { box.lock(); } } withBoxUnlocked(function() { box.content.push("gold piece"); }); try { withBoxUnlocked(function() { throw new Error("Pirates on the horizon! Abort!"); }); } catch (e) { console.log("Error raised:", e); } console.log(box.locked); // → true