ECMAScript 6,簡稱ES6 。是javascript語言下一代標準。它的目標是使得JavaScript語言能夠用來編寫複雜的大型應用程序,成爲企業級開發語言
。它是一種語言標準,6表示版本號。javascript
ECMA(European Computer Manufacturers Association)的第39號技術專家委員會(Technical Committee 39,簡稱TC39)負責制訂ECMAScript標準組織每一年都會發布ECMAScript的版本:html
ES2015:稱爲es6。前端
ES2018: www.ecma-international.org/ecma-262/8.…java
ES2019:www.ecma-international.org/ecma-262/9.…git
ES6與javascript的關係:ECMAScript是一種語言標準,javascript實現了這個標準(還有JScript和ActionScript也實現這個標準)。程序員
1996年11月,javascript的創造者-----netscape公司,決定將javascript提交給ECMA,以便使之成爲國際標準。es6
1997年,ECMA發佈ECMA-262號標準文件,規定了瀏覽器腳本語言的標準,並將這種語言稱爲ECMAScript,這個版本就是1.0版本。github
這個標準開始就是針對javascript語言制定的,但沒有稱其爲javascript,主要緣由以下:面試
商標。javascript自己已經被Netscape公司註冊爲商標。ajax
ECMA比javascript更開放,更中立。
ES6與ECMAScript2015的關係
ECMAScript2015是具體到2015年6月發佈的那一版。
ES6有兩層含義
特指ECMAScript2015
泛指ES2015及以後的新增特性,雖然以後的版本應當稱爲ES2018,ES2019...es6。
es6新增了不少強大的語法,以下是比較常使用的:
let 和 const
解構賦值
函數擴展
字符串擴展
數組擴展
對象的簡寫
其它內容,自行補充學習。
各類環境中對es6的支持程度: kangax.github.io/compat-tabl…
ES6電子書: es6.ruanyifeng.com/#docs/intro
咱們以前定義變量的關鍵字是var
,它定義的變量有不少奇怪的特色,以下有兩點比較突出:
變量先使用再定義------ 變量提高。
console.log(a);
var a = 1;
console.log(a)複製代碼
缺乏塊級做用域。
// 此處爲了使用循環,定義一個循環變量i。
for(var i=1; i<10;i++){}
// i在循環體以外也能使用。
console.info(i);複製代碼
這兩個問題都容易讓初學者混淆,也容易讓從其它語言轉過來的程序員混淆。爲了解決這些問題,ES6中新增了let。
而ES6引入const的緣由是,由於ES5中並無提供常量
的功能。
做用:定義變量。(var也是用來定義變量)
格式: let 變量名 = 變量值;
它用來定義變量,基本使用格式與var關鍵字同樣。在能夠在使用var 的地方改爲let。
不能重複定義
沒有變量提高(var定義的變量是有變量提高的),必須先定義再使用
全局變量不會附加到window對象的屬性中
具備塊級做用域
// 1. let 定義變量,變量不能夠再次定義
let name = 'zhangsan';
name = 'lisi';
console.log(name); // lisi
let name = 'wangwu'; // 再次定義,報錯:Identifier 'name' has already been declared複製代碼
做用域
全局做用域
局部做用域
塊級做用域(ES6中提出的)
若是是經過let關鍵字來定義變量的,則js代碼中就能夠經過{}來切分做用域了。
// 具備塊級做用域,塊就是大括號
{
let age = 18;
console.log(age); // 18
}
console.log(age); // 報錯,此做用域中沒有age的定義
// 塊級做用域的嵌套
{
let a = 1;
{
let a = 2;
console.log(a);
a = 3;
console.log(a);
}
console.log(a)
}
// 隱藏的塊級做用域
for (let i = 0; i < 10; i++) {
// i 只能在此範圍內使用,由於有塊級做用域
}
console.log(i); // 報錯,此做用域中沒有age的定義複製代碼
經過let定義的變量,再也不有沒有變量提高,必須先定義再使用
console.log(gender); // 報錯,此時尚未定義gender
let gender = '男';
console.log(1); // 不報錯,輸出undefined
var a = 1; 複製代碼
let聲明的全局變量不會以屬性的形式附加在window對象中,全局變量與window對象再無關係。
let hobby = '吃飯';
var a = 1
console.log(window.hobby);
console.log(window.a); 複製代碼
ES6中保留了對var的支持,你能夠在代碼中同時使用var和let。固然,建議使用let。
程序員在協同開發項目時,會遇到一種場景:有一些數據你們都須要用到,可是都不能修改,即數據是只讀的
。舉個例子:在開發公司的網站時,公司的基本信息:地址,公司名,電話等等信息能夠在多個地方都須要使用,但不容許去修改。 顯示,使用變量來保存這些信息是不適合的,由於變量不是隻讀的。這種狀況下, 咱們就能夠把這些數據保存在常量中。
做用:定義一個只讀的常量。
格式: const 常量名 = 常量值;
示例:const COMPANY_NAME = "XXX公司"
注意:
區別於變量名,常量名通常採用全大寫的方式,多個單詞之間使用_劃線分隔。
所謂常量,就是不能修改,即:
一旦定義就不能修改;
一旦聲明,就必須當即初始化;
const a = 1;
a = 2; // 報錯複製代碼
其它與let類似的特色
具備塊級做用域
沒有變量提高,必須先定義再使用
常量也是獨立的,定義後不會壓入到window對象中,不是window對象的屬性
const
實際上保證的,並非變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動
。
const obj = {a:1};
obj.a = 2;
console.log(obj); // 問題:obj對象的屬性值a是否修改了。複製代碼
對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,所以等同於常量值。
對於複合類型的數據(如對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const
只能保證這個指針是固定的(即老是指向另外一個固定的地址),至於它指向的數據結構是否是可變的,就不能控制了。所以,將一個對象聲明爲常量必須很是當心,它的屬性是能夠修改的
。
若是你真的但願定義一個不能修改的對象(屬性不能添加,修改,刪除),你可使用Object.freeze()。下面是一段參考代碼:它一個能夠把一個對象所有凍結的函數:
function makeConst(obj){
Object.freeze(obj);
Object.keys(obj).forEach(function(key){
if(typeof obj[key] === 'object'){
makeConst(obj[key])
}
})
}
var obj = {a:1,b:2};
makeConst(obj);
obj.a = 200;
obj.c = 100;
console.log(obj); //值保持不變複製代碼
關鍵字 | 變量提高 | 塊級做用域 | 初始值 | 更改值 | 經過window調用 |
---|---|---|---|---|---|
let | × | √ | - | Yes | No |
const | × | √ | Yes | No | No |
var | √ | × | - | Yes | Yes |
咱們常常會遇到一個場景:從對象中取出它的屬性值,並保存在一個變量中。
例如:
// 這裏的item是一個對象{},其中包含屬性name和age
let name = item.name;
let age = item.age;複製代碼
另外,如ajax請求的回調函數
$.ajax({
// 省略其它參數
success:function(result){
// 這裏的result是一個對象,其中有code屬性和data屬性
if(result.code === 200){
let data = result.data;
data.forEach(){
}
}
}
})複製代碼
ES6提供了一個更加方便的方式從對象中取出屬性值來,,這就解構賦值。
ES 6 容許按照必定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構(Destructuring)。
它有兩個動做:
- 解構:意思是把有結構的數據分解開成爲一個一個的值
- 賦值:把解構以後的值保存到變量複製代碼
基本示例
let arr = [1,2,3,4];
// 需求,快速地從數組中取出值來賦值給變量a,b,c,d
let a = arr[0];
let c = arr[1];
console.log(a,b,c,d)複製代碼
它可以快速從數組中取出值保存到變量中。它的本質是給變量賦值。
內容:
語法格式及解構規則
常規使用:變量個數等於數組長值
很是規使用
變量個數大於數組長度
變量個數小於數組長度
高級使用
用空跳過不須要的值
剩餘值
複雜嵌套場景
小面試題
格式
let [變量1=默認值1,變量2=默認值2,省略其它,變量n==默認值n ] = [數組元素1,數組元素2,省略其它,數組元素n]複製代碼
默認值是可選的,能夠設置,也能夠不設置;
規則:
賦值符號左右兩邊都是數組,把右邊的數組按下標從小到大取出來,放入左邊的數組中。
若是左邊的變量並無分配到某一個值:
有默認值,使用其默認值。
無默認值,其值是undefined
//最簡單的場景: 變量個數和數組中元素的是相等的
let arr = [5, 9, 10];
let [a, b, c] = arr;
console.log(a, b, c); // 輸出 5 9 10
// 等價於:
let a = arr[0];
let b = arr[1];
let c = arr[2];複製代碼
注意:
「=」左右兩邊的格式要統一。
// 變量多,值少
let arr = [5, 9, 10];
let [a, b, c, d] = arr;
console.log(a, b, c, d);
// 5 9 10 undefined
// 默認值
let arr = [5, 9];
let [a, b, c, d=4] = arr;
console.log(a, b, c, d);
// 5 9 undefined 4,
// 變量少,值多
let arr = [5, 9, 10, 8, 3, 2];
let [a, b] = arr;
console.log(a, b);
// 5 9
// 用空跳過不須要的值
let arr = [5, 9, 10, 8, 3, 2];
let [, , a, , b] = arr;
console.log(a, b);
// 10 3
// 複雜的場景,只要符合模式,便可解構
let arr = ['zhangsan', 18, ['175cm', '65kg']];
let [, ,[a,b]]=arr
// 如何讓a的值是175cm,b的值是65kg
console.log(a, b); // 175cm 65kg
複製代碼
let arr = [5, 9, 10, 8, 3, 2];
let [a, b, ...c] = arr; // ...c 接收剩餘的其餘值,獲得的c是一個數組
console.log(a, b, c);
// 結果:
// a = 5,
// b = 9,
// c = [10, 8, 3, 2]複製代碼
注意:
... 只能用在最後一個變量上。這個變量是一個數組,在解構賦值的過程當中,若是有出現數組元素個數大於變量個數的狀況,它將會把多餘的參數起來,保存在這個數組。
交換兩個變量的值?
var a = 1, b = 2;
// 寫代碼,實現互換a,b的值
// ????
let arr=[a,b]
複製代碼
let[b,a]=arr
console.info(a,b); // 要求輸出 2, 1複製代碼
做用:快速從對象中獲取值保存到變量中。它的本質是給變量賦值。
完整格式
let {"屬性名1":變量名1=默認值1, "屬性名2":變量名2=默認值2,... } = {"屬性名1":屬性值1,"屬性名2":屬性值2,...}複製代碼
解析規則:
默認值是可選的。你能夠指定默認值,也能夠不指定。
右邊的"屬性名"與左邊的「屬性名」 一致,則把右邊的屬性值賦值給左邊的變量名。
若是右邊的匹配不成立,看看是否有使用默認值,有默認值就使用默認值,沒有就是undefined。
精簡格式
若是左側對象中屬性名與變量名相同,則可左側合併:
let {變量名1=默認值1,變量名2=默認值2} = {"屬性名1":屬性值1,"屬性名2":屬性值2,...}複製代碼
解析規則:
右邊的"屬性名"與左邊的變量名 一致,則把右邊的屬性值賦值給左邊的變量名。
場景1,變量名和屬性名同樣
// 場景1,默認要求變量名和屬性名同樣
let { name, age } = {age: 27, name: '陽明'};
console.log(name, age);
let {a, c} = {a: 'hello', b: 'world'};
console.log(a, c); // hello, undefined複製代碼
注意:
「=」 左右兩邊的格式一致。
對象是屬性的無序集合,因此不須要管順序
場景2,變量更名
// 場景2,能夠經過:爲變量更名
let {b, name:a} = {name: '王陽明'};
console.log(b, a,name); 複製代碼
// 把其它的屬性全收集起來
let obj = {name:'zs', age:20, gender:'男'};
let {name, ...a} = obj;
console.log(name, a);
// 結果:
// name = zs
// a = {age: 20, gender: "男"};複製代碼
js中函數是一等公民
es6對函數的功能進行了一些拓展,補充了不少功能。學習這個部分的內容咱們就能夠更加靈活優雅地使用函數啦。
在定義一個函數時,咱們能夠給形參設置默認值:當用戶不填入這個值時,咱們有一個保底的值可使用。這個特性在不少其它的編程語言中一個基礎的特性,而在ES6以前,是不支持的,咱們須要經過一些變通的方式來實現。
參數的默認值在以前的課程內容已經涉及,例如在xhr.open(type,url,是否異步)
方法中,第3個參數默認是true,即表示異步ajax。
默認值的意思是:
若是傳入,就用你傳的值
若是不傳入,就使用某一個特殊的、事先定義好的值。這個值也就是默認值。
// ES5 中給參數設置默認值的變通作法
function open(type, url,isAsync) {
if(isAsync === undefined){
isAsync = true;
}
console.log(type, url, isAsync);
}
// 下面這兩句是等價的
open("get","common/get");//
open("get","common/get",true);
open("get","common/get",false);複製代碼
以上代碼主要是利用形參的一個特色:沒有賦值的話,其默認值是undefined。代碼是能夠工做的,可是顯得很累贅,es6提供了更簡單的實現。
function 函數名(參數名1='默認值1',參數名2='默認值2',參數名3='默認值3'){
}複製代碼
function open(type, url,isAsync=true) {
console.log(type, url, isAsync);
}
// 下面這兩句是等價的
open("get","common/get");//
open("get","common/get",true);
open("get","common/get",false);
複製代碼
思考:可否跳過isAsync,url,而只給type設置默認值?
注意:
帶默認值的形參放在形參列表的最右邊。
rest (其它的,剩餘的)參數 用於獲取函數多餘參數,把它們放在一個數組中。
在定義函數時,在最後一個參數前面加上...
, 則這個參數就是剩餘參數;
let fn = function(參數1,參數2,...rest參數){}
let fn = (參數1,參數2,...rest參數)=>{ }複製代碼
只是在定義函數時,在形參列表中區別一下,而在調用函數時並沒有區別。
編寫一個函數,求全部參數之和;
方法一:arguments
方法二:rest參數
function getSum (){
// 在這裏寫你的代碼
var sum = 0 ;
for(var i = 0; i < arguments.length; i++){
console.info( arguemnts[i])
sum += arguments[i];
}
}複製代碼
若是以箭頭函數 的方式去定義這個函數,則內部不可使用arguments這個對象了。此時,咱們就可使用
rest 參數,它能夠替代 arguments 的使用。 代碼以下:
// 參數不少,不肯定多少個,可使用剩餘參數
const getSum = (...values) => {
var sum = 0 ;
for(var i = 0; i < values.length; i++){
console.info( values[i])
sum += values[i];
}
}
// 調用
console.log(fn(6, 1, 100, 9, 10));複製代碼
與arguments相比,它是一個真正的數組,可使用所有的數組的方法。
學習箭頭函數能讓代碼更簡潔,效率更高;能看懂別人寫的代碼 ;
let fn3 = x => x * 2;複製代碼
ES6 中容許使用箭頭函數的方式來定義一個函數。前面學習的定義一個函數有兩種方式:
函數聲明式
函數表達式
如今有了一個新的方式:
3. 箭頭函數
let 函數名 = (形參1,...形參n)=>{
// 函數體
}複製代碼
// 1. 函數聲明式
function fu1(x){
return x * 2;
}
// 2. 函數表達式
let fn2 = function (x) {
return x * 2;
}
// 3. 箭頭函數
let fn3 = (x) => {
return x * 2;
}複製代碼
第一眼看到這個箭頭函數時,會以爲很奇怪。若是從函數表達式的格式出發, 通過以下2步演化
步驟就能夠獲得。
把function 關鍵字 後移動到 ()和 {} 中間
把function 改寫成 =>
注意:
- `=>`是一個總體,不要加空格
- 箭頭函數只在定義上有些區別,但在函數調用格式上,是沒有區別的。複製代碼
當形參有且只有一個,能夠省略小括號
let f = (x) => {console.log(x)}
// 能夠簡化成:
let f = x => {console.log(x)}複製代碼
當函數體只有一條語句,能夠省略大括號;
let f = x => {console.log(x)}
// 能夠簡化成:
let f = x => console.log(x)複製代碼
當函數體只有一條語句,而且就是return語句,則能夠省略return和大括號。
let f = x => {return x*2 }
// 能夠簡化成:
let f = x => x*2複製代碼
注意若是返回值是一個對象,要加()
let f = x => {return {a:1} }
// 能夠簡化成:
let f = x => {a:1} // 報錯
let f = x =>({a:1})複製代碼
內部沒有arguments
內部沒有this
不能做爲構造器
let fn = (a,b) => {
console.log(arguments); // 報錯,arguments is not defined
};
fn(1, 2);複製代碼
var name = 'lisi'; // 測試時,這裏必須用var,由於用let聲明的變量不能使用window調用
let obj = {
name: 'zhangsan',
f1 : () => {
console.log(this); // window對象
console.log(this.name); // lisi
},
f2 : function(){
console.log(this); // window對象
console.log(this.name); // lisi
}
};
obj.f1();複製代碼
let Person = () => {
};
let obj = new Person(); // 報錯,Person is not a constructor
// 換個角度理解,箭頭函數中都沒有本身的this,怎麼處理成員,因此不能當構造函數複製代碼
在javascript中,函數是一等公民 ,它除了起到最基本的提煉代碼以外,還能夠當作構造器來使用,它能作的事件太多了。在ES6提出的箭頭函數讓給函數減負了。
數組對象是js中很是重要的對象,它自己提供了很是多的方法,例如:sort,push,pop,unshift, splice,concat,map,forEach,filter,some,.... 。因爲前端的主要工做內容之一是與後端進行數據交互,而數據交互的載體大可能是數組,因此咱們對數組的操做要求也很是高。
曾經有一道面試題:寫出10個你用過的與數組相關的方法。
這一小節的學習會讓咱們多掌握幾個數組的方法。
功能:它的做用是把數組中的元素一項項地展開:把一個總體的數組拆開成單個的元素。
格式:...數組
基本用法
console.info(...[1,2,3]);複製代碼
應用1:數組拷貝
應用2: 數組合並
從把一個數組中的值全取出來,放在另外一個數組中的
var arr0 = ['a','b'];
var arr1 = [1,2,3];
var arr2 = [4, ...arr1];
var arr3 = [..arr0 ,...arr1];複製代碼
應用3:Math.max()
Math.max(1,3,4,6);
var arr = [1,3,4,6];
Math.max(...arr);
// 或者 Math.max.apply(this,[1,2,3,566])複製代碼
功能:把其它非數組的對象轉成數組。
格式: 數組 = Array.from(非數組對象)
它的實參有三種狀況:
自定義的,特殊格式的對象。
let fakeArr = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};複製代碼
就是爲了演示,並沒有實際應用價值。
arguments對象
DOM 操做返回的 NodeList 集合
在實際的開發中,咱們常常會遇到一種場景:從一個數組中找出符合條件的元素。咱們要的討論的重點是如何從數組中找出符合條件的元素,固然,咱們能夠經過手寫循環的方式來實現這個功能,可是如今es6中提供了現成的功能。find/findIndex
做用:從數組中找出咱們符合條件的第一個元素(或者是下標)。
find和findIndex的格式是一致的。
let result = [].find(function(item,index,self){
//....
// 若是知足查找的條件
return true;
})複製代碼
回調函數有三個參數,分別表示:數組元素的值、索引及整個數組
若是某次循環返回的是true,find和findIndex方法的返回值就是知足這個條件的第一個元素或索引
find和findIndex方法,會遍歷傳遞進來的數組
若是在回調函數體內,某個時刻return true,則表示查找過程結果,返回值就是本輪循環中的元素(或者是下標);若是所有的循環結束,也沒有return true,則表示沒有找到,沒有找到會返回undefined。
findIndex 找到數組中第一個知足條件的成員並返回該成員的索引,若是找不到返回 -1。
// 用法:找數組中第一個小於0的數字
let arr = [1, 2, 4, 0, -4, 3, -2, 9];
let result = arr.find(function (item) {
return item < 0; //遍歷過程當中,根據這個條件去查找
});
console.log(result); // -4複製代碼
注意經過箭頭函數來簡化代碼。
findIndex 的使用和 find 相似,只不過它查找的不是數組中的元素,而是元素的下標。
功能:判斷數組是否包含某個值,返回 true / false
格式:數組.includes(參數1,參數2)
參數1,必須,表示查找的內容
參數2,可選,表示開始查找的位置,0表示從第一個元素開始找。默認值是0。
示例:
let arr = [1, 4, 3, 9];
console.log(arr.includes(4)); // true
console.log(arr.includes(4, 2)); // false, 從2的位置開始查,因此沒有找到4
console.log(arr.includes(5)); // false複製代碼
字符串也有這個方法,功能也是類似的。
es6中對字符串提供了新的特性,咱們介紹其中幾個方法:
模板字符串
includes
startsWith
endWith
repeat
在作字符串拼接時,使用+
來拼接複雜內容是很麻煩的,而模板字符串能夠解決這個問題。
格式:`${變量}
${表達式}
`
語法:
模板字 符串使用反引號 ` 把內容括起來,相似於普通字符串的""。
${}充當界定符的做用,其中能夠寫變量名,表達式等。
容許字符串內部進行換行,代碼更好讀更好的體驗
示例:
let name = 'zs';
let age = 18;
// 拼接多個變量,在模板字符串中使用佔位的方式,更易懂
let str = `我是${name},今年${age}`;
// 內容過多能夠直接換行
let obj = [{name: 'flex', age: 20},{name: 'james', age: 21}];
let arr = ['175cm', '60kg'];
let html = ` <div> <ul> <li>${obj.name}</li> <li>${obj.age}</li> <li>${arr[0]}</li> <li>${arr[1]}</li> </ul> </div>複製代碼
格式:str.includes(searchString, [position])
功能:返回布爾值,表示是否找到了參數字符串
position: 從當前字符串的哪一個索引位置開始搜尋子字符串,默認值爲0。
格式:str.startsWidth(searchString, [position])
功能:返回布爾值,表示參數字符串是否在原字符串的頭部或指定位置
position: 在 str
中搜索 searchString
的開始位置,默認值爲 0,也就是真正的字符串開頭處。
格式:str.endsWith(searchString, [len])
功能:返回布爾值,表示參數字符串是否在原字符串的尾部或指定位置.
len:可選。做爲 str
的長度。默認值爲 str.length
。
repeat
方法返回一個新字符串,表示將原字符串重複n
次。
語法:str.repeat(n)
let html = '<li>itheima</li>';
html = html.repeat(10);複製代碼
Set是集合的意思。是ES6 中新增的內置對象,它相似於數組,可是成員的值都是惟一的,即沒有重複的值
。使用它能夠方便地實現用它就能夠實現數組去重的操做。
建立空set;
根據已有數組建立set
// 1. 基本使用
let set = new Set();
// 獲得一個空的Set對象
let set = new Set([1,2,3])複製代碼
size
:屬性,獲取 set
中成員的個數,至關於數組中的 length
add(value)
:添加某個值,返回 Set 結構自己。
delete(value)
:刪除某個值,返回一個布爾值,表示刪除是否成功。
has(value)
:返回一個布爾值,表示該值是否爲Set
的成員。
clear()
:清除全部成員,沒有返回值。
forEach
:遍歷
let arr = [1,1,2,3,3];
console.info([...new Set(arr)])複製代碼
對屬性名的簡化
對方法的簡化
let name = 'zhangsan', age = 20, gender = '女';
let obj = {
name: name, // 原來的寫法
age, // 對象屬性和變量名相同,能夠省略後面的 「:age」,下面的gender同理
gender,
fn1:function(){ // 常規寫法
console.log(123);
},
fn2 () { // 能夠省略
console.log(456);
}
};
console.log(obj.age); // 20
obj.fn2(); // 456複製代碼
ES6 (2015年10月)雖好,可是有兼容性問題,IE7-IE11 基本不支持 ES6
在最新的現代瀏覽器、移動端、Node.js 中都支持 ES6
後續咱們會講解如何處理 ES6 的兼容性
由於 ES 6 有瀏覽器兼容性問題,可使用一些工具進行降級(把ES6的代碼轉成ES5的代碼),例如:babel
babel官網](www.babeljs.cn/)
實時轉碼:babeljs.io/repl