ES6 新增功能點整理

學習文檔地址:https://www.runoob.com/w3cnote/es6-tutorial.html

注意:本文是作者自己學習時做到記錄,不作爲es6的學習材料。槓精勿擾!

 

1、webpcak  打包工具

詳細資料參考webpack中文文檔  https://www.webpackjs.com/concepts/

這篇文章學習文章還可以 :https://www.jianshu.com/p/6aee48560403

範例

const path = require('path');

module.exports = {
    mode: 'production',
    // 入口文件配置
    entry: './js/test.js',
    // 輸出配置
    output: {
        // 出口文件
        filename: 'bundle.js',
        // 設置全路徑
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        // 規則數組, 裏面的每一個對象都是在描述一個loader
        rules: [
            {
                //css文件加載,正則表達式css文件的路徑
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                ////圖片文件加載
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'file-loader',
                        query: {
                            name: 'img/[name]-[hash:5].[ext]'
                        }
                    },
                ],
            },
        ]
    },
    devServer:{
        contentBase: './dist'
    }
};

常用loader:

 ① ES6語法轉化    babel-loader

 ② 打包CSS   style-loader、css-loader

 ③ 圖片路徑處理  url-loader  

④ html-withimg-loader   解決HTML文件中引入 Img標籤的問題

⑤ extract-text-webpack-plugin   CSS與Js分離(一般不推薦)

⑥ 自動處理CSS3屬性前綴  postcss-loader 和 autoprefixer

⑦ 消除冗餘的CSS樣式  purifycss-webpack

⑧ 圖片壓縮         image-webpack-loader

常用插件(plugins)

① html-webpack-plugin  插件    HTML文件的發佈

② 配置JS壓縮  uglifyjs-webpack-plugin

2、gulp 自動化構建工具

詳細資料參考 gulp  中文網 https://www.gulpjs.com.cn/docs/getting-started/quick-start/

這篇文章作爲入門還可以  https://blog.csdn.net/weixin_43932245/article/details/90212725

常用的gulp插件: 

  • 編譯Lass (gulp-lass) 
  • Autoprefixer (gulp-autoprefixer) 
  • 縮小化(minify)CSS (gulp-minify-css) 
  • JSHint (gulp-jshint) 
  • 拼接 (gulp-concat) 
  • 醜化(Uglify) (gulp-uglify) 
  • 圖片壓縮 (gulp-imagemin) 
  • 即時重整(LiveReload) (gulp-livereload) 
  • 清理檔案 (gulp-clean) 
  • 圖片快取,只有更改過得圖片會進行壓縮 (gulp-cache) 
  • 更動通知 (gulp-notify)

 

// 引入 gulp
var gulp = require('gulp'); 

// 引入組件
var jshint = require('gulp-jshint');
var less = require('gulp-less');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var imagemin = require('gulp-imagemin');   圖片壓縮
var cleanCSS = require('gulp-clean-css');  css壓縮
 
// 檢查腳本
gulp.task('lint', function() {
    gulp.src('./js/*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'));
});

// 編譯less
gulp.task('less', function() {
    gulp.src('./less/*.less')
        .pipe(less())
        .pipe(gulp.dest('./css'));
});

// 合併,壓縮文件
gulp.task('scripts', function() {
    gulp.src('./js/*.js')
        .pipe(concat('all.js'))
        .pipe(gulp.dest('./dist'))
        .pipe(rename('lib.min.js'))
        .pipe(uglify())
        .pipe(gulp.dest('./dist'));
});

// 默認任務
gulp.task('build_dev', function(){
    gulp.run('lint', 'less', 'scripts');

    // 監聽文件變化
    gulp.watch('./js/*.js', function(){
        gulp.run('lint', 'less', 'scripts');
    });
});

運行gulp,執行命令爲: gulp build_dev

 

3、新的關鍵字 let 、 const

let

  1. 作用域在當前代碼塊  (var 是全局)
  2. 不能重複聲明
  3. let 不存在變量提升,var 會變量提升(let的字段需要先聲明在使用):

const

  1. 定義只讀變量,值不能變化(儘量值定義簡單常量,不要定義複合類型)
  2. 一旦聲明必須初始化,否則會報錯

for 循環計數器很適合用 let

for (var i = 0; i < 10; i++) {
  setTimeout(function(){
    console.log(i);
  })
}
// 輸出十個 10
for (let j = 0; j < 10; j++) {
  setTimeout(function(){
    console.log(j);
  })
}
// 輸出 0123456789

變量 i 是用 var 聲明的,在全局範圍內有效,所以全局中只有一個變量 i, 每次循環時,setTimeout 定時器裏面的 i 指的是全局變量 i ,而循環裏的十個 setTimeout 是在循環結束後才執行,所以此時的 i 都是 10。

變量 j 是用 let 聲明的,當前的 j 只在本輪循環中有效,每次循環的 j 其實都是一個新的變量,所以 setTimeout 定時器裏面的 j 其實是不同的變量,即最後輸出 12345。(若每次循環的變量 j 都是重新聲明的,如何知道前一個循環的值?這是因爲 JavaScript 引擎內部會記住前一個循環的值)。

 

4、解構賦值

解構賦值是對賦值運算符的擴展。他是一種針對數組或者對象進行模式匹配,然後對其中的變量進行賦值。

  • 解構的源,解構賦值表達式的右邊部分。

  • 解構的目標,解構賦值表達式的左邊部分。

可嵌套 、可忽略 、不完全解構 、解構默認值

let [a, [[b], c]] = [1, [[2], 3]];
// a = 1
// b = 2
// c = 3

let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
// foo = 'aaa'
// bar = 'bbb'
 
let { baz : foo } = { baz : 'ddd' };
// foo = 'ddd'

let {a = 10, b = 5} = {a: 3};
// a = 3; b = 5;
let {a: aa = 10, b: bb = 5} = {a: 3};
// aa = 3; bb = 5;

剩餘運算符...

let [a, ...b] = [1, 2, 3];
//a = 1
//b = [2, 3]

 

5、數據類型 Symbol  

ES6 引入了一種新的原始數據類型 Symbol ,表示獨一無二的值,最大的用法是用來定義對象的唯一屬性名。 

Symbol 函數棧不能用 new 命令,因爲 Symbol 是原始數據類型,不是對象。可以接受一個字符串作爲參數,爲新創建的 Symbol 提供描述,用來顯示在控制檯或者作爲字符串的時候使用,便於區分。

let sy = Symbol("KK");
console.log(sy);   // Symbol(KK)
typeof(sy);        // "symbol"
 
// 相同參數 Symbol() 返回的值不相等
let sy1 = Symbol("kk"); 
sy === sy1;       // false

注意點

Symbol 值作爲屬性名時,該屬性是公有屬性不是私有屬性,可以在類的外部訪問。但是不會出現在 for...in 、 for...of 的循環中,也不會被 Object.keys() 、 Object.getOwnPropertyNames() 返回。如果要讀取到一個對象的 Symbol 屬性,可以通過 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。

Symbol.for()

Symbol.for() 類似單例模式,首先會在全局搜索被登記的 Symbol 中是否有該字符串參數作爲名稱的 Symbol 值,如果有即返回該 Symbol 值,若沒有則新建並返回一個以該字符串參數爲名稱的 Symbol 值,並登記在全局環境中供搜索。

let yellow = Symbol("Yellow");
let yellow1 = Symbol.for("Yellow");
yellow === yellow1;      // false
 
let yellow2 = Symbol.for("Yellow");
yellow1 === yellow2;     // true
Symbol.keyFor()

Symbol.keyFor()

Symbol.keyFor() 返回一個已登記的 Symbol 類型值的 key ,用來檢測該字符串參數作爲名稱的 Symbol 值是否已被登記。

 

6、Map 對象

Maps 和 Objects 的區別:

  • 一個 Object 的鍵只能是字符串或者 Symbols,但一個 Map 的鍵可以是任意值。

  • Map 中的鍵值是有序的(FIFO 原則),而添加到對象中的鍵則不是。

  • Map 的鍵值對個數可以從 size 屬性獲取,而 Object 的鍵值對個數只能手動計算。

  • Object 都有自己的原型,原型鏈上的鍵名有可能和你自己在對象上的設置的鍵名產生衝突。

forEach()

var myMap = new Map();
 myMap.set(0, "zero");
 myMap.set(1, "one"); 
// 將會顯示兩個 logs。 一個是 "0 = zero" 另一個是 "1 = one" 
myMap.forEach(function(value, key) { 
console.log(key + " = " + value); 
}, myMap)

for...of

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
 
// 將會顯示兩個 log。 一個是 "0 = zero" 另一個是 "1 = one"
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
/* 這個 entries 方法返回一個新的 Iterator 對象,它按插入順序包含了 Map 對象中每個元素的 [key, value] 數組。 */
 
// 將會顯示兩個log。 一個是 "0" 另一個是 "1"
for (var key of myMap.keys()) {
  console.log(key);
}
/* 這個 keys 方法返回一個新的 Iterator 對象, 它按插入順序包含了 Map 對象中每個元素的鍵。 */
 
// 將會顯示兩個log。 一個是 "zero" 另一個是 "one"
for (var value of myMap.values()) {
  console.log(value);
}
/* 這個 values 方法返回一個新的 Iterator 對象,它按插入順序包含了 Map 對象中每個元素的值。 */

Map 對象的操作

//Map 與 Array的轉換
var kvArray = [["key1", "value1"], ["key2", "value2"]];
// Map 構造函數可以將一個 二維 鍵值對數組轉換成一個 Map 對象
var myMap = new Map(kvArray);
 // 使用 Array.from 函數可以將一個 Map 對象轉換成一個二維鍵值對數組
var outArray = Array.from(myMap);


//Map 的克隆
var myMap1 = new Map([["key1", "value1"], ["key2", "value2"]]);
var myMap2 = new Map(myMap1);
 console.log(original === clone); 
// 打印 false。 Map 對象構造函數生成實例,迭代出新的對象。


//Map 的合併

var first = new Map([[1, 'one'], [2, 'two'], [3, 'three'],]);
var second = new Map([[1, 'uno'], [2, 'dos']]);
 // 合併兩個 Map 對象時,如果有重複的鍵值,則後面的會覆蓋前面的,對應值即 uno,dos, three
var merged = new Map([...first, ...second]);

 

7、set 對象

Set 對象允許你存儲任何類型的唯一值,無論是原始值或者是對象引用。

Set 對象存儲的值總是唯一的,所以需要判斷兩個值是否恆等。有幾個特殊值需要特殊對待:

  • +0 與 -0 在存儲判斷唯一性的時候是恆等的,所以不重複;

  • undefined 與 undefined 是恆等的,所以不重複;

  • NaN 與 NaN 是不恆等的,但是在 Set 中只能存一個,不重複。

// Array 轉 Set
var mySet = new Set(["value1", "value2", "value3"]);
// 用...操作符,將 Set 轉 Array
var myArray = [...mySet];
String
// String 轉 Set
var mySet = new Set('hello');  // Set(4) {"h", "e", "l", "o"}
// 注:Set 中 toString 方法是不能將 Set 轉換成 String

Set 對象作用

//數組去重
var mySet = new Set([1, 2, 3, 4, 4]);
[...mySet]; // [1, 2, 3, 4]

//並集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var union = new Set([...a, ...b]); // {1, 2, 3, 4}

//交集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}

//差集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var difference = new Set([...a].filter(x => !b.has(x))); // {1}

 

8、Reflect 與 Proxy

Proxy 與 Reflect 是 ES6 爲了操作對象引入的 API 。

Proxy 可以對目標對象的讀取、函數調用等操作進行攔截,然後進行操作處理。它不直接操作對象,而是像代理模式,通過對象的代理對象進行操作,在進行這些操作時,可以添加一些需要的額外操作。

let target = {
    name: 'Tom',
    age: 24
}
let handler = {
    get: function(target, key) {
        console.log('getting '+key);
        return target[key]; // 不是target.key
    },
    set: function(target, key, value) {
        console.log('setting '+key);
        target[key] = value;
    }
}
let proxy = new Proxy(target, handler)
proxy.name     // 實際執行 handler.get
proxy.age = 25 // 實際執行 handler.set
// getting name
// setting age
// 25

注意:通過構造函數新建實例時其實是對目標對象進行了淺拷貝,因此目標對象與代理對象會互相影響

target 即目標對象, handler 是一個對象,聲明瞭代理 target 的指定行爲

  1. get(target, propKey, receiver)

  2. set(target, propKey, value, receiver)//receiver 表示原始操作行爲所在對象,一般是 Proxy 實例本身。

  3. ownKeys(target)//用於攔截對象自身屬性的讀取操作。主要包括以下操作:

  4. apply(target, ctx, args)//用於攔截函數的調用、call 和 reply 操作。target 表示目標對象,ctx 表示目標對象上下文,args 表示目標對象的參數數組。

  5. has(target, propKey)//用於攔截 HasProperty 操作,即在判斷 target 對象是否存在 propKey 屬性時,會被這個方法攔截。此方法不判斷一個屬性是對象自身的屬性,還是繼承的屬性。

  6. construct(target, args)//用於攔截 new 命令。返回值必須爲對象。

  7. deleteProperty(target, propKey)//用於攔截 delete 操作,如果這個方法拋出錯誤或者返回 false ,propKey 屬性就無法被 delete 命令刪除。

  8. defineProperty(target, propKey, propDesc)//用於攔截 Object.definePro若目標對象不可擴展,增加目標對象上不存在的屬性會報錯;若屬性不可寫或不可配置,則不能改變這些屬性。

  9. getOwnPropertyDescriptor(target, propKey)//用於攔截 Object.getOwnPropertyD() 返回值爲屬性描述對象或者 undefined 

  10. getPrototypeOf(target)//主要用於攔截獲取對象原型的操作。包括以下操作:

 

Reflect 可以用於獲取目標對象的行爲(內部方法),它與 Object 類似,但是更易讀,爲操作對象提供了一種更優雅的方式。它的方法與 Proxy 是對應的。

 

9、 字符串

  • includes():返回布爾值,判斷是否找到參數字符串。

  • startsWith():返回布爾值,判斷參數字符串是否在原字符串的頭部。

  • endsWith():返回布爾值,判斷參數字符串是否在原字符串的尾部。

  • repeat():字符串重複

  • padStart:返回新的字符串,表示用參數字符串從頭部(左側)補全原字符串。

  • padEnd:返回新的字符串,表示用參數字符串從尾部(右側)補全原字符串。

let string = "apple,banana,orange";
string.includes("banana");     // true
string.startsWith("apple");    // true
string.endsWith("apple");      // false
string.startsWith("banana",6)  // true

模板字符串

模板字符串相當於加強版的字符串,用反引號 `,除了作爲普通字符串,還可以用來定義多行字符串,還可以在字符串中加入變量和表達式。模板字符串中的換行和空格都是會被保留的

let name = "Mike";
let age = 27;
let info = `My Name is ${name},I am ${age+1} years old next year.`
console.log(info);
// My Name is Mike,I am 28 years old next year.

//當模板字符串中帶有變量,會將模板字符串參數處理成多個參數。
function f(stringArr,...values){
 let result = "";
 for(let i=0;i<stringArr.length;i++){
  result += stringArr[i];
  if(values[i]){
   result += values[i];
        }
    }
 return result;
}
let name = 'Mike';
let age = 27;
f`My Name is ${name},I am ${age+1} years old next year.`;
// "My Name is Mike,I am 28 years old next year."
 
f`My Name is ${name},I am ${age+1} years old next year.`;
// 等價於
f(['My Name is',',I am ',' years old next year.'],'Mike',28);

注意:模板字符串中的換行和空格都是會被保留的

 

國際化處理(轉化多國語言)

i18n`Hello ${name}, you are visitor number ${visitorNumber}.`;

 

10、數字

二進制表示法新寫法: 前綴 0b 或 0B 。

常量  

  1. 最小誤差值:        Number.EPSILON 

  2. 最大安全整數    Number.MAX_SAFE_INTEGER   

  3. 最小安全整數     Number.MIN_SAFE_INTEGE

方法

  1. Number.isFinite() //一個數值是否爲有限的

  2. Number.parseInt()//轉換爲整數 ,無法被解析成浮點數,則返回 NaN

  3. Number.isSafeInteger //用於判斷數值是否在安全範圍內。

  4. Number.isInteger  //用於判斷給定的參數是否爲整數。

整數和浮點數採用的是同樣的儲存方法,因此 1 與 1.0 被視爲相同的值

數字處理

  1. Math.trunc:用於返回數字的整數部分。

  2. Math.fround:用於獲取數字的32位單精度浮點數形式。

  3. Math.sign:判斷數字的符號(正、負、0)

 

11、ES6 對象

屬性的簡潔表示法 ,ES6允許對象的屬性直接寫變量,這時候屬性名是變量名,屬性值是變量值。

const age = 12;
const name = "Amy";
const person = {age, name};
person   //{age: 12, name: "Amy"}
//等同於
const person = {age: age, name: name}

方法名也可以簡寫,如果是Generator 函數,則要在前面加一個星號:

 

ES6允許用表達式作爲屬性名,但是一定要將表達式放在方括號內。

const obj = {
 ["he"+"llo"](){
   return "Hi";
  }
}
obj.hello();  //"Hi"

注意點:屬性的簡潔表示法和屬性名錶達式不能同時使用,否則會報錯。

 

拓展運算符(...)

用於取出參數對象所有可遍歷屬性然後拷貝到當前對象。

可用於合併兩個對象
let age = {age: 15};
let name = {name: "Amy"};
let person = {...age, ...name};
person;  //{age: 15, name: "Amy"}

對象的新方法

  • Object.assign(target, source_1, ···)用於將源對象的所有可枚舉屬性複製到目標對象中。

              assign 的屬性拷貝是淺拷貝,同名屬性後面的替換前面的

  • Object.is(value1, value2)用來比較兩個值是否嚴格相等,與(===)基本類似。
基本用法

Object.is("q","q");      // true
Object.is(1,1);          // true
Object.is([1],[1]);      // false
Object.is({q:1},{q:1});  // false
與(===)的區別

//一是+0不等於-0
Object.is(+0,-0);  //false
+0 === -0  //true
//二是NaN等於本身
Object.is(NaN,NaN); //true
NaN === NaN  //false

 

 

12、數組

  • Array.of()將參數中所有值作爲元素形成數組。

  • Array.from(arrayLike[, mapFn[, thisArg]]) 將類數組對象或可迭代對象轉化爲數組。

   arrayLike 想要轉換的類數組對象或可迭代對象。

        mapFn 可選,map 函數,用於對每個元素進行處理,放入數組的是處理後的元素。

        thisArg 可選,用於指定 map 函數執行時的 this 對象。

let map = {
    do: function(n) {
        return n * 2;
    }
}
let arrayLike = [1, 2, 3];
console.log(Array.from(arrayLike, function (n){
    return this.do(n);
}, map)); // [2, 4, 6]

類數組對象

一個類數組對象必須含有 length 屬性,且元素屬性名必須是數值或者可轉換爲數值的字符。

 

擴展方法

find()查找數組中符合條件的元素,若有多個符合條件的元素,則返回第一個元素。

findIndex()查找數組中符合條件的元素索引,若有多個符合條件的元素,則返回第一個元素索引。

let arr = Array.of(1, 2, 1, 3);
// 參數1:回調函數
// 參數2(可選):指定回調函數中的 this 值
console.log(arr.findIndex(item => item = 1)); // 0
 
// 數組空位處理爲 undefined
console.log([, 1].findIndex(n => true)); //0

fill()  將一定範圍索引的數組元素內容填充爲單個指定的值。

let arr = Array.of(1, 2, 3, 4);
// 參數1:用來填充的值
// 參數2:被填充的起始索引
// 參數3(可選):被填充的結束索引,默認爲數組末尾
console.log(arr.fill(0,1,2)); // [1, 0, 3, 4]

copyWithin()  將一定範圍索引的數組元素修改爲此數組另一指定範圍索引的元素。

 

// 參數1:被修改的起始索引
// 參數2:被用來覆蓋的數據的起始索引
// 參數3(可選):被用來覆蓋的數據的結束索引,默認爲數組末尾
console.log([1, 2, 3, 4].copyWithin(0,2,4)); // [3, 4, 3, 4]
 
// 參數1爲負數表示倒數
console.log([1, 2, 3, 4].copyWithin(-2, 0)); // [1, 2, 1, 2]
 
console.log([1, 2, ,4].copyWithin(0, 2, 4)); // [, 4, , 4]

includes()數組是否包含指定值。

flat()嵌套數組轉一維數組

flatMap()  先對數組中每個元素進行了的處理,再對數組執行 flat() 方法。

// 參數1:遍歷函數,該遍歷函數可接受3個參數:當前元素、當前元素索引、原數組
// 參數2:指定遍歷函數中 this 的指向
console.log([1, 2, 3].flatMap(n => [n * 2])); // [2, 4, 6]

複製數組

let arr = [1, 2],
    arr1 = [...arr];
console.log(arr1); // [1, 2]
 
// 數組含空位
let arr2 = [1, , 3],
    arr3 = [...arr2];
console.log(arr3); [1, undefined, 3]

合併數組
console.log([...[1, 2],...[3, 4]]); // [1, 2, 3, 4]

 

 

13、函數

默認參數 

function fn(name,age=17){
 console.log(name+","+age);
}
fn("Amy",18);  // Amy,18
fn("Amy","");  // Amy,
fn("Amy");     // Amy,17

只有在未傳遞參數,或者參數爲 undefined 時,纔會使用默認參數,null 值被認爲是有效的值傳遞。

注意點:使用函數默認參數時,不允許有同名參數。

不定參數

不定參數用來表示不確定參數個數,形如,...變量名,由...加上一個具名參數標識符組成。具名參數只能放在參數組的最後,並且有且只有一個不定參數。

箭頭函數

箭頭函數體中的 this 對象,是定義函數時的對象,而不是使用函數時的對象。

//適合使用的場景

// 回調函數
var Person = {
    'age': 18,
    'sayHello': function () {
      setTimeout(function () {
        console.log(this.age);
      });
    }
};
var age = 20;
Person.sayHello();  // 20
 
var Person1 = {
    'age': 18,
    'sayHello': function () {
      setTimeout(()=>{
        console.log(this.age);
      });
    }
};
var age = 20;
Person1.sayHello();  // 18

//不適合使用的場景
//定義函數的方法,且該方法中包含 this

var Person = {
    'age': 18,
    'sayHello': ()=>{
        console.log(this.age);
      }
};
var age = 20;
Person.sayHello();  // 20
// 此時 this 指向的是全局對象
 
var Person1 = {
    'age': 18,
    'sayHello': function () {
        console.log(this.age);
    }
};
var age = 20;
Person1.sayHello();   // 18
// 此時的 this 指向 Person1 對象

 

 

14、迭代器

Iterator 是 ES6 引入的一種新的遍歷機制,迭代器有兩個核心概念:

  • 迭代器是一個統一的接口,它的作用是使各種數據結構可被便捷的訪問,它是通過一個鍵爲Symbol.iterator 的方法來實現。

  • 迭代器是用於遍歷數據結構元素的指針(如數據庫中的遊標)。

可迭代的值:

  • Array
  • String
  • Map
  • Set

普通對象不可迭代

of 操作數必須是可迭代,這意味着如果是普通對象則無法進行迭代。如果數據結構類似於數組的形式,則可以藉助 Array.from() 方法進行轉換迭代

const arrayLink = {length: 2, 0: "zero", 1: "one"}
// 報 TypeError 異常
for (let item of arrayLink) {
  console.log(item);
}
 
// 正常運行
// output:
// zero
// one
for (let item of Array.from(arrayLink)) {
  console.log(item);
}

 

 

15、Class 類

class (類)作爲對象的模板被引入,可以通過 class 關鍵字定義類。

class 的本質是 function。

它可以看作一個語法糖,讓對象原型的寫法更加清晰、更像面向對象編程的語法。

// 匿名類
let Example = class {
    constructor(a) {
        this.a = a;
    }
}
// 命名類
let Example = class Example {
    constructor(a) {
        this.a = a;
    }
}

類定義不會被提升,這意味着,必須在訪問前對類進行定義,否則就會報錯。

類中方法不需要 function 關鍵字。

方法間不能加分號。

  • name:屬性返回跟在 class 後的類名(存在時)。

  • constructor:方法 類的默認方法,創建類的實例化對象時被調用。

  • new :class 的實例化必須通過 new 關鍵字。

  • extends:通過 extends 實現類的繼承。

 

 

16、export 與 import

導出(export) @與導入(import)兩個模塊。

模塊導入導出各種類型的變量,如字符串,數值,函數,類。

  • 導出的函數聲明與類聲明必須要有名稱(export default 命令另外考慮)。 

  • 不僅能導出聲明還能導出引用(例如函數)。

  • export 命令可以出現在模塊的任何位置,但必需處於模塊頂層。

  • import 命令會提升到整個模塊的頭部,首先執行。

/*-----export [test.js]-----*/
let myName = "Tom";
let myAge = 20;
let myfn = function(){
    return "My name is" + myName + "! I'm '" + myAge + "years old."
}
let myClass =  class myClass {
    static a = "yeah!";
}
export { myName, myAge, myfn, myClass }
 
/*-----import [xxx.js]-----*/
import { myName, myAge, myfn, myClass } from "./test.js";
console.log(myfn());// My name is Tom! I'm 20 years old.
console.log(myAge);// 20
console.log(myName);// Tom
console.log(myClass.a );// yeah!
//建議使用大括號指定所要輸出的一組變量寫在文檔尾部,明確導出的接口。
//函數與類都需要有對應的名稱,導出文檔尾部也避免了無對應名稱。

 

import 命令的特點

  • 只讀屬性:不允許在加載模塊的腳本里面,改寫接口的引用指向,即可以改寫 import 變量類型爲對象的屬性值,不能改寫 import 變量類型爲基本類型的值。

  •  單例模式:多次重複執行同一句 import 語句,那麼只會執行一次,而不會執行多次。import 同一模塊,聲明不同接口引用,會聲明對應變量,但只執行一次 import 。

  •  靜態執行特性:import 是靜態執行,所以不能使用表達式和變量。

export default 命令

  • 在一個文件或模塊中,export、import 可以有多個,export default 僅有一個。

  • export default 中的 default 是對應的導出接口變量。

  • 通過 export 方式導出,在導入時要加{ },export default 則不需要。

  • export default 向外暴露的成員,可以使用任意變量來接收。

 

 17、Promise 對象

Promise 異步操作有三種狀態:pending(進行中)、fulfilled(已成功)和 rejected(已失敗)。除了異步操作的結果,任何其他操作都無法改變這個狀態。

Promise 對象只有:從 pending 變爲 fulfilled 和從 pending 變爲 rejected 的狀態改變。只要處於 fulfilled 和 rejected ,狀態就不會再變了即 resolved(已定型)。

const p1 = new Promise(function(resolve,reject){
    resolve('success1');
    resolve('success2');
}); 
const p2 = new Promise(function(resolve,reject){  
    resolve('success3'); 
    reject('reject');
});
p1.then(function(value){  
    console.log(value); // success1
});
p2.then(function(value){ 
    console.log(value); // success3
});

狀態的缺點:

無法取消 Promise ,一旦新建它就會立即執行,無法中途取消。

如果不設置回調函數,Promise 內部拋出的錯誤,不會反應到外部。

當處於 pending 狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。

then 方法

then 方法接收兩個函數作爲參數,第一個參數是 Promise 執行成功時的回調,第二個參數是 Promise 執行失敗時的回調,兩個函數只會有一個被調用。

在 JavaScript 事件隊列的當前運行完成之前,回調函數永遠不會被調用。


const p = new Promise(function(resolve,reject){
  resolve('success');
});
 
p.then(function(value){
  console.log(value);
});
 
console.log('first');
// first
// success

注意點

簡便的 Promise 鏈式編程最好保持扁平化,不要嵌套 Promise。

注意總是返回或終止 Promise 鏈。

 

18、Generator 函數

ES6 新引入了 Generator 函數,可以通過 yield 關鍵字,把函數的執行流掛起,爲改變執行流程提供了可能,從而爲異步編程提供解決方案。Generator 有兩個區分於普通函數的部分:

  • 一是在 function 後面,函數名之前有個 * ;

  • 函數內部有 yield 表達式。

其中 * 用來表示函數爲 Generator 函數,yield 用來定義函數內部的狀態。

function* func(){
 console.log("one");
 yield '1';
 console.log("two");
 yield '2'; 
 console.log("three");
 return '3';
}

執行機制

調用 Generator 函數和調用普通函數一樣,在函數名後面加上()即可,但是 Generator 函數不會像普通函數一樣立即執行,而是返回一個指向內部狀態對象的指針,所以要調用遍歷器對象Iterator 的 next 方法,指針就會從函數頭部或者上一次停下來的地方開始執行

f.next();
// one
// {value: "1", done: false}
 
f.next();
// two
// {value: "2", done: false}
 
f.next();
// three
// {value: "3", done: true}
 
f.next();
// {value: undefined, done: true}

 

 

19、async 函數

 ES7 纔有的與異步操作有關的關鍵字,和 Promise , Generator 有很大關聯的。

async function name([param[, param[, ... param]]]) { statements }

  • name: 函數名稱。

  • param: 要傳遞給函數的參數的名稱。

  • statements: 函數體語句。

sync 函數中可能會有 await 表達式,async 函數執行時,如果遇到 await 就會先暫停執行 ,等到觸發的異步操作完成後,恢復 async 函數的執行並返回解析值。

await 關鍵字僅在 async function 中有效 ,await 操作符用於等待一個 Promise 對象, 它只能在異步函數 async function 內部使用。

function testAwait (x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}
 
async function helloAsync() {
  var x = await testAwait ("hello world");
  console.log(x); 
}
helloAsync ();
// hello world

返回值

返回 Promise 對象的處理結果。如果等待的不是 Promise 對象,則返回該值本身。

如果一個 Promise 被傳遞給一個 await 操作符,await 將等待 Promise 正常處理完成並返回其處理結果。 

function testAwait (x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}
 
async function helloAsync() {
  var x = await testAwait ("hello world");
  console.log(x); 
}
helloAsync ();
// hello world

await針對所跟不同表達式的處理方式:

  • Promise 對象:await 會暫停執行,等待 Promise 對象 resolve,然後恢復 async 函數的執行並返回解析值。
  • 非 Promise 對象:直接返回對應的值。

 

 

 

 

 

 

 

 

 

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章