中國電動超跑「前途 K50」預計 2017 亮相

Tesla 去(2015)年前三季在中國賣了約3000 輛Model S 和Model X 頂級款電動車,在全球全年交車輛更是達到50,580 輛,但有沒有可能,中國冒出的競爭對手會威脅Tesla 在電動車市場的領先地位?中國最大的汽車設計公司之一「北京長城華冠」在2015 年發表該公司第一款、也是中國第一款電動超跑「K50」,性能和價格都相當於Tesla Model S,而負責K50 生產的子公司「前途汽車」2 月於蘇州動土設廠,也意味著K50 量產在即。

K50 號稱5 秒就能加速至100公里,北京長城華冠董事長陸群受訪時說到,K50 有著碳纖維的車身、鋁製車架,預計2017 年就會亮相,售價約在70 萬人民幣(相當於10 萬6000 美元、345 萬台幣),價格相當於鋁製車身的Tesla Model S,而比起同樣是碳纖維車身的插電式油電混合車BMW i8,K50 的售價只有1/3。

陸群說,公司從Tesla 身上和其他電動車廠商身上學習,他們的目標就是打造高品質的汽車。前途汽車這個全資子公司自2015 年成立,任務就是打造電動汽車,而自己設廠,對他們來說是唯一的解決方案,因為在中國沒有其他在做碳纖維模型的工廠,這個花20 億人民幣打造的廠房,未來也會為其他車廠代工製造,預計初期的產值可以達到一年5 萬輛車。

至於在K50 之外,前途汽車也計畫再發表兩款便宜一些的電動車,陸群為前途汽車訂立目標,在2020 年獲得電動車市場15% 的市佔,又或者是45 萬輛。「我們會讓消費者相信,中國也是有能力打造一個全新的汽車品牌,一個頂尖的汽車品牌,一個頂尖的純電動車品牌。」陸群說。

分析師:打造電動車要看長期續航力

Bloomberg Intelligence 駐香港的汽車分析師Steve Man 是這樣看的,他認為前途汽車最終若要成功,得看他的行銷和市場聲望,但在那之前,打造一台經得起時間考驗的電動車可是需要相當多的耐心和資本,「我們就來看看前途有沒有這麼長的續航力」。

Elon Musk  對此表示,聽聽就好?

這番話透露出些許不信任的意味,至於身為市場領先者、被挑戰的對象,Tesla 創辦人兼執行長Elon Musk 又是怎麼看的呢?Elon Musk 曾在日前一場演講中對市場上充滿電動車和自駕車新近者眾多做出以下回應,「現在有太多新創公司發布電動車、自駕車的消息,我都在等哪天我媽也跳出來發布一輛。」

Elon Musk 這番話不是針對前途汽車,光是在中國市場,這類宣布要做電動車的新創公司可真不少。中國科技創業家李斌在2015 年創立「未來汽車」(NextEV,Inc),獲得騰訊和高瓴資本投資;樂視創辦人兼CEO賈躍亭在今年4 月也揭示一輛四門電動跑車「LeSEE」的概念;傳統車廠長安汽車也和福特合夥,投資180 億人民幣研發低能源汽車。

  • 資料來源:

本文授權轉載自《科技新報》──〈〉

(首圖來源:截自官網)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

新北清潔公司,居家、辦公、裝潢細清專業服務

Panasonic投500億日圓設車用鋰電池中國產線

全球電動車用鋰電池領導廠商日本松下(Panasonic)宣布,將投資500億日圓(約新台幣136億元、人民幣27億元)在中國成立以電動車鋰電池為主要產品的電池工廠,預計在2017年投入生產。這是繼松下與特斯拉(Tesla)合作在美國內華達州成立Gigafactory之後,另一大車用鋰電池生產計劃,將鞏固松下在美、中兩大市場的發展基礎。

中國電動車市場後市看好,松下積極搶進

中國政府將電動車列為減輕空污方案的方案之一,在政策與產業面上皆有積極作為,包括提供民眾每輛車最高5.5萬元人民幣的購車補貼,以及比亞迪(BYD)、北企集團等業者發展電動車的獎勵措施等。根據《日經》新聞中文網的報導,中國純電動車(EV)與插電式油電混和車(PHEV)的市場規模目前雖然不及10萬輛,但在未來十年內將成長7.5倍到約65萬輛之譜;而根據中國汽車工業協會的統計,今年1~11月之間,EV與PHEV的產量比去年同期增加了4.4倍,來到29萬輛。且不僅中國大陸本土廠商,日產、福斯汽車等也已展開中國市場的布局。

中國EV與PHEV的需求爆發直接帶動車用鋰電池的成長,也因而促成松下宣布到中國設廠的決定。松下將與中國當地企業合作,投資500億日圓在遼寧省大連市建造鋰電池工廠,主要產品將供給EV與PHEV,預計年產量可供20萬輛電動車使用,以目前技術換算,電池容量年產量約為20GWh。

在松下之前,南韓LG Chem已於十月宣布將在江蘇省南京市建立車用鋰電池工廠,且已在中國展開推銷業務。

松下戰略:搶入美、中兩大市場

松下已是全球最大的車用鋰電池製造商,市佔率高達45.7%;第二名為日產NEC,佔17.3%,先前宣布在中國設廠的LG Chem的市占率10.5%則為全球第三。而在本次設立車用鋰電池廠之前,松下在中國大陸已有個人電腦的電池工廠。

松下於2014年宣布與Tesla合作在美國內華達州建設一座超大型鋰電池工廠Gigafactory,初期預估投資額約1,500億日圓。但隨著今年Tesla發表Powerwall/Powerpack並奪下大筆訂單、加上全球電動車需求暴漲的預期,Gigafactory的投資額最後估計將來到50億美元,且投產時程也從原先的2017提前到2016年。到了2020年整體廠房完成並產能全開時,Gigafactory總產能估計將達50GWh,可供50萬輛EV/PHEV使用;不過,該廠也有部分產能將用於生產Powerwall與Powerpack產品。

以日本企業近年對中國的投資額來看,500~600億日圓屬於較罕見的大手筆投資,同時顯示松下積極開發美、中兩大電動車市場的野心。目前美國是全球第一大電動車需求市場,中國、日本分列第二與第三。到了2025年,美國市場需求預計將來到95萬輛以上、中國也會成長到65萬輛左右。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

※別再煩惱如何寫文案,掌握八大原則!

web應用安全框架選型:Spring Security與Apache Shiro

一、 SpringSecurity 框架簡介

官網:

源代碼:

Spring Security 是強大的,且容易定製的,基於Spring開發的實現認證登錄與資源授權的應用安全框架。

SpringSecurity 的核心功能:

  • Authentication:認證,用戶登陸的驗證(解決你是誰的問題)
  • Authorization:授權,授權系統資源的訪問權限(解決你能幹什麼的問題)
  • 安全防護,防止跨站請求,session 攻擊等

二、比較一下shiro與Spring Security

目前在java web應用安全框架中,與Spring Security形成直接競爭的就是shiro,二者在核心功能上幾乎差不多,但從使用的角度各有優缺點。筆者認為:沒有最好的,只有最合適的。

2.1 用戶量

從使用情況上看,二者都在逐步提高使用量。shiro的使用量一直高於spring security.

2.2.使用的方便程度

通常來說,shiro入門更加容易,使用起來也非常簡單,這也是造成shiro的使用量一直高於Spring Security的主要原因。但是從筆者的角度來看,二者其實都簡單,我說說我的理由:

  • 在沒有Spring Boot之前,Spring Security的大部分配置要通過XML實現,配置還是還是非常複雜的。但是有了 Spring Boot之後,這一情況已經得到顯著改善。
  • Spring Security之所以看上去比shiro更複雜,其實是因為它引入了一些不常用的概念與規則。大家應該都知道2/8法則,這在Spring Security裏面體現的特別明顯,如果你只學Spring Security最重要的那20%,這20%的複雜度和shiro基本是一致的。也就是說,不重要的那80%,恰恰是Spring Security比shiro的“複雜度”。

也就是說,如果有人能幫你把Spring Security最重要的那20%摘出來,二者的入門門檻、複雜度其實是差不太多的。

2.3.社區支持

Spring Security依託於Spring龐大的社區支持,這點自不必多說。shiro屬於apache社區,因為它的廣泛使用,文檔也非常的全面。二者從社區支持來看,幾乎不相上下。

但是從社區發展的角度看,Spring Security明顯更佔優勢,隨着Spring Cloud、Spring Boot、Spring Social的長足進步,這種優勢會越來越大。因為Spring Security畢竟是Spring的親兒子,Spring Security未來在於Spring系列框架集成的時候一定會有更好的融合性,前瞻性、兼容性!這也是為什麼我們要學Spring Security的主要原因!

2.4.功能豐富性

Spring Security因為它的複雜,所以從功能的豐富性的角度更勝一籌。其中比較典型的如:

  • Spring Security默認含有對OAuth2.0的支持,與Spring Social一起使用完成社交媒體登錄也比較方便。shiro在這方面只能靠自己寫代碼實現。
  • 還有一種普遍說法:Spring Security在網絡安全的方面下的功夫更多,但是筆者並未有非常直接的感受,有可能出現安全問題的時候才會感到不夠安全的痛。

三、總結

如果你只是想實現一個簡單的web應用,shiro更加的輕量級,學習成本也更低。如果您正在開發一個分佈式的、微服務的、或者與Spring Cloud系列框架深度集成的項目,筆者還是建議您使用Spring Security。

期待您的關注

  • 博主最近新寫了一本書:
  • 本文轉載註明出處(必須帶連接,不能只轉文字):。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

【運維】記一次上線前的緊急定位與修復-獻上九條小經驗

1 簡介

本文介紹了作者所在團隊在某次上線前測試發現問題、定位問題並修復上線的過程,最後給出幾點經驗總結,希望對大家有用。

2 過程

(1)今天需要上線,但昨晚才合併了所有分支,時間很緊迫。不幸的是,打包測試后發現有一個Springboot應用(模塊R)啟動失敗,但進程沒有死,一直在輸出報錯日誌

(2)Google了相關的報錯日誌,並沒有找到相關信息。查看了模塊R的代碼變更,並沒有什麼改動,以為是環境問題;部署到其它環境后,發現問題依舊存在,而且這個問題從未出現過,基本排除環境問題,問題還是出在代碼上。

(3)啟動模塊R上一個版本(現生產環境)的代碼,正常啟動。所以問題還是出現模塊R的改動上。

(4)對比模塊R的發布包的新版本與生產版本的差異,發現第三方依賴包都一致,但自己項目的依賴包不同。

(5)想到一個有效的辦法,依次用生產版本替換掉自己項目的包,最終定位了問題出在通用模塊D上。

(6)查看模塊D的代碼變更記錄,改動比較大,比較難發現是哪裡的改動造成的。

(7)重新看日誌。為何要重看呢?並不是心血來潮,主要是想找關聯。既然已經知道了問題在哪個模塊代碼上,通過查看日誌與該模塊可能相關的信息,或許能找到蛛絲馬跡。

(8)果然!!!重新查看日誌發現,模塊R啟動時,報了一個其它錯誤ErrorA,但被後面不斷重複出現的錯誤ErrorB刷掉了,所以一開始並沒有注意到它。通過該報錯,與模塊D的代碼改動對比。終於定位出了問題!

(9)創建hotfix分支,修改代碼提交,重新merge,打包,測試通過,部署生產!!!

因為部署上線是有特定的時間窗口的,如果錯過了時間,就要下次再上線,還好及時定位,及時解決!

3 經驗總結

(1)不要放過任何日誌,特別是報錯的日誌,日誌是極其有用的。不要只看最後面的報錯,也不要只看最前面的報錯,任何報錯都可能提供新的方向和線索。如果日誌信息不夠,可以嘗試打開debug模式,會有大量的日誌信息,當然也要求你有足夠強的過濾和整理信息的能力。

(2)提取有用日誌,可以用greptailless等linux命令。

(3)組件化、模塊化很重要,能快速縮小問題範圍。能通過只回退某個模塊實現部分功能先上線。

(4)善用對比工具,如diff命令,BeyondCompare軟件等。

(5)善用代碼變更記錄,這是版本控制給我們帶來的好處,可以方便我們對比代碼改動了什麼,什麼時候改的,能加速問題定位;也能及時回退代碼。

(6)上線前要做充分的測試。這次問題的出現項目流程上的原因在於沒有進行充分的測試。(1)寫代碼的人修改了通用模塊,卻沒有測試依賴它的其它模塊的功能會不會受影響,而只測試了自己那一部分;(2)合併代碼后,沒有足夠的時間來進行測試。部署前一天,才合併了代碼打包測試。所以時間非常緊迫,在短時間要定位問題並解決,容易造成壓力。

(7)要有獨立的測試環境。這個是導致方向性錯誤的原因,經過是這樣的:A同學打包了自己的分支,這時剛好B同學稍晚一點也打包了分支,而打包的環境只有一個,B同學的包覆蓋了A同學的包。所以在A部署的時候,實際用了B同學的代碼打的包,導致啟動失敗。所以一直以為是A同學代碼的問題,這個方向性的錯誤浪費了很多時間。應該要讓每個分支可以同時打包,但不會覆蓋。

(8)不要先入為主。不要過早認定某個模塊就是有問題的,請參考上一條。

(9)團隊作戰,分工合作。整個過程全靠團隊一起協作才能快速定位並解決;打造一個開放包容、溝通順暢的團隊是多麼的重要。

If You Want to Go Fast, Go Alone. If You Want to Go Far, Go Together.

4 最後

運維和問題定位的知識很多,也非常重要,需要持續學習。本文僅講述了本次過程用到的方法。更多的知識以後慢慢再介紹…

歡迎關注公眾號<南瓜慢說>,將持續為你更新…

多讀書,多分享;多寫作,多整理。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

算法核心——空間複雜度和時間複雜度超詳細解析

算法核心——空間複雜度和時間複雜度超詳細解析

一、什麼是算法

算法

  • 一個有限指令集
  • 接受一些輸入(有些情況下不需要收入)
  • 產生輸出
  • 一定在有限步驟之後終止
  • 每一條指令必須:
  1. 有充分明確的目標,不可以有歧義
  2. 計算機能處理的範圍之內
  3. 描述應不依賴於任何一種計算機語言以及具體的實現手段

其實說白了,算法就是一個計算過程解決問題的方法。我們現在已經知道數據結構表示數據是怎麼存儲的,而“程序=數據結構+算法”,數據結構是靜態的,算法是動態的,它們加起來就是程序

對算法來說有輸入,有輸出,相當於函數參數返回值。我們寫算法的時候習慣把算法封裝到一個函數中。

二、什麼是好的算法

好,從上面我們知道了什麼是算法,下面我再說什麼是好的算法
在解決同一個問題的時候,我們通常會有很多種不一樣的算法,區別就在於,有的算法比較笨,有的算法比較聰明,那我們怎麼去衡量它們誰好誰壞呢?我們通常有下面兩個指標:

  • 空間複雜度:根據算法寫成的程序在執行時佔用存儲單元的長度。
  • 時間複雜度:根據算法寫成的程序在執行時耗費時間的長度。

先舉個例子說,如果讓你打印十個整數,你那個程序可能瞬間就給出結果了,如果讓你打印十萬個整數呢?這你就得多等一會了。所以這個程序運行的時間,就跟你要處理的數據是十個還是十萬個是相關的,這個十萬就是我們要處理的數據的規模。我們把它叫做n,是一個變量的話,那我們這個程序所用的時間空間都跟這個n是有直接關係的。解決一個問題有很多中不同的方法,你在設計這個方法的時候,一定要把這兩個要素考慮清楚。一不小心,如果空間複雜度太大的話,你那個程序就可能直接爆掉了,非正常中斷,我一會會在後面講,時間複雜度如果太大的話,你就可能等很長時間都等不出結果。

時間複雜度

先來看上面圖片中的幾組代碼,我是用Python表示的,你在看的時候考慮兩個問題:

 

  1. 四組代碼中,哪組的運行時間最短?
  2. 用什麼方式來體現算法運行的快慢?

剛才說n可以看作數據的規模,規模不一樣,運行時間肯定也不一樣,而且所用時間也不好確定,不同的n會得到不同的時間,所以我們用時間複雜度來表示算法運行的快慢。
先來看下面圖片中的幾個生活中的事件,估計時間:

這裏你會發現我們會用“”表示一個大概,後面還有相應的時間單位,那時間複雜度也參照類似的方法:
時間複雜度:用來評估算法運行效率的一個式子

看上面圖片所示,先說print(‘Hello World’),它的時間複雜度表示為O(1),O嚴格來說,它表示數學上一個式子的上界,我們可以簡單的理解為就是一個估計,大約,相當於上面說的“”。1可以理解為是個運行單位(類似於秒這樣的單位),為什麼是O(1),因為print(‘Hello World’)只執行了一次,同理分析第二個:

 

for i in range(n):
    print('Hello World')

它的時間複雜度表示為O(n),因為這組代碼執行了n次。n還是個單位,同理,分析第三個:

for i in range(n):
    for j in range(n):
        print('Hello World')

它的時間複雜度表示為O(),因為是有兩層循環,所以是,還是個單位。第四個你自己就可以分析了,我就不多此一舉了。但千萬不要以為就是這麼簡單,咱再看下面代碼圖片:

看到這個圖片,你是不是感覺很良好,和你猜的差不多是吧,哈哈,不要高興的太早,告訴你們,錯了,它們的時間複雜度不是這樣的。
為什麼?我說了,“1”是單位,但“3”不是單位,3是3乘1,就比如說在生活中,問你一壺水燒多長時間,沒有人回答說是三個幾分鐘或者幾個三分鐘。再說第二個,是單位,n也是個單位,但是比n大,所以我們在估計時用大單位,就好比生活中問你大概睡了多久,你一般說是幾個小時,而不是說幾個小時零幾分鐘,你強調的是一個大概的時間,明白了吧。
所以正確的時間複雜度是這樣的:

第一個為什麼是O(1),首先print(‘Hello World’)打印一次和打印三次實際的影響不大吧,就是不管執行幾次,只要它的規模不上升到n這麼大的時候,換句話說,1是個單位,所以不管怎樣,因為這是表示近似,不是表示精確的,所以是O(1).好,再看下面這個圖片:

當你的循環減半的時候,時間複雜度就會變為O(logn)。所以你可以這樣記,當算法過程出現循環折半的時候,複雜度式子中會出現logn。

 

時間複雜度小結

  • 時間複雜度是用來估計算法運行時間的一個式子(單位)
  • 一般來說,時間複雜度高的算法比時間複雜度低的算法慢
常見的時間複雜度(按效率排序)

複雜問題的時間複雜度

如何簡單快速地判斷算法複雜度

空間複雜度

在空間複雜度中需要注意的一點就是理解“空間換時間”,在研究一個算法的時候,時間比空間重要。

 

此篇完

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

javascript中判斷數據類型

編寫javascript代碼的時候常常要判斷變量,字面量的類型,可以用typeof,instanceof,Array.isArray(),等方法,究竟哪一種最方便,最實用,最省心呢?本問探討這個問題。

1. typeof

1.1 語法

typeof返回一個字符串,表示未經計算的操作數的類型。

語法:typeof(operand) | typeof operand
參數:一個表示對象或原始值的表達式,其類型將被返回
描述:typeof可能返回的值如下:

類型 結果
Undefined “undefined”
Null “object”
Boolean “boolean”
Number “number”
Bigint “bigint”
String “string”
Symbol “symbol”
宿主對象(由JS環境提供) 取決於具體實現
Function對象 “function”
其他任何對象 “object”

從定義和描述上來看,這個語法可以判斷出很多的數據類型,但是仔細觀察,typeof null居然返回的是“object”,讓人摸不着頭腦,下面會具體介紹,先看看這個效果:

    // 數值
    console.log(typeof 37) // number
    console.log(typeof 3.14) // number
    console.log(typeof(42)) // number
    console.log(typeof Math.LN2) // number
    console.log(typeof Infinity) // number
    console.log(typeof NaN) // number 儘管它是Not-A-Number的縮寫,實際NaN是数字計算得到的結果,或者將其他類型變量轉化成数字失敗的結果
    console.log(Number(1)) //number Number(1)構造函數會把參數解析成字面量
    console.log(typeof 42n) //bigint
    // 字符串
    console.log(typeof '') //string
    console.log(typeof 'boo') // string
    console.log(typeof `template literal`) // string
    console.log(typeof '1') //string 內容為数字的字符串仍然是字符串
    console.log(typeof(typeof 1)) //string,typeof總是返回一個字符串
    console.log(typeof String(1)) //string String將任意值轉換成字符串
    // 布爾值
    console.log(typeof true) // boolean
    console.log(typeof false) // boolean
    console.log(typeof Boolean(1)) // boolean Boolean會基於參數是真值還是虛值進行轉換
    console.log(typeof !!(1)) // boolean 兩次調用!!操作想短語Boolean()
    // Undefined
    console.log(typeof undefined) // undefined
    console.log(typeof declaredButUndefinedVariabl) // 未賦值的變量返回undefined
    console.log(typeof undeclaredVariable ) // 未定義的變量返回undefined
    // 對象
    console.log(typeof {a: 1}) //object
    console.log(typeof new Date()) //object
    console.log(typeof /s/) // 正則表達式返回object
    // 下面的例子令人迷惑,非常危險,沒有用處,應避免使用,new操作符返回的實例都是對象
    console.log(typeof new Boolean(true)) // object
    console.log(typeof new Number(1)) // object
    console.log(typeof new String('abc')) // object
    // 函數
    console.log(typeof function () {}) // function
    console.log(typeof class C { }) // function
    console.log(typeof Math.sin) // function 

1.2 迷之null

javascript誕生以來,typeof null都是返回‘object’的,這個是因為javascript中的值由兩部分組成,一部分是表示類型的標籤,另一部分是表示實際的值。對象類型的值類型標籤是0,不巧的是null表示空指針,它的類型標籤也被設計成0,於是就有這個typeof null === ‘object’這個‘惡魔之子’。

曾經有ECMAScript提案讓typeof null返回‘null’,但是該提案被拒絕了。

1.3 使用new操作符

除Function之外所有構造函數的類型都是‘object’,如下:

    var str = new String('String');
    var num = new Number(100)
    console.log(typeof str) // object
    console.log(typeof num) // object
    var func = new Function()
    console.log(typeof func) // function 

1.4 語法中的括號

typeof運算的優先級要高於“+”操作,但是低於圓括號

    var iData = 99
    console.log(typeof iData + ' Wisen') // number Wisen
    console.log(typeof (iData + 'Wisen')) // string 

1.5 判斷正則表達式的兼容性問題

typeof /s/ === 'function'; // Chrome 1-12 , 不符合 ECMAScript 5.1
typeof /s/ === 'object'; // Firefox 5+ , 符合 ECMAScript 5.1 

1.6 錯誤

ECMAScript 2015之前,typeof總能保證對任何所給的操作數都返回一個字符串,即使是沒有聲明,沒有賦值的標示符,typeof也能返回undefined,也就是說使用typeof永遠不會報錯。

但是ES6中加入了塊級作用域以及let,const命令之後,在變量聲明之前使用由let,const聲明的變量都會拋出一個ReferenceError錯誤,塊級作用域變量在塊的頭部到聲明變量之間是“暫時性死區”,在這期間訪問變量會拋出錯誤。如下:

    console.log(typeof undeclaredVariable) // 'undefined'
    console.log(typeof newLetVariable) // ReferenceError
    console.log(typeof newConstVariable) // ReferenceError
    console.log(typeof newClass) // ReferenceError

    let newLetVariable
    const newConstVariable = 'hello'
    class newClass{} 

1.7 例外

當前所有瀏覽器都暴露一個類型為undefined的非標準宿主對象document.all。typeof document.all === ‘undefined’。景觀規範允許為非標準的外來對象自定義類型標籤,單要求這些類型標籤與已有的不同,document.all的類型標籤為undefined的例子在web領域被歸類為對原ECMA javascript標準的“故意侵犯”,可能就是瀏覽器的惡作劇。

總結:typeof返回變量或者值的類型標籤,雖然對大部分類型都能返回正確結果,但是對null,構造函數實例,正則表達式這三種不太理想。 

2. instanceof

2.1 語法

instanceof運算符用於檢測實例對象(參數)的原型鏈上是否出現構造函數的prototype。

語法:object instanceof constructor
參數:object 某個實例對象
          constructor 某個構造函數
描述:instanceof運算符用來檢測constructor.property是否存在於參數object的原型鏈上。

// 定義構造函數
    function C() {
    }
    function D() {
    }
    var o = new C()
    console.log(o instanceof C) //true,因為Object.getPrototypeOf(0) === C.prototype
    console.log(o instanceof D) //false,D.prototype不在o的原型鏈上
    console.log(o instanceof Object) //true 同上

    C.prototype = {}
    var o2 = new C()
    console.log(o2 instanceof C) // true
    console.log(o instanceof C) // false C.prototype指向了一個空對象,這個空對象不在o的原型鏈上
    D.prototype = new C() // 繼承
    var o3 = new D()
    console.log(o3 instanceof D) // true
    console.log(o3 instanceof C) // true C.prototype現在在o3的原型鏈上

需要注意的是,如果表達式obj instanceof Foo返回true,則並不意味着該表達式會永遠返回true,應為Foo.prototype屬性的值可能被修改,修改之後的值可能不在obj的原型鏈上,這時表達式的值就是false了。另外一種情況,改變obj的原型鏈的情況,雖然在當前ES規範中,只能讀取對象的原型而不能修改它,但是藉助非標準的__proto__偽屬性,是可以修改的,比如執行obj.__proto__ = {}后,obj instanceof Foo就返回false了。此外ES6中Object.setPrototypeOf(),Reflect.setPrototypeOf()都可以修改對象的原型。

instanceof和多全局對象(多個iframe或多個window之間的交互)

瀏覽器中,javascript腳本可能需要在多個窗口之間交互。多個窗口意味着多個全局環境,不同全局環境擁有不同的全局對象,從而擁有不同的內置構造函數。這可能會引發一些問題。例如表達式[] instanceof window.frames[0].Array會返回false,因為Array.prototype !== window.frames[0].Array.prototype。

起初,這樣可能沒有意義,但是當在腳本中處理多個frame或多個window以及通過函數將對象從一個窗口傳遞到另一個窗口時,這就是一個非常有意義的話題。實際上,可以通過Array.isArray(myObj)或者Object.prototype.toString.call(myObj) = “[object Array]”來安全的檢測傳過來的對象是否是一個數組。

2.2 示例

String對象和Date對象都屬於Object類型(它們都由Object派生出來)。

但是,使用對象文字符號創建的對象在這裡是一個例外,雖然原型未定義,但是instanceof of Object返回true。

    var simpleStr = "This is a simple string";
    var myString  = new String();
    var newStr    = new String("String created with constructor");
    var myDate    = new Date();
    var myObj     = {};
    var myNonObj  = Object.create(null);

    console.log(simpleStr instanceof String); // 返回 false,雖然String.prototype在simpleStr的原型鏈上,但是後者是字面量,不是對象
    console.log(myString  instanceof String); // 返回 true
    console.log(newStr    instanceof String); // 返回 true
    console.log(myString  instanceof Object); // 返回 true

    console.log(myObj instanceof Object);    // 返回 true, 儘管原型沒有定義
    console.log(({})  instanceof Object);    // 返回 true, 同上
    console.log(myNonObj instanceof Object); // 返回 false, 一種創建非 Object 實例的對象的方法

    console.log(myString instanceof Date); //返回 false

    console.log( myDate instanceof Date);     // 返回 true
    console.log(myDate instanceof Object);   // 返回 true
    console.log(myDate instanceof String);   // 返回 false 

注意:instanceof運算符的左邊必須是一個對象,像”string” instanceof String,true instanceof Boolean這樣的字面量都會返回false。

下面代碼創建了一個類型Car,以及該類型的對象實例mycar,instanceof運算符表明了這個myca對象既屬於Car類型,又屬於Object類型。

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
var mycar = new Car("Honda", "Accord", 1998);
var a = mycar instanceof Car;    // 返回 true
var b = mycar instanceof Object; // 返回 true 

不是…的實例

要檢測對象不是某個構造函數的實例時,可以使用!運算符,例如if(!(mycar instanceof Car))

instanceof雖然能夠判斷出對象的類型,但是必須要求這個參數是一個對象,簡單類型的變量,字面量就不行了,很顯然,這在實際編碼中也是不夠實用。

總結:obj instanceof constructor雖然能判斷出對象的原型鏈上是否有構造函數的原型,但是只能判斷出對象類型變量,字面量是判斷不出的。

3. Object.prototype.toString()

3.1. 語法

toString()方法返回一個表示該對象的字符串。

語法:obj.toString()
返回值:一個表示該對象的字符串
描述:每個對象都有一個toString()方法,該對象被表示為一個文本字符串時,或一個對象以預期的字符串方式引用時自動調用。默認情況下,toString()方法被每個Object對象繼承,如果此方法在自定義對象中未被覆蓋,toString()返回“[object type]”,其中type是對象的類型,看下面代碼:

    var o = new Object();
    console.log(o.toString()); // returns [object Object] 

注意:如ECMAScript 5和隨後的Errata中所定義,從javascript1.8.5開始,toString()調用null返回[object, Null],undefined返回[object Undefined]

3.2. 示例

覆蓋默認的toString()方法

可以自定義一個方法,來覆蓋默認的toString()方法,該toString()方法不能傳入參數,並且必須返回一個字符串,自定義的toString()方法可以是任何我們需要的值,但如果帶有相關的信息,將變得非常有用。

下面代碼中定義Dog對象類型,並在構造函數原型上覆蓋toString()方法,返回一個有實際意義的字符串,描述當前dog的姓名,顏色,性別,飼養員等信息。

function Dog(name,breed,color,sex) {
        this.name = name;
        this.breed = breed;
        this.color = color;
        this.sex = sex;
    }
    Dog.prototype.toString = function dogToString() {
        return "Dog " + this.name + " is a " + this.sex + " " + this.color + " " + this.breed
    }

    var theDog = new Dog("Gabby", "Lab", "chocolate", "female");
    console.log(theDog.toString()) //Dog Gabby is a female chocolate Lab 

4. 使用toString()檢測數據類型

目前來看toString()方法能夠基本滿足javascript數據類型的檢測需求,可以通過toString()來檢測每個對象的類型。為了每個對象都能通過Object.prototype.toString()來檢測,需要以Function.prototype.call()或者Function.prototype.apply()的形式來檢測,傳入要檢測的對象或變量作為第一個參數,返回一個字符串”[object type]”。

    // null undefined
    console.log(Object.prototype.toString.call(null)) //[object Null] 很給力
    console.log(Object.prototype.toString.call(undefined)) //[object Undefined] 很給力

    // Number
    console.log(Object.prototype.toString.call(Infinity)) //[object Number]
    console.log(Object.prototype.toString.call(Number.MAX_SAFE_INTEGER)) //[object Number]
    console.log(Object.prototype.toString.call(NaN)) //[object Number],NaN一般是数字運算得到的結果,返回Number還算可以接受
    console.log(Object.prototype.toString.call(1)) //[object Number]
    var n = 100
    console.log(Object.prototype.toString.call(n)) //[object Number]
    console.log(Object.prototype.toString.call(0)) // [object Number]
    console.log(Object.prototype.toString.call(Number(1))) //[object Number] 很給力
    console.log(Object.prototype.toString.call(new Number(1))) //[object Number] 很給力
    console.log(Object.prototype.toString.call('1')) //[object String]
    console.log(Object.prototype.toString.call(new String('2'))) // [object String]

    // Boolean
    console.log(Object.prototype.toString.call(true)) // [object Boolean]
    console.log(Object.prototype.toString.call(new Boolean(1))) //[object Boolean]

    // Array
    console.log(Object.prototype.toString.call(new Array(1))) // [object Array]
    console.log(Object.prototype.toString.call([])) // [object Array]

    // Object
    console.log(Object.prototype.toString.call(new Object())) // [object Object]
    function foo() {}
    let a = new foo()
    console.log(Object.prototype.toString.call(a)) // [object Object]

    // Function
    console.log(Object.prototype.toString.call(Math.floor)) //[object Function]
    console.log(Object.prototype.toString.call(foo)) //[object Function]

    // Symbol
    console.log(Object.prototype.toString.call(Symbol('222'))) //[object Symbol]

    // RegExp
    console.log(Object.prototype.toString.call(/sss/)) //[object RegExp] 

上面的結果,除了NaN返回Number稍微有點差池之外其他的都返回了意料之中的結果,都能滿足實際開發的需求,於是我們可以寫一個通用的函數來檢測變量,字面量的類型。如下:

    let Type = (function () {
        let type = {};
        let typeArr = ['String', 'Object', 'Number', 'Array', 'Undefined', 'Function', 'Null', 'Symbol', 'Boolean', 'RegExp', 'BigInt'];
        for (let i = 0; i < typeArr.length; i++) {
            (function (name) {
                type['is' + name] = function (obj) {
                    return Object.prototype.toString.call(obj) === '[object ' + name + ']'
                }
            })(typeArr[i])
        }
        return type
    })()
    let s = true
    console.log(Type.isBoolean(s)) // true
    console.log(Type.isRegExp(/22/)) // true 

除了能檢測ECMAScript規定的八種數據類型(七種原始類型,BooleanNullUndefinedNumberBigIntStringSymbol,一種複合類型Object)之外,還能檢測出正則表達式RegExpFunction這兩種類型,基本上能滿足開發中的判斷數據類型需求。

5. 判斷相等

既然說道這裏,不妨說一說另一個開發中常見的問題,判斷一個變量是否等於一個值。ES5中比較兩個值是否相等,可以使用相等運算符(==),嚴格相等運算符(===),但它們都有缺點,== 會將‘4’轉換成4,後者NaN不等於自身,以及+0 !=== -0。ES6中提出”Same-value equality“(同值相等)算法,用來解決這個問題。Object.is就是部署這個算法的新方法,它用來比較兩個值是否嚴格相等,與嚴格比較運算(===)行為基本一致。

    console.log(5 == '5') // true
    console.log(NaN == NaN) // false
    console.log(+0 == -0) // true
    console.log({} == {}) // false

    console.log(5 === '5') // false
    console.log(NaN === NaN) // false
    console.log(+0 === -0) // true
    console.log({} === {}) // false

Object.js()不同之處有兩處,一是+0不等於-0,而是NaN等於自身,如下:

    let a = {}
    let b = {}
    let c = b
    console.log(a === b) // false
    console.log(b === c) // true
    console.log(Object.is(b, c)) // true 

注意兩個空對象不能判斷相等,除非是將一個對象賦值給另外一個變量,對象類型的變量是一個指針,比較的也是這個指針,而不是對象內部屬性,對象原型等。

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?