ECMA(European Computer Manufacturers Association)
中文名稱爲歐洲計算機制 機製 造商協會,這個組織的目標是評估、開發和認可電信和計算機標準。1994 年後該 組織改名爲 Ecma
國際。
ECMAScript
是由Ecma
國際通過 ECMA-262
標準化的指令碼程式設計語言。
Ecma
國際制定了許多標準,而 ECMA-262
只是其中的一個。所有標準列表點我檢視
ECMA-262(ECMAScript)
歷史版本點我檢視
版本 | 時間 | 說明 |
---|---|---|
第1版 | 1997年 | 制定了語言的基本語法 |
第2版 | 1998年 | 較小改動 |
第3版 | 1999年 | 引入正則、例外處理、格式化輸出等,IE開始支援 |
第4版 | 2007年 | 過於激進,未發佈 |
第5版 | 2009年 | 引入嚴格模式、JSON,擴充套件物件、陣列、原型、字串、日期方法 |
第6版 | 2015年 | 模組化、物件導向語法、Promise、箭頭函數、let、const、陣列解構賦值等 |
第7版 | 2016年 | 冪運算子、陣列擴充套件、Async/await關鍵字 |
第8版 | 2017年 | Async/swait、字串擴充套件 |
第9版 | 2018年 | 物件解構賦值、正則擴充套件 |
第10版 | 2019年 | 擴充套件物件陣列方法 |
ES.next | 動態指向下一個版本 |
TC39(Technical Committee 39)
是推進 ECMAScript
發展的委員會。其會員都是 公司(其中主要是瀏覽器廠商,有蘋果、谷歌、微軟、因特爾等)。TC39
定期 召開會議,會議由會員公司的代表與特邀專家出席
let
關鍵字用來宣告變數,使用let宣告的變數特點如下:
範例如下:
<script>
// 1. 不允許重複宣告
// let name = '旺財';
// let name = '小強';
// 2. 塊級作用域
// 宣告的變數只能在塊內使用,if while for else
// {
// let name2 = '羅志祥';
// console.log(name2);
// }
// console.log(name2);
// 3. 不存在變數提升
// console.log(song);
// let song = '白色空間';
// 4. 不影響作用域
// {
// let girl = '周揚青';
// function test(){
// console.log(girl);
// }
// test();
// }
</script>
const
關鍵字用來宣告常數,特點如下:
範例如下:
<script>
const VALUE = 12;
// VALUE = 13; 會報錯
const person = {
name:'wangcai',
age:12
}
console.log(person);// {name: "wangcai", age: 12}
person.name = '小強';// 不會報錯
console.log(person);// {name: "小強", age: 12}
person = {};// Uncaught TypeError: Assignment to constant variable
</script>
注意:物件屬性修改和陣列元素變化不會觸發const報錯
應用場景:
const
let
ES6
允許按照一定模式,從陣列和物件中提取值,對變數進行賦值,這稱爲解構賦值。
範例如下:
<script>
// 1. 陣列的解構賦值
const names = ["張三", "李四", "王五"];
let [zhang, li, wang] = names;
console.log(zhang);
console.log(li);
console.log(wang);
// 2. 物件的解構賦值
const person = {
name: "旺財",
age: 12,
eat: function () {
console.log("我就知道吃");
},
};
let { name, age, eat } = person;
console.log(name);
console.log(age);
eat();
// 3. 複雜解構賦值
let tingfeng = {
name: "謝霆鋒",
age: 38,
songs: ["忘情水", "北京歡迎你"],
history: [
{
name: "謝小小",
},
{
name: "謝大大",
},
],
};
let {
songs: [one, two],
history: [first, second],
} = tingfeng;
console.log(one);
console.log(history);
console.log(second);
</script>
注意:頻繁使用物件方法、陣列元素,就可以使用解構賦值
模板字串(template string)
是增強版的字串,用反引號(`)標識,特點如下:
${xxx}
形式輸出變數範例如下:
<script>
// 1. 宣告模板字串
let str = `我也是一個字串哦`
// 2. 內容中可以直接出現換行符
let str2 = `<ul>
<li>腎疼</li>
<li>腰疼</li>
<li>胸疼</li>
</ul>`
// 3. 變數拼接
let name = '旺財'
let out = `${name}是我的最愛哦`
console.log(out);
</script>
注意:當遇到字串與變數拼接時使用模板字串
ES6
允許在大括號裏面,直接寫入變數和函數,作爲物件的屬性和方法。
範例如下:
<script>
let name = '旺財'
let change = function(){
console.log('我們可以改變世界');
}
const person={
name,
change,
eat(){
console.log('我們還可以吃吃吃');
}
}
console.log(person);
</script>
注意:物件簡寫形式簡化了程式碼,推薦以後使用簡寫
ES6
允許使用「箭頭」(=>)定義函數,注意點如下:
arguments
範例如下:
<script>
// 1.通用寫法
let fn = (agr1, arg2, arg3) => {
return agr1 + arg2 + arg3;
};
let result = fn(1, 2, 3);
console.log(result);
// this是靜態的,始終指向函數宣告時所在作用域下的this的值
function getName() {
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
};
// 設定window的name屬性
window.name = "旺財";
const person = {
name: "小強",
};
// 直接呼叫
getName(); // 旺財
getName2(); // 旺財
// call方法呼叫
getName.call(person); //小強
getName2.call(person); // 旺財
// 2. 不能作爲建構函式範例化物件
// let Dog= (name,age)=>{
// this.name = name
// this.age = age
// }
// let d = new Dog('旺財',12)
// console.log(d);//Uncaught TypeError: Dog is not a constructor
// 3. 不能使用arguments變數
// let fn2 = () => {
// console.log(arguments);//Uncaught ReferenceError: arguments is not defined
// };
// fn2();
// 4. 箭頭函數的簡寫
// 1. 當形參只有一個參數時,可以省略小括號
let add = (n) => {
return n + n;
};
// 2. 當函數體只有一條語句的時候,此時return可以省略,且語句的執行結果就是函數的返回值
let pow = (n) => n * n;
console.log(pow(2));
</script>
ES6
允許給函數參數賦值初始值。
範例如下:
<script>
// 1. ES6允許給函數參數設定預設值,一般位置放最後
function add(a, b, c = 10) {
return a + b + c;
}
let result = add(1, 2, 3);
console.log(result);
// 2. 與解構賦值結合
function connect({ host = "127.0.0.1", port, username, password }) {
console.log(host);
console.log(password);
}
connect({
host: "localhost",
port: "8080",
username: "root",
password: "root",
});
</script>
ES6
引入rest
參數,用於獲取函數的實參,用來代替arguments
。
範例如下:
<script>
// ES5獲取實參方式
function data(){
console.log(arguments);
}
data('旺財','小強','大明')
// ES6 rest參數
function data2(...args){
console.log(args);
}
data2('豬','鴨','魚') // ["豬", "鴨", "魚"]
</script>
注意:rest參數非常適合不定個數參數函數的場景
「...」
擴充套件運算子能將陣列轉換爲逗號分隔的「參數序列」。
範例如下:
<body>
<div></div>
<div></div>
<div></div>
<script>
// ...擴充套件運算子能將一個數組轉換成以逗號分隔的參數序列
const tfboys = ['易烊千璽','王源','黃曉明'] // => '易烊千璽','王源','黃曉明'
function chunwan(){
console.log(arguments);
}
chunwan(...tfboys)
// 1. 陣列的合併
const kuaizi = ['肖央','王太利']
const fenghuang = ['曾毅','玲花']
const zuixuanxiaopingguo = kuaizi.concat(fenghuang)
console.log(zuixuanxiaopingguo);
const zuixuanxiaopingguo2 = [...kuaizi,...fenghuang]
console.log(zuixuanxiaopingguo2);
// 2. 陣列的克隆
const sanzhihua = ['E','G','M']
const sanyecao = [...sanzhihua]
console.log(sanyecao);
// 3. 將僞陣列轉換爲真正的陣列
const divs = document.querySelectorAll('div')
console.log(divs);
const divArr = [...divs]
console.log(divArr);
</script>
</body>
ES6
引入了一種新的原始數據型別Symbol
,表示獨一無二的值。他是javascript
語言的第七種數據型別,是一種類似於字串的數據型別。
特點如下:
symbol
的值是唯一的,用來解決命名衝突問題symbol
值不能與其他數據進行運算symbol
定義的物件屬性不能使用for...in
回圈遍歷,但是可以使用Reflect.ownKeys
來獲取物件的所有鍵名注意:遇到唯一性的場景,要使用symbol
Symbol()
Symbol('xxx')
Symbol.fro('xxx')
範例如下:
<script>
// 建立symbol
let s = Symbol();
console.log(s, typeof s); // 10-symbol基本使用.html:12 Symbol() "symbol"
let s2 = Symbol("demo");
let s3 = Symbol("demo");
console.log(s2, s3, s2 === s3); // Symbol(demo) Symbol(demo) false
let s4 = Symbol.for("test");
let s5 = Symbol.for("test");
console.log(s4 === s5); // true
// 不能與其他數據進行計算
// let result = s + 100
</script>
範例如下:
<script>
let game = {};
// 宣告一個物件
let methods = {
up: Symbol(),
down: Symbol(),
};
game[methods.up] = function () {
console.log("我可以快速上升");
};
game[methods.down] = function () {
console.log("我可以快速下降");
};
console.log(game);
// 新增symbol屬性2
let youxi = {
name: '狼人殺',
[Symbol('say')]:function(){
console.log('我可以發炎');
},
[Symbol('zibao')]:function(){
console.log('我可以自爆');
}
}
console.log(youxi);
</script>
除了定義自己使用的Symbol
值意外,ES6
還提供了11個內建的Symbol
值,指向語言內部使用的方法,可以稱這些方法爲魔術方法,因爲他們會在特定的場景下自動執行。
方法 | 描述 |
---|---|
Symbol.hasInstance | 當其他物件使用 instanceof 運算子,判斷是否爲該對 象的範例時,會呼叫這個方法 |
Symbol.isConcatSpreadable | 物件的 Symbol.isConcatSpreadable 屬性等於的是一個 布爾值,表示該物件用於 Array.prototype.concat()時, 是否可以展開。 |
Symbol.species | 建立衍生物件時,會使用該屬性 |
Symbol.match | 當執行 str.match(myObject) 時,如果該屬性存在,會 呼叫它,返回該方法的返回值。 |
Symbol.replace | 當該物件被 str.replace(myObject)方法呼叫時,會返回 該方法的返回值 |
Symbol.search | 當該物件被 str. search (myObject)方法呼叫時,會返回 該方法的返回值。 |
Symbol.split | 當該物件被 str. split (myObject)方法呼叫時,會返回該 方法的返回值。 |
Symbol.iterator | 物件進行 for…of 回圈時,會呼叫 Symbol.iterator 方法, 返回該物件的預設遍歷器 |
Symbol.toPrimitive | 該物件被轉爲原始型別的值時,會呼叫這個方法,返回該物件對應的原始型別值。 |
Symbol.toStringTag | 在該物件上面呼叫 toString 方法時,返回該方法的返 回值 |
Symbol.unscopables | 該物件指定了使用with關鍵字時,哪些屬性會被with 環境排除。 |
迭代器是一種機制 機製,他是一種介面,爲各種不同的數據結構提供統一的存取機制 機製。任何數據結構只要部署Iterator
介面,就可以完成遍歷操作。
ES6
創造了一種新的遍歷命名for..of
回圈,Iterator
介面主要供for..of
消費。
原生具備Iterator
介面的數據(可用for of
遍歷):
工作原理:
注意: 需要自定義遍歷數據的時候,要想到迭代器
範例程式碼:
<script>
const xiyou = ["豬八戒", "唐僧", "孫猴子", "沙僧"];
for (let v of xiyou) {
console.log(v);
}
// 自定義迭代器
const banji = {
name: "終結一班",
students: ["小米", "三星", "華爲"],
[Symbol.iterator]() {
let index = 0;
let _this = this;
return {
next: function () {
if (index < _this.students.length) {
const result = { value: _this.students[index], done: false };
index++;
return result;
} else {
return { value: undefined, done: true };
}
},
};
},
};
for(let stu of banji){
console.log(stu);
}
</script>
生成器函數時ES6
提供的一種非同步變成解決方案,語法行爲與傳統函數完全不同。
範例程式碼:
<script>
// 生成器其實就是一種特殊的函數,非同步程式設計
function* gen() {
console.log("hello generator");
yield "一隻沒有耳朵";
yield "一隻沒有尾巴";
yield "真奇怪 真奇怪";
}
let iterator = gen();
console.log(iterator);
console.log(iterator.next()); //{value: "一隻沒有耳朵", done: false}
console.log(iterator.next()); //{value: "一隻沒有尾巴", done: false}
console.log(iterator.next()); //{value: "真奇怪 真奇怪", done: false}
console.log(iterator.next()); //{value: undefined, done: true}
// 遍歷
// for(let v of gen()){
// console.log(v);
// }
</script>
範例如下:
// 生成器傳參
function* gen2(arg) {
console.log(arg);// AAA
let one = yield 111;
console.log(one);// BBB
let two = yield 222;
console.log(two);//CCC
let three = yield 333;
console.log(three);//DDD
}
// 執行獲取迭代器物件
let iterator2 = gen2('AAA')
console.log(iterator2.next())
// next方法可以傳入實參
console.log(iterator2.next('BBB'));
console.log(iterator2.next('CCC'));
console.log(iterator2.next('DDD'));
範例一:
<script>
// 需求 1S後控制檯輸出111,2S後輸出222,3S後輸出333
function one() {
setTimeout(() => {
console.log("111");
iterator3.next()
}, 1000);
}
function two() {
setTimeout(() => {
console.log("222");
iterator3.next()
}, 2000);
}
function three() {
setTimeout(() => {
console.log("333");
iterator3.next()
}, 3000);
}
function* gen() {
yield one();
yield two();
yield three();
}
let iterator3 = gen()
iterator3.next()
</script>
範例二:
<script>
// 模擬獲取 用戶數據->訂單數據->商品數據
function getUser() {
setTimeout(() => {
console.log("用戶數據獲取成功");
let data = "用戶數據";
iterator4.next(data)
}, 1000);
}
function getOrders() {
setTimeout(() => {
console.log("訂單數據獲取成功");
let data = "訂單數據";
iterator4.next(data)
}, 1000);
}
function getGoods() {
setTimeout(() => {
console.log("商品數據獲取成功");
let data = "商品數據";
iterator4.next(data)
}, 1000);
}
function* gen4() {
let user = yield getUser();
console.log(`user:${user}`);
let orders = yield getOrders();
console.log(`orders:${orders}`);
let goods = yield getGoods();
console.log(`goods:${goods}`);
}
let iterator4 = gen4();
iterator4.next();
</script>
Promise
是ES6
引入的非同步程式設計的新解決方案。語法上Promise
是一個建構函式,用來封裝非同步操作並可以獲取其成功或失敗的結果。
範例:
<script>
// 範例化Promise物件
new Promise(function (resolve, reject) {
setTimeout(() => {
let data = "hello world";
// resolve(data);
reject('error')
}, 1000);
}).then(
function (value) {// 成功回撥 resolve
console.log(value);
},
function (reason) {// 失敗回撥 reject
console.log(reason);
}
);
</script>
ES6
提供了新的數據結構Set
,類似於陣列,但成員的值都是唯一的,集合實現了iterator
介面,所有可以使用「擴充套件運算子」
和「for...of...」
進行遍歷,集合的屬性和方法如下:
size
:返回集合的元素個數add
:增加一個新元素,返回當前集合delete
:刪除元素,返回boolean
值has
:檢測集閤中是否包含某個元素,返回boolean
值clear
:清空集合,返回undefined
<script>
const s = newSet(["旺財", "小米", "三星", "華爲", "蘋果"]);
console.log(s.size);
s.add("諾基亞");
s.delete("旺財");
console.log(s.has("vivo"));
s.clear();
console.log(s);
// 範例
let arr = [1, 2, 1, 3, 5, 6, 2, 4, 5, 3];
// 1. 陣列去重
let r1 = [...new Set(arr)];
console.log(r1);
// 2. 陣列取交集
let arr2 = [2, 3, 4, 2, 3, 9, 10];
let r2 = [...new Set(arr)].filter((item) => new Set(arr2).has(item));
console.log(r2);
// 3. 並集
let union = [...new Set([...arr, ...arr2])];
console.log(union);
// 4. 差集
let r4 = [...new Set(arr)].filter((item) => !new Set(arr2).has(item));
console.log(r4);
</script>
ES6
提供了Map
數據結構,它類似於物件,也是鍵值對的集合。但是"鍵"的範圍不限於字串,各種型別的值(包括物件)都可以當做鍵。Map也實現了iterator介面,所以可以使用「擴充套件運算子」
和「for...of..」
進行遍歷。Map的屬性和方法如下:
size
:返回Map
的元素個數set
:增加一個新元素,返回當前Mapget
:返回鍵名物件的鍵值has
:檢測Map
中是否包含某個元素,返回boolean
值clear
:清空集合,返回undefined
範例:
const m = new Map()
m.set('name','旺財')
m.set('change',function(){
console.log('我是大旺財');
})
console.log(m.get('name'));
m.set('demo','test')
m.delete('demo')
for(let v of m){
console.log(v);
}
m.clear()
console.log(m);
ES6
提供了更接近傳統語言的寫法,引入了Class
(類)這個概念,作爲物件的模板。通過class
關鍵字可以定義類。
基本上,ES6
的class
可以看做只是一個語法糖,它的絕大部分功能,ES5
都可以做到,新的class
寫法只是讓物件原型的寫法更加清晰、更加物件導向程式設計的語法而已。
知識點:
class
宣告類constructor
定義建構函式初始化extends
繼承父類別super
呼叫父級構造方法static
定義靜態方法和屬性範例:
<script>
// class初體驗
class Phone {
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
call() {
console.log("我可以打電話哦");
}
// get set方法
get price() {
console.log("get prices called");
return 2999;
}
set price(newVal) {
console.log("set price called");
}
// 靜態屬性
static version = "MIUI 12.0.2";
// 靜態方法
static printVersion() {
console.log("i am ", this.version);
}
}
let huawei = new Phone("華爲", 1111);
huawei.call();
console.log(huawei.version); // undefined
// huawei.printVersion()// Uncaught TypeError: huawei.printVersion is not a function
console.log(Phone.version); // MIUI 12.0.2
Phone.printVersion(); //i am MIUI 12.0.2
// get set test
console.log(huawei.price);// 2999
huawei.price = "3999";
console.log(huawei.price);
// 類繼承
class SmartPhone extends Phone {
constructor(brand, price, color, size) {
super(brand, price);
this.color = color;
this.size = size;
}
photo() {
console.log("我可以拍照哦");
}
// 子類重寫父類別方法
call() {
console.log("我可以視訊通話哦");
}
}
let xiaomi = new SmartPhone("小米", 1999, "red", 6.9);
xiaomi.photo(); // 我可以拍照哦
xiaomi.call(); // 我可以視訊通話哦
</script>
</body>
ES6
提供了二進制和八進制數值的新的寫法,分別用字首0b
和0o
表示。
// 二進制和八進制
let b = 0b1010;
let o = 0o777;
let d = 100;
let x = 0xff;
console.log(b, o, d, x);
Number.isFinite()
用來檢查一個數值是否是有限的Number.isNaN()
用來檢查一個值是否爲NaN
ES6
將全域性方法parseInt
和parseFloat
移植到Number
物件上面,使用不變
Math.trunc()
用於去除一個小數的小數部分,返回整數部分
Number.isInteger()
用來判斷一個數值是否爲整數
<script>
// 二進制和八進制
let b = 0b1010;
let o = 0o777;
let d = 100;
let x = 0xff;
console.log(b, o, d, x); //10 511 100 255
// isFinite 檢測一個數值是否爲有限數
console.log(Number.isFinite(100)); // true
console.log(Number.isFinite(100 / 0)); // false
console.log(Number.isFinite(Infinity)); // false
// isNaN檢測一個數值是否爲NaN
console.log(Number.isNaN(123)); // false
// parseInt parseFloat字串轉整數
console.log(Number.parseInt("123asa")); //123
console.log(Number.parseFloat("2.3431ifm是")); //2.3431
// isInteger判斷一個數是否爲整數
console.log(Number.isInteger(5)); //true
console.log(Number.isInteger(5.2)); //false
// trunc將數位的小數部分抹掉
console.log(Math.trunc(3.4)); //3
// sign判斷一個梳到底爲整數 負數 還是零
console.log(Math.sign(100)); //1
console.log(Math.sign(0)); //0
console.log(Math.sign(-100)); //-1
</script>
ES6
新增了一些Object
物件的方法:
Object.is
:比較兩個值是否嚴格相等,與「===」行爲基本一致(+0與NaN)Object.assign
:物件的合併,將源物件的所有可列舉屬性,複製到目標物件__proto__
、setPrototypeOf
可以直接設定物件的原型範例:
<script>
// 1. Object.is判斷兩個值是否完全相等
console.log(Object.is(120, 120)); //true
console.log(Object.is(NaN, NaN)); // true
console.log(NaN === NaN); // false
// 2. Object.assign物件的合併
const config1 = {
host: "localhost",
port: "9090",
};
const config2 = {
port: "8080",
username: "username",
};
console.log(Object.assign(config1, config2)); //{host: "localhost", port: "8080", username: "username"} 同欄位的話後面會把前面的替換
// 3, Object.setPrototypeof 設定物件原型
const p = {
name: "旺財",
};
const hobbis = {
hobbies: ["籃球", "足球"],
};
Object.setPrototypeOf(p, hobbis);
console.log(Object.getPrototypeOf(p)); //hobbies: (2) ["籃球", "足球"] _proto__: Object
console.log(p); //{name: "旺財"}name: "旺財"__proto__: hobbies: (2) ["籃球", "足球"]__proto__: Object
</script>
模組化是指將一個大的程式檔案,拆分爲許多小的檔案,然後將小檔案組合起來。
模組化的優勢有以下幾點:
ES6
之前的模組化規範有:
CommonJS
==> NodeJS
、Browerify
AMD
===> requireJS
CMD
==> seaJS
模組功能個主要由兩個命令構成:export
和import
export
:用於規定模組的對外介面,導出import
:用於輸入其他模組提供的功能,匯入