[Effective JavaScript 筆記]第59條:避免過度的強制轉換

来源:http://www.cnblogs.com/wengxuesong/archive/2016/07/08/5652178.html
-Advertisement-
Play Games

js是弱類型語言。許多標準的操作符和代碼庫會把輸入參數強制轉換為期望的類型而不是拋出錯誤。如果未提供額外的邏輯,使用內置操作符的程式會繼承這樣的強制轉換行為。functin square(x){ return x*x; } square("3");//9 強制轉換 強制轉換可以帶來方便性,但也會帶來... ...


js是弱類型語言。許多標準的操作符和代碼庫會把輸入參數強制轉換為期望的類型而不是拋出錯誤。如果未提供額外的邏輯,使用內置操作符的程式會繼承這樣的強制轉換行為。

functin square(x){
    return x*x;
}
square("3");//9

強制轉換

強制轉換可以帶來方便性,但也會帶來相關的麻煩,一些錯誤無法顯露出來,導致程式行為的不穩定和難以調試。
當強制轉換與重載的函數一起工作的時候,結果會更難理解。上一節講的位向量類的enable方法。該方法使用其參數的類型來決定其行為。如果enable方法嘗試將其參數強制轉換為一個期望的類型,那麼方法簽名可能會變更難理解。將方法的參數強制轉換為一個數字完全破壞了重載。

BitVector.prototype.enable=function(x){
    x=Number(x);//轉化為數字
    if(typeof x=== 'number'){//一直是正確的
        this.enableBit(x);
    }else{//這裡永遠不會執行
        for(var i=0,n=x.length;i < n;i++){
           this.enableBit(x[i]); 
        }
    }
};

一般規則,在那些使用參數類型來決定重載函數行為的函數中避免強制轉換參數。強制轉換使用很難識別出參數的變數。

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方法中引用。
當遇到錯誤時,這些測試能幫助我們更早地捕獲錯誤,使得它們更容易診斷。但,這也可能擾亂代碼庫並潛在地影響應用程式的性能。是否使用防禦性編程是一個成本和收益的問題。

提示

  • 避免強制轉換和重載的混用

  • 考慮防禦性地監視非預期的輸入


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 場景 1. 過濾非正常用戶使用的http請求。 2. 限制正常用戶使用的範圍(下載速度、訪問頻率等)。 3. 通過架構規劃來提升安全。 4. 能自動解決http請求問題。 解決方案 代理自身的安全 1. 千萬不要使用root啟動!!! 2. 關閉伺服器的信息。 3. 關閉掉不使用的模塊。 過濾htt ...
  • 一、MyBatis入門簡要介紹(百科) MyBatis 是支持普通 SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis 消除了幾乎所有的JDBC代碼和參數的手工設置以及結果集的檢索。MyBatis 使用簡單的 XML或註解用於配置和原始映射,將介面和 Java 的POJOs(Plain ...
  • 在工作過程中,我經常能和來自全球各地的首席信息安全官(chief information security officers ,CISO)交流,他們所在的企業面對著不同的信息安全環境,關心的安全問題也不盡相同。但總體上來說,他們在信息安全防護上的困擾集中在以下四個問題: 1、雲應用安全 如今,越來越 ...
  • 一、平臺簡介 AgileEAS.NET SOA 中間件平臺是一款基於基於敏捷並行開發思想和Microsoft .Net構件(組件)開發技術而構建的一個快速開發應用平臺。用於幫助中小型軟體企業建立一條適合市場快速變化的開發團隊,以達到節省開發成本、縮短開發時間,快速適應市場變化的目的。 AgileEA ...
  • 本文為原創文章,轉載請註明出處,謝謝 ZkClient使用 1、jar包引入,演示版本為0.8,非maven項目,可以下載jar包導入到項目中 2、創建Zookeeper連接 示例:ZkClient zc = new ZkClient("192.168.117.128:2181",10000,100 ...
  • 1.意圖 將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤銷的操作。 2.別名 動作(Action),事務(Transaction) 3.動機 命令模式通過將請求本身變成一個對象來使請求可向未指定的應用對象提出請求。這個對象可被存儲並像其他的對 ...
  • 獲取【下載地址】 【免費支持更新】三大資料庫 mysql oracle sqlsever 更專業、更強悍、適合不同用戶群體【新錄針對本系統的視頻教程,手把手教開發一個模塊,快速掌握本系統】 A集成代碼生成器 [正反雙向(單表、主表、明細表、樹形表,開發利器)+快速構建表單;freemaker模版技術 ...
  • 需求:一個簡單的後臺java程式,收集信息,並將信息發送到遠端伺服器。 實現:實現一個後臺線程,實時處理髮送過來的信息,並將信息發送到伺服器。 技術要點: 1、單例模式 2、隊列 並沒有實現全部代碼,簡單把技術要點寫出來: 此程式只是做信息收集,併為後期數據統計做準備,通過單線程隊列實現,避免申請過 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...