整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          每日SQL自學知識點(第六天)—窗口函數全面滲透用法

          每日SQL自學知識點(第六天)—窗口函數全面滲透用法

          載自:www.cnblogs.com/lihaoyang/p/6756956.html


          開窗函數:在開窗函數出現之前存在著很多用 SQL 語句很難解決的問題,很多都要通過復雜的相關子查詢或者存儲過程來完成。為了解決這些問題,在 2003 年 ISO SQL 標準加入了開窗函數,開窗函數的使用使得這些經典的難題可以被輕松的解決。目前在 MSSQLServer、Oracle、DB2 等主流數據庫中都提供了對開窗函數的支持,不過非常遺憾的是 MYSQL 暫時還未對開窗函數給予支持。

          開窗函數簡介:與聚合函數一樣,開窗函數也是對行集組進行聚合計算,但是它不像普通聚合函數那樣每組只返回一個值,開窗函數可以為每組返回多個值,因為開窗函數所執行聚合計

          算的行集組是窗口。在 ISO SQL 規定了這樣的函數為開窗函數,在 Oracle 中則被稱為分析函數。

          數據表(Oracle):T_Person 表保存了人員信息,FName 字段為人員姓名,FCity 字段為人員所在的城市名,FAge 字段為人員年齡,FSalary 字段為人員工資

          CREATE TABLE T_Person (FName VARCHAR2(20),FCity VARCHAR2(20),FAge INT,FSalary INT)

          向 T_Person 表中插入一些演示數據:

          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Tom','BeiJing',20,3000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Tim','ChengDu',21,4000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Jim','BeiJing',22,3500);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Lily','London',21,2000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('John','NewYork',22,1000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('YaoMing','BeiJing',20,3000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Swing','London',22,2000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Guo','NewYork',20,2800);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('YuQian','BeiJing',24,8000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Ketty','London',25,8500);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Kitty','ChengDu',25,3000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Merry','BeiJing',23,3500);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Smith','ChengDu',30,3000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Bill','BeiJing',25,2000);
          INSERT INTO T_Person(FName,FCity,FAge,FSalary)
          VALUES('Jerry','NewYork',24,3300);

          select * from t_person:

          要計算所有人員的總數,我們可以執行下面的 SQL 語句:SELECT COUNT(*) FROM T_Person

          除了這種較簡單的使用方式,有時需要從不在聚合函數中的行中訪問這些聚合計算的值。比如我們想查詢每個工資小于 5000 元的員工信息(城市以及年齡),并且在每行中都顯示所有工資小于 5000 元的員工個數:

          select fname,
                 fcity,
                 fsalary,
                 (select count(*) from t_person where fsalary < 5000) 工資少于5000員工總數
            from t_person
           where fsalary < 5000

          雖然使用子查詢能夠解決這個問題,但是子查詢的使用非常麻煩,使用開窗函數則可以大大簡化實現,下面的 SQL 語句展示了如果使用開窗函數來實現同樣的效果

          select fname, fcity, fsalary, count(*) over() 工資小于5000員工數
            from t_person
           where fsalary < 5000

          可以看到與聚合函數不同的是,開窗函數在聚合函數后增加了一個 OVER 關鍵字。

          開窗函數格式: 函數名(列) OVER(選項)

          OVER 關鍵字表示把函數當成開窗函數而不是聚合函數。SQL 標準允許將所有聚合函數用做開窗函數,使用 OVER 關鍵字來區分這兩種用法。
          在上邊的例子中,開窗函數
          COUNT(*) OVER()對于查詢結果的每一行都返回所有符合條件的行的條數。OVER 關鍵字后的括號中還經常添加選項用以改變進行聚合運算的窗口范圍。如果 OVER 關鍵字后的括號中的選項為空,則開窗函數會對結果集中的所有行進行聚合運算。

          PARTITION BY 子句:

          開窗函數的 OVER 關鍵字后括號中的可以使用 PARTITION BY 子句來定義行的分區來供進行聚合計算。與 GROUP BY 子句不同,PARTITION BY 子句創建的分區是獨
          立于結果集的,創建的分區只是供進行聚合計算的,而且不同的開窗函數所創建的分區也不互相影響。下面的 SQL 語句用于
          顯示每一個人員的信息以及所屬城市的人員數

          select fname,fcity,fage,fsalary,count(*) over(partition by fcity) 所在城市人數 from t_person

          COUNT(*) OVER(PARTITION BY FCITY)表示對結果集按照FCITY進行分區,并且計算當前行所屬的組的聚合計算結果。比如對于FName等于 Tom的行,它所屬的城市是BeiJing,同
          屬于BeiJing的人員一共有6個,所以對于這一列的顯示結果為6。

          這就不需要先對fcity分組求和,然后再和t_person表連接查詢了,省事兒。

          在同一個SELECT語句中可以同時使用多個開窗函數,而且這些開窗函數并不會相互干
          擾。比如下面的SQL語句用于顯示每一個人員的信息、所屬城市的人員數以及同齡人的人數:

          --顯示每一個人員的信息、所屬城市的人員數以及同齡人的人數:
          select fname,
                 fcity,
                 fage,
                 fsalary,
                 count(*) over(partition by fcity) 所屬城市的人個數,
                 count(*) over(partition by fage) 同齡人個數
            from t_person

          ORDER BY子句:

          開窗函數中可以在OVER關鍵字后的選項中使用ORDER BY子句來指定排序規則,而且有的開窗函數還要求必須指定排序規則。使用ORDER BY子句可以對結果集按
          照指定的排序規則進行排序,并且
          在一個指定的范圍內進行聚合運算。ORDER BY子句的語法為:

          ORDER BY 字段名 RANGE|ROWS BETWEEN 邊界規則1 AND 邊界規則2

          RANGE表示按照值的范圍進行范圍的定義,而ROWS表示按照行的范圍進行范圍的定義;邊界規則的可取值見下表:

          “RANGE|ROWS BETWEEN 邊界規則1 AND 邊界規則2”部分用來定位聚合計算范圍,這個子句又被稱為定位框架。

          例子程序一:查詢從第一行到當前行的工資總和:

          select fname,
                 fcity,
                 fage,
                 fsalary,
                 sum(fsalary) over(order by fsalary rows between unbounded preceding and current row) 到當前行工資求和
            from t_person

          這里的開窗函數“SUM(FSalary) OVER(ORDER BY FSalary ROWS BETWEEN
          UNBOUNDED PRECEDING AND CURRENT ROW)”表示按照FSalary進行排序,然后計算從第
          一行(UNBOUNDED PRECEDING)到當前行(CURRENT ROW)的和,這樣的計算結果就是按照
          工資進行排序的工資值的累積和。

          “RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW”是開窗函數中最常使用的定位框架,為了簡化使用,如果使用的是這種定位框架,則可以省略定位框架聲明部分,
          也就是說上邊的sql可以簡化成:

          select fname,
                 fcity,
                 fage,
                 fsalary,
                 sum(fsalary) over(order by fsalary) 到當前行工資求和
            from t_person

          例子程序二:把例子程序一的row換成了range,是按照范圍進行定位的

          select fname,
                 fcity,
                 fage,
                 fsalary,
                 sum(fsalary) over(order by fsalary range between unbounded preceding and current row) 到當前行工資求和
            from t_person

          區別:

          這個SQL語句與例1中的SQL語句唯一不同的就是“ROWS”被替換成了“RANGE”?!癛OWS”
          是按照行數進行范圍定位的,而“RANGE”則是按照值范圍進行定位的,這兩個不同的定位方式
          主要用來處理并列排序的情況。比如 Lily、Swing、Bill這三個人的工資都是2000元,如果按照
          “ROWS”進行范圍定位,則計算從第一條到當前行的累積和,而如果 如果按照 “RANGE”進行
          范圍定位,則仍然計算從第一條到當前行的累積和,不過由于等于2000元的工資有三個人,所
          以計算的累積和為從第一條到2000元工資的人員結,所以對 Lily、Swing、Bill這三個人進行開
          窗函數聚合計算的時候得到的都是7000( “ 1000+2000+2000+2000 ”)。

          下邊這的估計不常用:

          例子程序三:

          SELECT FName,
                 FSalary,
                 SUM(FSalary) OVER(ORDER BY FSalary ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING)  前二后二和
            FROM T_Person;

          這里的開窗函數“SUM(FSalary) OVER(ORDER BY FSalary ROWS BETWEEN 2
          PRECEDING AND 2 FOLLOWING)”表示按照FSalary進行排序,然后計算從當前行前兩行(2
          PRECEDING)到當前行后兩行(2 FOLLOWING)的工資和,注意對于第一條和第二條而言它們
          的“前兩行”是不存在或者不完整的,因此計算的時候也是要按照前兩行是不存在或者不完整進
          行計算,同樣對于最后兩行數據而言它們的“后兩行”也不存在或者不完整的,同樣要進行類似
          的處理。

          例子程序四:

          SELECT FName, FSalary,
          SUM(FSalary) OVER(ORDER BY FSalary ROWS BETWEEN 1 FOLLOWING AND 3 FOLLOWING) 后面一到三之和
          FROM T_Person;

          這里的開窗函數“SUM(FSalary) OVER(ORDER BY FSalary ROWS BETWEEN 1
          FOLLOWING AND 3 FOLLOWING)”表示按照FSalary進行排序,然后計算從當前行后一行(1
          FOLLOWING)到后三行(3 FOLLOWING)的工資和。注意最后一行沒有后續行,其計算結果為
          空值NULL而非0。

          例子程序五:算工資排名

          SELECT FName, FSalary,
          COUNT(*) OVER(ORDER BY FSalary ROWS BETWEEN UNBOUNDED PRECEDING AND
          CURRENT ROW)
          FROM T_Person;

          這里的開窗函數“COUNT(*) OVER(ORDER BY FSalary RANGE BETWEEN UNBOUNDED
          PRECEDING AND CURRENT ROW)”表示按照FSalary進行排序,然后計算從第一行
          (UNBOUNDED PRECEDING)到當前行(CURRENT ROW)的人員的個數,這個可以看作是計算
          人員的工資水平排名。

          不再用ROWNUM 了 省事了。這個over簡寫就會出錯。

          例子程序6:結合max求到目前行的最大值

          SELECT FName, FSalary,FAge,
          MAX(FSalary) OVER(ORDER BY FAge) 此行之前最大值
          FROM T_Person;

          這里的開窗函數“MAX(FSalary) OVER(ORDER BY FAge)”是“MAX(FSalary)
          OVER(ORDER BY FAge RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)”
          的簡化寫法,它表示按照FSalary進行排序,然后計算從第一行(UNBOUNDED PRECEDING)
          到當前行(CURRENT ROW)的人員的最大工資值。

          例子程序6:over(partition by XX order by XX) partition by和order by 結合

          員工信息+同齡人最高工資,按工資排序

          SELECT FName, FSalary,FAge,
          MAX(FSalary) OVER(PARTITION BY FAge order by fsalary) 同齡人最高工資
          FROM T_Person;

          PARTITION BY子句和ORDER BY 可以 共 同 使用,從 而 可以 實現 更 加復 雜 的 功能
          ==================================================================================

          高級開窗函數/ 排名的實現ROW_NUMBER();rank() ,dense_rank()

          除了可以在開窗函數中使用COUNT()、SUM()、MIN()、MAX()、AVG()等這些聚合函數,
          還可以在開窗函數中使用一些高級的函數,有些函數同時被DB2和Oracle同時支持,比如
          RANK()、DENSE_RANK()、ROW_NUMBER(),而有些函數只被Oracle支持,比如
          RATIO_TO_REPORT()、NTILE()、LEAD()、LAG()、FIRST_VALUE()、LAST_VALUE()。
          下面對這幾個函數進行詳細介紹。

          RANK()和DENSE_RANK()函數都可以用于計算一行的排名,不過對于并列排名的處理方式
          不同;ROW_NUMBER()函數計算一行在結果集中的行號,同樣可以將其當成排名函數。這三個
          函數的功能存在一定的差異,舉例如下:工資從高到低排名:

          SELECT FName, FSalary,FAge,
          RANK() OVER(ORDER BY fsalary desc) f_RANK,
          DENSE_RANK() OVER(ORDER BY fsalary desc) f_DENSE_RANK,
          ROW_NUMBER() OVER(ORDER BY fsalary desc) f_ROW_NUMBER
          FROM T_Person;

          rank(),dense_rank()語法:

          RANK()
          dense_rank()
          【語法】RANK ( ) OVER ( [query_partition_clause] order_by_clause )
              dense_RANK ( ) OVER ( [query_partition_clause] order_by_clause )
          
          【功能】聚合函數RANK 和 dense_rank 主要的功能是計算一組數值中的排序值。
          【參數】dense_rank與rank()用法相當,
          【區別】dence_rank在并列關系是,相關等級不會跳過。rank則跳過
          rank()是跳躍排序,有兩個第二名時接下來就是第四名(同樣是在各個分組內) 
          dense_rank()l是連續排序,有兩個第二名時仍然跟著第三名。

          row_number() 函數語法:

          ROW_NUMBER()
          【語法】ROW_NUMBER() OVER (PARTITION BY COL1 ORDER BY COL2) 
          【功能】表示根據COL1分組,在分組內部根據 COL2排序,而這個值就表示每組內部排序后的順序編號(組內連續的唯一的) 
          row_number() 返回的主要是“行”的信息,并沒有排名
          【參數】
          【說明】Oracle分析函數
          
          主要功能:用于取前幾名,或者最后幾名等

          ===================================================================

          排序函數實際場景使用:計算排行榜,排名

          微信活動,每天參與,有得分,活動結束后選出排名靠前的發獎。

          每參與一次,就是一個訂單,表結構:

          比如要查詢期號issue為20170410期的排行榜,按得分倒敘排序,得分一樣按訂單創建先后,算排行,sql需要這么寫:

          select ROWNUM rank, t.*
            from (select *
                    from t_zhcw_order
                   where issue='20170410'
                   order by integral desc, create_date asc) t

          使用了開窗函數后就可以簡化:

          select t.*,
                         row_number() over(order by t.integral desc, t.create_date asc) 排名
                    from t_zhcw_order t
                   where issue='20170410'

          如果想只要排名范圍,可以在外邊再包一層,這也是高效分頁的一種方式:

          、 前言

          1、在上一篇文章里給大家介紹oracle自動巡檢腳本生成html報告,這篇文章介紹linux服務巡檢腳本生成html報告。
          2、腳本依然是簡單腳本語句的堆積,方便大家二次編輯使用。
          3、項目已經上傳到我的github上
          項目地址:
          https://github.com/domdanrtsey/oswatch.git

          二、注意事項與報告部分截圖

          一定注意閱讀git上的README.md說明,避免部分信息無法正常顯示




          三、README.md

          1、使用root用戶執行
          2、使用說明
          1)、腳本中 ifconfig、mpstat、iostat命令有依賴,需要安裝相關依賴包

          yum -y install bc sysstat net-tools
          1

          2)、執行完巡檢之后,將在腳本所在的路徑下生成html巡檢結果報告,如下
          192.168.31.102os_linux_summary.html
          3)、巡檢項信息如下(其他統計項可根據實際需要自行添加)

          1)、系統基本信息

          2)、cpu信息

          3)、ip網絡信息

          4)、cpu使用率

          5)、連接數信息

          6)、系統限制信息

          7)、內存使用信息

          8)、磁盤使用信息

          9)、網絡流量情況/系統資源變化

          10)、cpu消耗情況前10排行

          11)、cpu消耗按內存情況前10排行

          12)、磁盤io情況

          13)、系統定時任務列表

          14)、系統定時任務腳本內容

          四、腳本內容

          單理解:

          ECMAScript是一個標準,

          JavaScript是一個實現 。

          1、ECMAScript的簡介

          ECMAScript是一種由Ecma國際(前身為歐洲計算機制造商協會,英文名稱是European Computer Manufacturers Association)通過ECMA-262標準化的腳本程序設計語言。這種語言在萬維網上應用廣泛,它往往被稱為JavaScript或JScript,所以它可以理解為是JavaScript的一個標準,但實際上后兩者是ECMA-262標準的實現和擴展。

          2、JavaScript的簡介

          JavaScript一種直譯式腳本語言,是一種動態類型、弱類型、基于原型的語言,內置支持類型。它的解釋器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用于客戶端的腳本語言,最早是在HTML(標準通用標記語言下的一個應用)網頁上使用,用來給HTML網頁增加動態功能。

          JavaScript是通用的跨平臺腳本語言,遵守ECMA-262標準(ES標準),換句話說就是ECMAScript的方言。為了取得技術優勢,微軟推出了JScript,CEnvi推出ScriptEase,與JavaScript同樣可在瀏覽器上運行。為了統一規格,因為JavaScript兼容于ECMA標準,因此也稱為ECMAScript。

          JavasSript商標屬于Oracle公司,因為Sun公司被Oracle收購。JavaScript早年被Sun公司注冊,代表JavaScript這門語言。但是最早發明JavaScript是網景公司。在1995年時,由Netscape公司的Brendan Eich,在網景導航者瀏覽器上首次設計實現而成。因為Netscape與Sun合作,Netscape管理層希望它外觀看起來像Java,因此取名為JavaScript。但實際上它的語法風格與Self及Scheme較為接近。

          3、ES6:全稱ECMAScript 6.0

          ES6經過持續幾年的磨礪,它已成為 JS 有史以來最實質的升級,特性涵蓋范圍甚廣, 小到受歡迎的語法糖,例如箭頭函數(arrow functions)和簡單的字符串插值(string interpolation),大到燒腦的新概念,例如代理(proxies)和生成器(generators);它將徹底改變程序員們編寫JS代碼的方式。

          ES6兼容性列表:http://kangax.github.io/compat-table/es6/

          ES6兼容性列表

          3.1、新語法

          let關鍵字

          let a;
          let b, c, d;
          let e=1;
          let f=1, g="hello";
          • 不允許重復聲明;
          • 塊級作用域(只在代碼塊內生效 {});
          • 不存在變量提升;
          • 不影響作用域鏈;

          const定義常量

          const MAX_AGE=100;
          • 一定要賦予初始值。
          • 一般常量使用大寫(潛規則),一些函數定義的其他情況除外。
          • 常量值不允許修改。
          • 塊級作用域。
          • 對數組和對象的元素修改,不算對常量的修改,不會報錯。

          變量的解構賦值

          //數組的解構
          const TEST01=[1,2,3,4];
          let [a, b, c, d]=TEST01;
          
          //對象的解構
          const TEST02={name:"zhangsan", age:10,say:function(){}};
          let {name, age, say}=TEST02;
          • 按照一定的模式,從數組或者對象中獲取值,并對對象賦值的過程,稱為解構。

          模板字符串

          //字符串賦值方式有:"",''
          //ES6新增:``
          let name="張三";
          let str=`你好,${name}`;
          • 內容中可以直接出現換行符。
          • 直接變量拼接:${var}。

          簡化對象寫法

          let name="張三";
          let say=function(){};
          
          //簡化寫法
          let zhangsan={
              name,
              say
          };
          //等效于
          let zhangsan={
              name: name,
              say: say
          };
          
          //方法聲明簡化
          let test={
              say(){
                  console.log("你好");
              }
          };
          //等效于
          let test={
              say: function(){
                  console.log("你好");
              }
          };
          • 允許大括號內直接寫變量和函數,作為對象的屬性和方法。

          箭頭函數

          //聲明方式:=>定義函數
          let add=(a, b)=>{
              return a+b;
          }
          • this是靜態的,this始終指向函數聲明時所在作用域下的this。
          • 不能作為構造函數實例化對象。
          • 不能使用arguments變量。
          • 箭頭函數的簡寫:省略小括號:形參有且只有一個;省略花括號,當代碼只有一條語句的時候, 此時return也要省略,語句的返回結果就是函數的返回結果。
          • 適用于this無關的回調操作,不適用于this有關的回調。

          函數參數默認值

          //ES6允許函數參數賦值默認值
          function add(a,b=10){
              return a+b;
          }
          • 具有默認值的參數一般要放到最后。
          • 可與解構賦值結合:function add({a, b, c})。

          rest參數:可變參數

          // ...表示
          function(...args){
              console.log(args);//數組
          }
          • rest參數必須最后。

          擴展運算符

          //[...]擴展運算符:將數組轉換為逗號分割的參數序列。
          let a=[1,2,3];
          function say(){
              console.log(arguments);
          }
          say(...a);//實參位置,相當于:say(1,2,3);
          • 應用:數組合并:[...a,...b];數組的克?。簂et b=[...a];將偽數組轉化為真正數組:dom:Object-Array。

          Symbol原始數據類型

          let s=Symbol();
          
          let s1=Symbol("你好");
          let s2=Symbol("你好");
          //s1===s2:false
          
          let s3=Symbol.for("你好");
          let s4=Symbol.for("你好");
          //s3===s4:true
          
          //使用
          let person={
              name:"張三",
              say:function(){
              }
          };
          let methods={
              say:Symbol("say")
          };
          person[methods.say]=function(){  
          };
          //這樣就可以預防新增加方法影響原有的方法。
          • 表示獨一無二的值。
          • 第七種數據類型:Number,String,Boolean,Undefined,Null,Object,Symbol。
          • 類似于字符串的數據類型。
          • 特征:值唯一,解決命名沖突問題。不能與其他數據進行運算。對象屬性不能通過for in循環遍歷,但是可以通過Reflect.ownKeys來獲取所有的鍵名稱。
          • 使用場景:給對象添加對于無二的屬性,方法。
          • 內置值(11個):
            Symbol.hasInstance: 對象的Symbol.hasInstance屬性,指向一個內部方法。當其他對象使用instanceof運算符,判斷是否為該對象的實例時,會調用這個方法。比如,foo instanceof Foo在語言內部,實際調用的是Foo[Symbol.hasInstance](foo)。
            Symbol.isConcatSpreadable: 對象的Symbol.isConcatSpreadable屬性等于一個布爾值,表示該對象用于Array.prototype.concat()時,是否可以展開。
            Symbol.species: 對象的Symbol.species屬性,指向一個構造函數。創建造衍生對象時,會使用該屬性。
            Symbol.match:對象的Symbol.match屬性,指向一個函數。當執行str.match(myObject)時,如果該屬性存在,會調用它,返回該方法的返回值。
            Symbol.replace:對象的Symbol.replace屬性,指向一個方法,當該對象被String.prototype.replace方法調用時,會返回該方法的返回值。
            Symbol.search:對象的Symbol.search屬性,指向一個方法,當該對象被String.prototype.search方法調用時,會返回該方法的返回值。
            Symbol.split:對象的Symbol.split屬性,指向一個方法,當該對象被String.prototype.split方法調用時,會返回該方法的返回值。
            Symbol.iterator: 對象的Symbol.iterator屬性,指向該對象的默認遍歷器方法。Symbol.toPrimitive:對象的Symbol.toPrimitive屬性,指向一個方法。該對象被轉為原始類型的值時,會調用這個方法,返回該對象對應的原始類型值。
            Symbol.toStringTag:對象的Symbol.toStringTag屬性,指向一個方法。在該對象上面調用Object.prototype.toString方法時,如果這個屬性存在,它的返回值會出現在toString方法返回的字符串之中,表示對象的類型。也就是說,這個屬性可以用來定制[object Object]或[object Array]中object后面的那個字符串。
            Symbol.unscopables:對象的Symbol.unscopables屬性,指向一個對象。該對象指定了使用with關鍵字時,哪些屬性會被with環境排除。

          迭代器

          ES6: for...of循環進行遍歷。

          原生具備iterator接口的數據:Array,Arguments,Set,Map,String,TypedArray,NodeList。

          iterator接口:指的是對象內部的一個屬性Symbol.iterator。

          let nums=[1,2,3];
          // for..of:n為鍵值。
          // for..in:n為鍵名稱。
          for(let n of nums){
              console.log(n);
          }
          //迭代器
          let iterator=nums[Symbol.iterator];
          
          // 自定義迭代器事例
          let person={
              name:"張三",
              works:["A","B"],
              [Symbol.iterator](){
                  //索引
                  let index=0;
                  return {
                      //包含next函數
                      next:()=> {
                          //返回值:value和done
                          if(index < this.works.length){
                              let result={value:this.works[index],done:false};
                              index++;
                              return result;
                          }else{
                              return {value:undefined,done:true};
                          }
                      }
                  };
              }
          };
          
          for(let w of person){
              console.log(w);
          }

          生成器

          //1.基礎用法
          function * gen(){
              console.log("hello");
          }
          let it=gen();
          //真正執行,輸出hello
          it.next();
          
          //2.yield關鍵字:代碼片段
          function * gen(){
              console.log("hello-A");
              yield "A";
              console.log("hello-B");
              yield "B";
          }
          
          //返回迭代器對象
          let it=gen();
          it.next();//hello-A
          it.next();//hello-B
          for(let f of gen()){
              console.log(f);//輸出的是yield內容
          }
          
          //3.生成器參數
          function * gen(arg){
              console.log(arg);
              let one=yield 1;
              console.log(one);
              let two=yield 1;
              console.log(two);
          }
          let it=gen("A");
          it.next("B");//A
          it.next("C");//B
          it.next();//C
          • 特殊的函數
          • 主要:異步編程,純回調函數。

          Promise諾言

          //resolve成功->then第一個函數
          //rejects失敗->then第二個函數或catch
          const p=new Promise(function(resolve,reject){
              //resolve(data);
              //reject(data)
          });
          p.then(function(data){
              //成功
          },function(data){
              //失敗
          });
          p.then(function(data){
              //成功
          }).catch(function(data){
              //失敗
          });
          
          //Promise.prototype.then:
          //默認返回結果是Promise
          //成功回調結果,則為返回的數據結果。
          //拋出錯誤,失敗的Promise
          //可以鏈式調用。
          • 異步編程解決方案。
          • Promise是一個構造函數。

          Set數據結構

          類似于數組,但是成員的值都是唯一的,并實現了iterator接口??梢允褂脭U展運算符和for-of進行遍歷。

          let s=new Set();
          let s1=new Set([1,2]);
          
          //屬性和方法
          s1.size;//元素個數
          s1.add(3);//添加新元素
          s1.delete(3);//刪除元素
          s1.has(3);//是否存在
          s1.clear();//清空
          for(let a of s1){}//for-of操作。
          let arr1=[...s1];//擴展運算符:1,2數組
          
          //用途:去重
          let arr=[1,2,3,2];
          let arr2=[...new Set(arr)];
          

          Map數據結構

          類似于對象,鍵值對集合。但是鍵的類型不限于字符串,各種類型都可以當作鍵。

          Map也事項了iterator接口,也可以使用擴展運算符和for-of進行遍歷。

          let m=new Map();
          let m=new Map([["birth","201212"],["firstName","張"]]);
          
          m.set("name","張三");//添加元素
          m.size;//數據量
          m.delete("name");//刪除
          m.get("name");//獲取
          m.clear();//清空
          for(let a of m){
              //a類型為數組:[key,value]
          }
          

          class類

          Es6引入了class的概念,作為對象的模板,通過class關鍵字定義。

          可以看作是一個語法糖,絕大部分功能Es5都能實現,但是class寫法讓對象原型的寫法更清晰,更像面向對象的語法。

          class Person {
            //構造方法,名字固定不能修改
            constructor(name, age) {
              this.name=name;
              this.age=age;
            }
          
            //方法結構必須方法名稱加括號,不能使用ES5方式
            say() {
              console.log(`你好,${this.name}!`);
            }
          
            //靜態屬性方法:關鍵字static
            static maxAge=200;
            static getMaxAge() {
              return maxAge;
            }
          }
          
          //繼承:extends
          class Worker extends Person {
            constructor(name, age, workAge) {
              super(name, age);
              this.workAge=workAge;
            }
          
            work() {
              console.log("工作");
            }
          
            //方法重寫
            say() {
              console.log(`我是員工${this.name}!`);
            }
          }
          
          //get和set
          class Dog {
            //get方法
            get name() {
              console.log("get name調用");
              return this.name;
            }
          
            set name(name) {
              console.log("set name調用");
              this.name=name;
            }
          }
          let dog=new Dog();
          dog.name; //get使用方式
          dog.name="doudou"; //set方式

          數值的擴展-Number

          • Number.EPSILON:javascript地 最小精度,值接近于:2.22E-16,主要用于浮點數運算地精度誤差問題。
          • 進制形式:0b:二進制:let a=0b1010;0o:八進制:let b=0o77;0x:十六進制:let c=0xaf;
          • Number.isFinite:檢測數值是否為有限數,Number.isFinite(100);
          • Number.isNaN:檢測數值是否為NaN。
          • Number.parseInt/Number.parseFloat:字符串轉int/float。
          • Number.isInteger:是否為整數。
          • Math.trunc:將數字小數部分抹掉。
          • Math.sign:整數返回1,負數返回-1,0返回0。

          對象方法地擴展-Object

          • Object.is(a, b):判斷2個值是否i完全相等。
          • Object.assign(a, b):2個對象地合并。
          • Object.setPrototypeOf:設置原型對象。
          • Object.getPrototypeOf:獲取原型對象。

          模塊化

          模塊化:大文件拆成小文件,然后將小文件合并起來。

          好處:

          防止命名沖突。代碼復用。高維護性。


          ES6之前地模塊化規范有:

          CommonJS:NodeJS,BrowserifyAMD:requireJSCMD:seaJS

          ES6模塊化規范:

          • export:定義對外接口。
          • import:定義輸入模塊。
          //分別暴露
          export let name="zhangsan";
          export function say(){}
          
          //統一暴露
          let name="zhangsan";
          function say(){}
          export {
          	name,
              say
          };
          
          //默認暴露
          let name="zhangsan";
          function say(){}
          export default {
              name,
              say
          };
          
          //通用導入方式
          import * as P from "test.js";
          
          //解構賦值形式
          import {name, say as hello} from "test.js";
          
          //默認暴露的引入方式,2種方式等價
          import {default as P} from "test.js";
          import P from "test.js";
          • 瀏覽器使用模塊化ES6的方式:
          <script type="module">
              import * as P from "test.js"; 
              //一通操作
          </script>
          • 瀏覽器另一種引入模塊化ES6的方式:
          <script src="./app.js" type="module"></script>
          //app.js文件內部進行引入等一通操作
          import * as P from "test.js"; 
          //一通操作

          4、ES7~ES11的新特性

          ES7(ES2016)新特性

          • Array.prototype.includes:數組是否包含某個元素,返回boolean類型。
          const a=[1, 2];
          a.includes(1);
          • 指數操作符:[**]快速實現冪運算,功能與Math.pow相同。
          let a=2 ** 10;//2的10次方=1024,等價:Math.pow(2,10);

          ES8(ES2017)新特性

          asyncawait讓異步代碼看起來跟同步代碼一樣。

            • async函數:返回值必須為promise對象,promise對象的結果由async函數執行的返回值決定。
          //async函數
          async function fn() {
            //返回結果不是一個promise類型的對象,返回結果就會是成功的promise。
            //return "hello";
              
            //拋出錯誤,返回結果是一個失敗的promise
            //throw new Error("hello");
              
            //返回結果是一個promise對象。
          }
          
          let result=fn();
          result.then((value)=> {
              console.log("成功");
            }).catch((error)=> {
              console.log("失敗");
            });
            • await表達式:

          await必須放到async函數中;

          await右側的表達式一般為promise對象。

          await返回promise成功的值。

          await的promise失敗了,就會拋出異常,需要通過try-catch捕獲處理。

          //創建promist
          function getUser() {
            return new Promise((resolve, reject)=> {
              resolve("user info");
            });
          }
          
          //await必須要在async函數中
          async function main() {
            try {
              //resolve成功數據
              let userInfo=await getUser();
              console.log(userInfo);
            } catch (error) {
              //reject失敗數據
              console.error(error);
            }
          }

          Object.values和Object.entries:

          let a={name:"dd",age:12};
          
          //對象所有的鍵
          Object.keys(a);
          //對象所有的值
          Object.values(a);
          //返回每個元素的鍵值數組[key,value]
          Object.entries(a);
          //屬性描述對象
          Object.getOwnPropertyDescriptor(a);

          ES9(ES2018)新特性

          • rest參數和spread擴展運算符在ES6中已經引入,當時只針對數組,ES9中可以為對象提供支持。
          function test({a, b, ...others}){
              console.log(a);
              console.log(b);
              console.log(others);
          }
          test({
              a:1,
              b:2,
              c:3,
              d:4
          });
          //輸出:1,2,{c:3,d:4}
          
          //對象擴展
          let a={name:"張三"};
          let b={age:12};
          let c={...a,...b};//{name:'張三',age:12}
          • 正則擴展-命名捕獲分組
          //以前
          let str="<a href='http://nomax.cn'>諾碼信科技</a>";
          let reg=/<a href='(.*)'>(.*)<\/a>/;
          let result=reg.exec(str);
          console.log(result[1]); //http://nomax.cn
          console.log(result[2]); //諾碼信科技
          
          //現在:?<url>
          let str="<a href='http://nomax.cn'>諾碼信科技</a>";
          let reg=/<a href='(?<url>.*)'>(?<text>.*)<\/a>/;
          let result=reg.exec(str);
          console.log(result.groups.url); //http://nomax.cn
          console.log(result.groups.text); //諾碼信科技
          • 正則擴展-反向斷言:正向斷言。
          • 正則擴展-dotAll模式。

          ES10(ES2019)新特性

          • Object.fromEntries:把鍵值對數組轉成了對象
          //二維數組
          let re=Object.fromEntries([
              ['name':'張三'],
              ['age', 20]
          ]);
          • String的trimStart和trimEnd:清除字符串前或后的空白字符。
          • 數組擴展方法:flat/flatMap:將多維數組轉化為低維數組。
          let arr=[1,2,[3,4]];
          arr.flat();//1,2,3,4
          //arr.flat(deep);--deep代表深度,默認1,如果三維數組展開,就需要傳遞2.
          
          //flatMap可以看作是flat和map2個操作的結合。
          let arr2=[1,2,3];
          //以下2中方式等價
          let arr3=arr2.map(item=>[item*10]);
          let arr4=arr3.flat();
          //flatMap方式。
          let arr4=arr2.flatMap(item=>[item*10]);
          • Symbol.prototype.description:屬性擴展,獲取描述字符串
          let s=Symbol("hello");
          s.description;//返回hello

          ES11(ES2020)新特性

          • 私有屬性
          class Persion {
            //公有屬性
            name;
            //私有屬性
            #age;
            constructor(name, age) {
              this.name=name;
              this.#age=age;
            }
          }
          • Promise.allSettled:批量異步任務處理
          const p1=new Promise((resolve, reject)=> {
            resolve("data1");
          });
          
          const p2=new Promise((resolve, reject)=> {
            reject("error2");
          });
          
          //返回成功的promise,內部結果數組對每個記錄狀態。
          let re=Promise.allSettled([p1, p2]);
          
          //有一個失敗,就返回失敗的Promise
          let re2=Promise.all([p1, p2]);
          • String.prototype.matchAll:字符串擴展,得到正常批量匹配的結果
          • 可選鏈操作符:?.
          function main(config) {
            //原先的獲取方式
            //let host=config && config.db && config.db.host;
          
            //現在-?.
            let host=config?.db?.host;
          }
          
          main({
            db: {
              host: "127.0.0.1",
              port: "3306",
            },
          });
          • 動態import:按需加載
          function btnClick() {
            //通過import函數動態導入模塊,返回結果為promise,參數為導入模塊
            import("./test01").then((module)=> {
              module.sayHell("d");
            });
          }
          • BigInt大整數數據類型
          let n=222n;
          typeof(n);//bigint
          //普通值轉biginit
          BitInit(122);
          //主要用于大整數的運算
          • globalThis全局對象
          console.log(globalThis);

          學無止境!


          主站蜘蛛池模板: 亚洲日韩激情无码一区| 日韩在线视频一区| 日韩人妻一区二区三区免费| 国产免费av一区二区三区| 国产a∨精品一区二区三区不卡| 国产一区二区三区播放| 亚洲丰满熟女一区二区哦| 88国产精品视频一区二区三区| 免费人妻精品一区二区三区| 亚洲一区二区三区在线视频| 精品国产一区二区22| 无码视频一区二区三区在线观看| 丰满人妻一区二区三区视频| 国产精品亚洲一区二区无码 | 精品少妇ay一区二区三区| 精品一区二区三区中文字幕| 亚洲乱色熟女一区二区三区丝袜| 国产精品成人一区二区| 国产成人精品一区二区三区| 一区二区三区杨幂在线观看| 亚洲一区二区三区国产精品| 好爽毛片一区二区三区四 | 亚洲国产av一区二区三区| 色一乱一伦一区一直爽| 国产SUV精品一区二区88L| 精品一区二区三区在线观看l| 亚洲国产系列一区二区三区| 中文激情在线一区二区| 国产乱码精品一区二区三区香蕉| 国内精品视频一区二区八戒| 国产在线视频一区二区三区| 成人国产精品一区二区网站| 国产婷婷一区二区三区| 国产成人无码一区二区三区在线 | 日本高清天码一区在线播放| 美女视频一区二区三区| 亚洲国产精品一区二区九九| 免费看一区二区三区四区| 国产精品日本一区二区不卡视频 | 日韩人妻无码一区二区三区久久99| 国产精品主播一区二区|