javascript
[Effective JavaScript 笔记]第59条:避免过度的强制转换
js是弱類型語言。許多標準的操作符和代碼庫會把輸入參數強制轉換為期望的類型而不是拋出錯誤。如果未提供額外的邏輯,使用內置操作符的程序會繼承這樣的強制轉換行為。
functin square(x){return x*x; } square("3");//9強制轉換
強制轉換可以帶來方便性,但也會帶來相關的麻煩,一些錯誤無法顯露出來,導致程序行為的不穩定和難以調試。
當強制轉換與重載的函數一起工作的時候,結果會更難理解。上一節講的位向量類的enable方法。該方法使用其參數的類型來決定其行為。如果enable方法嘗試將其參數強制轉換為一個期望的類型,那么方法簽名可能會變更難理解。將方法的參數強制轉換為一個數字完全破壞了重載。
一般規則,在那些使用參數類型來決定重載函數行為的函數中避免強制轉換參數。強制轉換使用很難識別出參數的變量。
bits.enable('100');//數字還是位數組值調用者可以合理地認為參數可以是一個數字或一個位數組值,然而我們的構造函數并不是為字符串設計的,因此無法識別它。
防御性編程
可能是調用者沒有用對,但如果設計API時,強制只接收數字和對象,則可以避免出現上面的錯誤。
BitVector.prototype.enable=function(x){if(typeof x=== 'number'){this.enableBit(x);}else if(typeof x==='object' && object){for(var i=0,n=x.length;i < n;i++){this.enableBit(x[i]); }}else{throw new TypeError('請輸入一個數或類數組對象');} };enable方法的最終版本是一種風格更加謹慎的示例,被稱為防御性編程。防御性編程試圖以額外的檢查來抵御潛在的錯誤。抵御所有可能的錯誤是不可能的。如,我們可能使用檢查來確保如果x具有length屬性,那么它應該是一個對象,然而這并不是安全的,比如,一個意外使用的String對象。
監視函數
js除了提供實現檢查的基本工具外,比如typeof操作符,還可以編寫簡潔的工具函數來監視函數簽名。如,可以使用一個預先檢查來監視BitVector的構造函數。
function BitVector(x){uint32.or(arrayLike).guard(x);//... }借助于共享原型對象來實現guard方法以構建一個監視對象的工具庫。
var guard={guard:function(x){if(!this.test(x)){throw new TypeError('expected '+this);}} };每個監視對象實現自己的test方法和錯誤消息的字符串描述。
uint32監視對象
var uint32=Object.create(guard); uint32.test=function(x){return typeof x === 'number' && x === (x >>> 0); }; uint32.toString=function(){return 'uint32'; };uint32的監視對象使用js位操作符的一個訣竅來實現32位無符號整數的轉換。無符號右移位運算符在執行移位運算前會將其第一個參數轉換為一個32位的無符號整數。移入零位對整數值沒有影響。實際上uint32.test是把一個數字與該數字轉換為32位無符號整數的結果做比較。
arrayLike監視對象
下面實現arrayLike的監視對象。
var arrayLike=Object.create(guard); arrayLike.test=function(x){return typeof x==='object' && x && uint32.test(x.length); }; arrayLike.toString=function(){return 'array-like object'; };這里又進一步地采取了防御性編程來確保一個類數組對象應該具有一個無符號整數的length屬性。
“鏈”方法
最后,實現一些原型方法的“鏈”方法,比如or方法。
guard.or=function(other){var res=Object.create(guard);var self=this;res.test=function(x){return self.test(x)||other.test(x);};var description=this+' or '+other;res.toString=function(){return description;};return res; }該方法合并接受者監視對象和另一個監視對象,產生一個新的監視對象。新監視對象的test和toString方法合并了這兩個輸入對象的方法。這里用局部的self來保存this的引用,以確保能在合成的監視對象的test方法中引用。
當遇到錯誤時,這些測試能幫助我們更早地捕獲錯誤,使得它們更容易診斷。但,這也可能擾亂代碼庫并潛在地影響應用程序的性能。是否使用防御性編程是一個成本和收益的問題。
提示
-
避免強制轉換和重載的混用
-
考慮防御性地監視非預期的輸入
轉載于:https://www.cnblogs.com/wengxuesong/p/5652178.html
總結
以上是生活随笔為你收集整理的[Effective JavaScript 笔记]第59条:避免过度的强制转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于Async与Await的FAQ
- 下一篇: 为何Apache下.htaccess不起