1. 程式人生 > >[Android 之美] 那些你不知道的APK 瘦身,讓你的APK更小

[Android 之美] 那些你不知道的APK 瘦身,讓你的APK更小

[Android 之美] APK 瘦身,減少APK的大小

讓我們的apk檔案儘可能更小,移除那些未使用的程式碼和資原始檔。本章節介紹瞭如何做到讓APK更小,效能更好,下載轉化率會更高,以及如何指定在構建APK過程中保留或移除專案中的程式碼和資源,在我們還沒有分析APK大小之前,專案中存在一些資源放置處理不當,沒有統一的規範,依賴管理不合理,資源重疊,dex方法數過多、檔案過大等問題,導致整個APK檔案也比較大,對於下載轉化率必然有一定的影響。
那麼公司要求我們的產品APK體積大小要優化到3M左右。經過我們的努力終於達到要求,然而我們發現還能再小。

分析APK的大小

古人云:工欲善其事,必先利其器,我們得先有利器,下面就是我們常用的分析APK大小工具的利器做一些簡單的介紹和使用,幫助我們分析造成APK體積較大的元凶,以便於我們從那些方面入手優化。

使用Android Studio 2.2

Android Studio 2.2 新功能直接能分析APK的大小,雙擊開啟就能看到那些佔用APK比例大,方法數等。

這裡寫圖片描述

  • 分析任何的APK
  • 檢視APK下載包的大小,解壓後的實際大小
  • 反編譯資原始檔,還原layout中的資源id,程式碼
  • 分析dex,顯示每部分的方法數,直接檢視那些library體積比較大

使用方法:Build -> Analyz APK

有了Analyz APK這個利器,以下工具也可以基本不用了

NimbleDroid

NimbleDroid 是美國哥倫比亞大學的博士創業團隊研發出來的自動化分析Android app效能指標的系統,分析的方式有靜態和動態兩種方式,其中靜態分析可以分析出APK安裝包中大檔案排行榜,各種知名SDK的大小以及佔程式碼整體的比例,各種型別檔案的大小以及佔排行,各種知名SDK的方法數以及佔所有dex中方法數的比例,針對緩慢的方法,緩慢的第三方SDK和記憶體洩漏。
測量生成的速度、網路、記憶體和磁碟使用率。總之有非常多分析App效能的功能,如果要做效能優化,也可以嘗試使用

NimbleDroid

檢視詳細的方法耗時

ClassShark

ClassShark 是一款檢視Android執行檔案(apk)的瀏覽工具,目前有兩個android App(Apk)和桌面(jar)的版本。
使用這款工具,可以很方便的開啟APK/Class/Jar/res
等 檔案和分析裡面的內容。

通過以上任一工具分析我們知道我們專案中主要是以下檔案佔用APK大小:

  • classes.dex
    classes.dex是java原始碼編譯後生成的java位元組碼檔案,

  • res
    主要是存放我們的圖片資源

  • resources.arsc
    編譯後的二進位制資原始檔,非常多無效資原始檔(語言)

  • assets
    主要存放了我們的快取資料檔案,已做最優化壓縮,我們考慮能否雲端存放。

  • lib
    主要是存放我們的so庫,目前我們已經優化了

既然知道了那些資料導致我們APK體積大,那麼我們就著手瘦身了。

對APK進行瘦身

對資源進行極限壓縮

對資源進行極限壓縮,主要是對如:res裡面用到的圖片資原始檔和assets資料夾下的一些html,db等一些快取預留在APK的資料檔案

  • assets資源壓縮,使用7zip或者lzma壓縮方式最高,把檔案打包壓縮
  • res 圖片資源的壓縮,使用tinypng優化Android的資源圖片,通常我們可以在保證圖片不失真的情況下,多壓縮幾次。目前tinypng已經支援png和jpg圖片、.9圖的壓縮
  • 將非alpha的圖轉換成jpg形式

通過以上方法我們圖片降低了79%的大小。

使用WEBP,SVG圖片資源格式

  • WebP是谷歌研發出來的一種圖片資料格式,它是一種支援有失真壓縮和無失真壓縮的圖片檔案格式,如果應用支援到Android 4.0+,那麼我們可以使用WebP格式代替PNG,我們的資源大小能降低50%多。或者有些資源可以使用SVG圖片資源更小。
    以下是他們的對比圖:

這裡寫圖片描述

這裡提供方便轉換的WEBP資源的工具:

利用AndResGuard資源壓縮打包工具

微信中的資源混淆工具主要為了混淆資源ID長度(例如將res/drawable/icon.png,png變成混淆為r/s/a.png),同時利用7z深度壓縮、對png的儲存方式做了改變佔用記憶體更小,大大減少了安裝包體積

具體原始碼與使用方法詳細在github中:

清除你的程式碼和資源

通過上面的圖片資源極限壓縮能對APK減小不少,但這往往這些還是不夠的,專案裡還有很多未使用的資原始檔,重複的資源等,這裡主要參考Google官方文件https://developer.android.com/studio/build/shrink-code.html#shrink-code 部分,利用Android Plugin開啟gradle 的Code shrinkingProGuard結合使用。

  • ProGuard能夠檢測和刪除未使用的類,欄位,方法,和從你的打包應用程式的屬性,包括那些包含程式碼庫,ProGuard是一個混淆優化位元組碼的工具,能夠刪除一些未使用的程式碼,混淆使用的類,欄位,方法和短名稱,經過混淆處理也能夠使APK原始碼得到保護

  • Code shrinking是一個Android Plugin for Gradle,從您的打包的應用程式中刪除未使用的資源,包括程式碼庫中的未使用的資源。它工作在與程式碼縮小,這樣,一旦未使用的程式碼已被刪除,任何資源不再引用可以安全地刪除。

該功能需要依賴於:

  • SDK Tools 25.0.10 或更高
  • Android Plugin for Gradle 2.0.0 或更高

清除無用程式碼

code shrinking需要結合ProGuard使用,新增minifyEnabled true在你的build.gradle檔案中。

需要注意code shrinking會減慢Gradle 編譯,應避免使用它在您的除錯版本中使用它。Android Studio禁用ProGuard使用 Instant Run.。
例如,以下從build.gradle檔案片段,使code shrinking為釋出版本

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile(‘proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
    ...
}

其中getDefaultProguardFile(‘proguard-android.txt')預設ProGuard設定來自於Android SDK tools/proguard/中的資料夾

更多的減少程式碼可以嘗試使用相同位置的proguard-android-optimize.txt檔案(這樣能讓我們的APK又減少了0.5M以上)proguard-rules.pro是你自定義的proguard規則。

那麼我們怎麼知道每一次build,刪除了和未刪除那些資源和程式碼呢,ProGuard會輸出以下檔案在/build/outputs/mapping/release/:

  • dump.txt
    描述.apk檔案中所有類檔案間的內部結構
  • mapping.txt
    列出了原始的類,方法和欄位名與混淆後代碼間的對映。這個檔案很重要,當你從release版本中收到一個bug報告時,可以用它來翻譯被混淆的程式碼。
  • seeds.txt
    列出了未被混淆的類和成員
  • usage.txt
    列出了從.apk中刪除的程式碼
  • resources.txt
    列出resource被保留的資源
自定義混淆規則

在某些情況下,預設的混淆器配置檔案proguard-android.txt檔案是會移除所有隻有未使用的程式碼,但也有可能會誤刪除了你需要的程式碼,所以要注意以下幾種情況:

  • AndroidManifest.xml配置的檔案類
  • 使用了JNI 的介面方法
  • 執行時反射呼叫方法(不過現在ProGuard已經可以處理這種了)

新增-keep來忽略一下防止被混淆的程式碼到proguard-rules.pro檔案中,比如:

-keep public class MyClass

有關自定義proguard-rules.pro檔案的更多資訊,可以參考ProGuard Manual.這裡Troubleshooting列出了一些常見的問題。

清除無用的資原始檔

Resource shrinking 需要和Code shrinking 一起使用。在程式碼中刪除所有未使用的程式碼後,Resource shrinking才可以知道哪些資源APK程式仍然使用,你必須先刪除未使用的程式碼,Resource才會成為無用的,從而被清除掉。

新增shrinkResources true屬性在你的 build.gradle檔案中,相應程式碼塊如下:

android {
    ...
    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
}

resource shrinker 目前還不支援移除定義在values/目錄下的資原始檔(strings,dimensions,styles,colors),因為Android Asset Packaging Tool(AAPT)不允許Gradle Plugin指定預定義的版本資源[issue 70869]

指定要忽略的資原始檔

如果我們希望保留或丟棄特定的資源,需要在專案中建立一個XML檔案,並使用resources標籤,並指定每個資源儲存在工具中tools:keep和每個資源在工具中丟棄 tools:discard。兩個屬性都可以使用逗號(,)分隔符宣告資源名稱列表。也可以使用* 作為匹配符,匹配名稱。

相應程式碼塊如下:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
    tools:discard="@layout/unused2" />

需要在專案resources目錄儲存res/raw/keep.xml檔案,build的時候該檔案不會被打包到APK裡面。

啟用嚴格的檢測

通常情況下,resource shrinker可以準確地確定資源使用。如果你使用Resources.getIdentifier()動態獲取指定資源的Id,在預設情況下,這樣資源具有匹配名稱的格式為潛在的使用,無法去除。

例如,下面的程式碼將導致所有img_字首的資源都無法去除。


String name = String.format("img_%1d", angle + 1);
res = getResources().getIdentifier(name, "drawable", getPackageName());

resource shrinker 也通過搜尋程式碼中是否包含資源名來判斷是否在build的時候刪除。

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:shrinkMode="strict" />

在 resource 檔案中指定 shrinkMode,你可以指定 Gradle 在處理該資原始檔時候的方式,預設的值為 safe,你也可以將它指定為 strict(只會保留有明確引用的資源,以及處理被 tools:keeptools:discard 標註的資源)

在後面檢視資源回收情況,我們會講到,會遇到有些xml 無法被清除的問題,使用shrinkMode可以解決這個問題。

清除未使用的替代資源

Gradle resource shrinker 只刪除你在程式碼中未使用資源,這意味著它不會刪除不同的裝置配置的可替代資源。如果有必要,你可以使用Android Gradle pluginresconfigs屬性刪除替代資原始檔。

例如:我們專案中適配10種國家語言,而專案依賴了v7、v4等其他support包裡面包含20種國家語言,那麼我們可以通過resconfigs 刪除剩餘的可替代資原始檔,這對於我們APK大小可減少了不少,

以下程式碼說明了如何限制你的語言資源,只是英語和法語:

android {
    defaultConfig {
        ...
        resConfigs "en", "fr"
    }
}

像上面那樣通過resconfig屬性指定的語言。未指定的語言的任何資源都被刪除。

同樣的圖片資源我們也可以這麼做,例如:我們提供一套xxhdpi的圖片資源,其他的都過濾清除掉,這樣大量清除了support,其他第三方library的資原始檔,關於這個待會我們在後面會說。

合併重複的資源

預設情況下,Gradle也將同名的資源,比如相同的名字,可能是在不同的資原始檔夾下,這樣子不能通過shrinkResources屬性來去除。

只有當兩個或多個檔案共享相同的資源名稱、型別和限定符時才發生資源合併,關於資源的合併優先順序如下:

Gradle 主要從以下位置合併資源:

  • src/main/res/ 主要資源
  • Gradle 使用variant(build type 和 build flavors)
  • Library的依賴使用

Gradle合併重複資源優先順序為:

Dependencies → Main → Build flavor → Build type

例如:如果一個重複的資源在你的mian res中和一個Build flavor指定 ,Gradle 會優先選擇Build flavor

檢視資源回收

當你Gradle resource shrinker,Gradle Console 輸出日誌,移除APK資源的資訊。例如:

:android:shrinkDebugResources
Removed unused resources: Binary resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning

APK構建完成後會Gradle會生成一個resource.txt 在 /build/outputs/mapping/release/ 中,這個檔案包括詳細資訊,如資源參考其他資源和使用或刪除資源的詳細資訊等。

例如:找出為什麼@drawable/ic_plus_anim_016,仍然包含在你的APK中,在resource.txt 搜尋該檔名,你可能會發現它是被另一個資源引用,如下:

16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out]     @drawable/ic_plus_anim_016

現在需要知道為什麼@drawable/add_schedule_fab_icon_anim 仍然在使用,搜尋我們可以知道應該有程式碼引用著add_schedule_fab_icon_anim

如果你不使用嚴格的檢查(就是上面講的shrinkMode),同樣的我們如果我們在drawable中使用了字串’#FFFFFF‘ 這樣的使用resource shrinker也不能將他移除在APK中,通常我們可以在Gradle Console中看到以下資訊:

10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
    used because it format-string matches string pool constant ic_plus_anim_%1$d.

那麼這種情況我們如何解決呢,可以通過以下方法來清理:

  • 使用tools:discard,在 tools:shrinkMode=”strict” 的時候生效,指定某資原始檔需要刪除。在你確定該資原始檔無效的時候使用。
  • 利用Lint找出未使用的資源並清理掉

    在Android Studio中開啟“Analyze” 然後選擇”Inspect Code…”,範圍選擇整個專案,然後點選”OK”

到這裡APK的大小又小了不少。

使用APK Splits構建APK

雖然我們上面很好的使用了resource shrinker可以回收一些未使用的資源(v7、v4、google Service 等Libarry資源),但有些資源仍然未被清除。

例如:那些未使用的多套替代資源,或者是library內部隱患著引用著的資源而我們卻沒有使用到。或者是我們要根據使用者的手機去提供不同版本的APK,如解析度(xxhdpi,mhdpi等),so庫等。那麼我們可以使用APK Splits大大的減少一些無用的資源,這裡我們主要參考了http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits 文件。

APK Splits比起使用 flavors,能讓應用程式更有效地構建一些形式的多個apk。

多 apk 只支援以下型別:

  • 螢幕密度
  • ABI

使用新的APK Splits,構建同一個應用程式的hdpi版本和mdpi版本,能夠共享很多的任務 (如 javac,dx,proguard)。此外,它會被認為是一個單一的variant,並且同一個測試程式將會被用來測試每​​個多APK。

按螢幕密度拆分

android {
  ...
  splits {
    density {
      enable true
      exclude "ldpi", "tvdpi", "xxxhdpi"
      compatibleScreens 'small', 'normal', 'large', 'xlarge'
    }
  }
  • enable: 啟用螢幕密度拆分機制
  • exclude: 預設情況下所有螢幕密度都包括在內,你可以移除一些密度。
  • include: 表示要包括哪些螢幕密度
  • reset(): 重置螢幕密度列表為只包含一個空字串 (這能夠實現,在與include一起使用時可以表示使用哪一個螢幕密度,而不是要忽略哪一些螢幕密度)
  • compatibleScreens:表示相容螢幕的列表。這將會注入到manifest中匹配的 節點。這個設定是可選的。

構建完成後可以在out/apk/目錄下看到多個版本的APK

按 ABI 拆分

android {
  ...
  splits {
    abi {
      enable true
      reset()
      include 'x86', 'armeabi-v7a', 'mips'
      universalApk true
    }
  }
}
  • enable: 啟用ABI拆分機制
  • exclude: 預設情況下所有ABI都包括在內,你可以移除一些ABI。
  • include:指明要包含哪些ABI
  • reset():重置ABI列表為只包含一個空字串(這可以實現,在與include一起使用來可以表示要使用哪一個ABI,而不是要忽略哪一些ABI)
  • universalApk:指示是否打包一個通用版本(包含所有的ABI)。預設值為 false。

例如:我們專案主要提供xxhdpi的圖片資源,而專案中引用到了很多第三方庫(v7、v4、google Service 等Libarry資源)我們無法使用到,那麼我們可以通過這種方法來去除那些資源。這樣我們的APK又減小了非常多。

使用多版本的APK

Multiple APK Support是一個在Google Play,可以釋出不同的應用程式,分別針對不同的裝置配置特徵。每個APK是一個完整的、獨立的應用程式版本,但他們分享在Google Play相同的應用程式清單,必須共享相同的包名和與簽名。Google Play 會自動給你匹配相應的APK,這樣我們的APK 就可以是分不同版本構建需要資原始檔,從而減小APK的大小。

通過釋出有多個APK,我們可以:

目前我們基於這個方案做了不同螢幕的APK。

資源動態載入

我們可以在專案中使用資源動態載入形式,例如:表情,語言,離線庫等資源動態載入,減小APK的大小。

依賴庫優化

  • 如果應用支援的最低版本是API14,那就不要使用android support庫,或者分開使用android support庫,用哪個引入哪個庫(android-support-ui/android-support-core 等)雖然現在支援還不太好,Google servie 也是如此。
  • 使用更輕量級的庫代替,或者優化library的大小,不然自己寫更好。
  • 刪除armable-v7包下的so、刪除x86包下的so,基本上armable的so也是相容armable-v7的,armable-v7a的庫會對圖形渲染方面有很大的改進,不過最好的是根據上面我們說的提供多版本APK,對不同的平臺精簡,再或者動態的載入so。
  • 使用H5編寫介面,圖片雲端獲取
  • 資源快取庫不放在assets下,雲端獲取更新。

支援外掛化

未來對於一些獨立業務模組,可以做成外掛化動態載入,使用者需要使用時,只需下載少部分外掛。

使用ReDex優化

ReDex是Facebook開源一個減小安卓app大小以提高效能的工具,內嵌以及清除殭屍程式碼這樣的優化來減小位元組碼,主要是對Dex進行了優化,能讓APK 執行更快,不過需要多測試是否會崩潰。

關於APK瘦身我們就總結到這了,應該還有很多更好的方案,若有錯漏,歡迎補充。

Android 之美 從0到1

相關推薦

[Android ] 那些知道APK APK

[Android 之美] APK 瘦身,減少APK的大小 讓我們的apk檔案儘可能更小,移除那些未使用的程式碼和資原始檔。本章節介紹瞭如何做到讓APK更小,效能更好,下載轉化率會更高,以及如何指定在構建APK過程中保留或移除專案中的程式碼和資源,在我們還

【實用工具】這些不得不知道的chrome外掛事半功倍

平時chrome外掛用多了,發現在工作中有很多外掛特別好用,讓你事半功倍。於是我抽時間整理了一些非常好用的chrome外掛分享給大家,其中有些外掛是我已經離不開,每天都在用的。希望這篇文章能幫助你找到適合你的外掛,提升工作效率。 工作類 FeHelper【強烈推薦】 FeHelper是一個Web前端助手,由中

知道的JavaScript中讀書筆記

java symbol 內置 script null scrip ring obj 不知道 七種內置類型 null, undefined, boolean, number, string, object, symbol typeof null === ‘object‘ //

知道的騷操作有人上淘寶剁手有人去玩遊戲保護瀕危動物

雙11血拼大戰剛剛結束沒多久,身邊的剁手黨們又開始了新的征程——玩起了手淘裡的“野生小夥伴”。 這是一款手機淘寶最新上線的小遊戲。沉浸其中的網友,驚呼自己都要忙死了:除了剁手,還要每天種樹養雞養蛙養小象! 還有網友把小象養成了“大象”。看來,不光收包裹排前後,就連養野生動物都分快慢吶。瞧瞧人家的寶

Android XML shape 標籤使用詳解(apk減少記憶體好幫手)

Android XML shape 標籤使用詳解   一個android開發者肯定懂得使用 xml 定義一個 Drawable,比如定義一個 rect 或者 circle 作為一個 View 的背景。但是,也肯定也有人在能使用 Drawable 的地方選擇使用一

阿裏京東淘寶那些知道的事兒

大眾 商業 business 抽象 模式 運營 公司 銷售 tom B2B即business to business,2是to的諧音,即企業與企業之間,商家與商家之間,通過互聯網進行產品、服務及信息的交換。 交易的供需雙方都是商家(或企業、公司)。如:阿裏巴巴就是這種模式的

Android50個知道的使用竅門

今天給大家分享下安卓系統的安卓手機的使用技巧方法,以時下最為普遍最主流的Android 2.3系統為例,不過大部分使用技巧在其他版本的安卓系統上同樣適用。   1.使用Android電源管理widget從Android2.1系統開始內建了一個非常強大的帶能源管理widget

Android推送通知那些知道的細節

場景一:你的App接收到了多條推送訊息,但是要實現點選每條通知做不同的事情(如:傳過去不同的值 ),問題是怎麼判斷點選的是哪一條通知訊息呢? 解答: //第二個引數用來表示不同notification,一定要設定成變數,否則多條訊息只能實現相同操作。        

關於 Android N 那些知道的事兒

今年3月,Google 破天荒提前半年釋出了 Android N 開發者預覽版。當然,作為一個不合格的穀粉並沒有第一時間體驗安裝,因為至今仍然能夠回憶起來去年今日此門中(霧)興沖沖刷了 Android M Preview 的時候發現各種 Crash 就連微信也(

正則表達式知道的replace

執行 兩個 引擎 logs blog 學無止境 div 國慶節 另一個 我們都知道js內置類String提供了一個replace方法,可以把指定字符串替換為另一個字符串,他的基礎用法如下: 1 var str="hello world"; 2 3 var str=str

知道的HTTPHTTPS

發的 graph 實的 layer 這份 方式 發送 機構 加密 確保web安全的HTTPS   HTTPS=HTTP+ 加密 + 認證 + 完整性保護   1、加密:     1)通信的加密       所謂互聯網,是由能連通到全世界的網絡組成的。無論世界哪個角 落的服務

知道的HTTP首部字段一覽

warning erer 標記 字段 expec 已過期 gpo table 主體 一、HTTP/1.1 首部字段一覽   HTTP 首部字段根據實際用途被分為以下 4 種類型:   1、通用首部字段:請求報文和響應報文兩方都會使用的首部。 首部字段名 說明 Ca

css知道的元素隱藏

空間 hidden 產生 style ott 渲染 部分 div pre 前言:說到元素隱藏,大部分人會想到display:none和visbility:hidden;但是實際上關於元素隱藏還分多種情況,比如是否占據空間,隱藏之後是否可以觸發點擊事件等情況 css元素隱藏種

那些知道的PS大片攝影

mage ogr edi FQ dib cdn PE roc med 你以為這張照片是P出來的? 才不是! 人家是開個起重機吊著拍的! 而且沒有任何保護措施! 這樣的照片戰鬥民族的攝影師才敢這樣拍…要是在天朝這麽做估計都找不到模特… 這張照片出自烏茲

阿里資料庫十年變遷那些知道的二三事

第十個雙11即將來臨之際,阿里技術推出《十年牧碼記》系列,邀請參與歷年雙11備戰的核心技術大牛,一起回顧阿里技術的變遷。 今天,阿里資料庫事業部研究員張瑞,將為你講述雙11資料庫技術不為人知的故事。在零點交易數字一次次提升的背後,既是資料庫技術的一次次突破,也見證了阿里技術人永不言敗的精神,每一次化“不可能

盤點趙麗穎和馮紹峰官宣引爆微博知道那些事!

10月16日是趙麗穎的31歲生日,上午10時許,趙麗穎和馮紹峰一同在微博晒出了二人的結婚照,官宣正式結婚。致使微博幾度陷入癱瘓,其公佈訊息的“官宣體”更是引發了眾多媒體和個人的模仿。范冰冰的“我們體”,鹿晗的“大家好,給大家介紹一下,這是我的女朋友@”,我們不難發現,明星們簡單的一句話公開戀情方式總是會頻頻引

JavaScript知道的this

很重要的一句話 只有深諳了this,你才有可能用 JavaScript 建立類似谷歌地圖這樣大型的複雜應用 一、這篇文章出現的背景 1. this在我們開發過程中的重要性(開發場景) -- 通過一段程式碼簡單瞭解this 提供了一種更優雅的方式來隱式”傳遞”一個物件引用, 讓API

【JS】《知道的JavaScript》 物件

簡單基本型別(string、boolean、number、null、undefined)本身並不是物件,但是typeof null時會返回字串‘object’。但實際上,null本身是基本型別。 原理是這樣的。不同的物件在底層都表示二進位制,在js中二進位制前三位都為0的話會被判斷為object

iTutorGroup:雅思與託福知道那些

說起雅思和託福,很多人想到的就是出國留學,但是兩者具體的區別可能還有很多的人不是特別的瞭解。很多準備留學的人都會問,出國留學靠雅思還是託福,這兩個哪個更容易些,哪個適用的國家更多呢?那就由iTutorGroup來給各位普及一下雅思和託福的相關知識,幫助出國留學的同學做個考試參考。 一、雅思

Python那些事——知道的python的“獨門暗器”!

隨著近幾年人工智慧的流行,從而引發了一個程式語言的興起,我想說到這,大家應該都明白了這是什麼吧,沒錯它就是大名鼎鼎的——Python 對於python,我給大家總結了以下幾點: Python 是一個高層次的結合瞭解釋性、編譯性、互動性和麵向物件的指令碼語言。 Python 的設計具