es6 學習筆記(一)
環境搭建和簡單實踐
怎麽es6還要環境搭建呢?我用的還是javascript嗎?然而不是這麽一回事。
es6在語法上有很多的變化,算是脫胎換骨了,但是因為瀏覽器還沒有完全支持es6的新語法,所以使用es6開發,就應該先將其轉化為es5,那麽就需要工具來完成,
babel
Babel是一個編譯器,負責將源代碼轉換成指定的語法的目標代碼,可以使之很好的在運行環境中執行我們的代碼。
安裝babel的命令行工具:
//一般要先在當前項目生成一個package.json;然後將babel-cli安裝在本地 ,它只是一個開發依賴。另外不同的項目依賴庫的版本可能都不同,全局的babel-cli庫也不能保證兼容各個項目中其他依賴庫的版本。
$ npm install -D babel-cli;
安裝轉碼規則包,Babel支持很多語法的轉碼,可以選擇集成的。
babel-preset-env 是一個新的 preset,可以根據配置的目標運行環境(environment)自動啟用需要的 babel 插件,babel-preset-env 的工作方式類似 babel-preset-latest,唯一不同的就是 babel-preset-env 會根據配置的 env 只編譯那些還不支持的特性。
$ npm install -D babel-preset-env
然後編譯,
//編譯某個具體的js文件 $ babel index.js --out-file index-compile.js //編譯目錄中所有的js文件並另存到指定目錄 $ babel src --out-dir lib / $ babel src -d lib
每次都這樣做,太繁瑣了?試用一下這條命令。在package.json文件中的script中添加:
"build": "babel src -d lib"
它可以實現簡單的編譯的功能,不過這不是最好的解決方案,
因為Babel 默認只轉換新的 JavaScript 句法(syntax),而不轉換新的 API ,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局對象,以及一些定義在全局對象上的方法(比如 Object.assign)都不會轉碼
為了能夠完全轉換es6的內容,需要安裝babel-polyfill插件
1.先引入webpack,這裏只是因為babel-polyfill可以在Node/Browserify/webpack中使用
//全局安裝,在配置完成後,可以直接通過webpack運行, $ npm install -g webpack //一般會裝在本地項目中,就不能直接使用webpack需要找node_module中的webpack的位置。 $ npm install -D webpack
2.安裝babel-polyfill插件,babel-cli,babel-preset-env
$ npm install -save-dev babel-polyfill babel-cli babel-preset-env
3.在需要的文件中引入babel-polyfill:
import "babel-polyfill";
//node.js中引入:require(‘babel-polyfill‘);
4.配置webpack.config.js文件,將[‘babel-polyfill‘, ‘./src/index.js‘] 寫到entry屬性中。如下
const path = require(‘path‘); module.exports = { entry: [‘babel-polyfill‘, ‘./src/index.js‘], module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" } ] }, output: { filename: ‘bundle.js‘, path: path.resolve(__dirname, ‘dist‘) } };
5.配置.babelrc文件
{ "persets": ["env"]; }
6.啟動webpack
$ webpack
promise
promise是什麽?(來自sf.gg的promise百科)
Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最早提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了 Promise 對象。
所謂 Promise,簡單說就是一個容器,裏面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。
promise方法:
1.構造函數
Promise( function(resolve, reject) { } );
2.實例,構造函數用於生成Promise對象
let promise = new Promise(function(resolve, reject) { });
3.then方法
let promise = function() { return new Promise(function(resolve, reject) { setTimeout(function() {resolve()}) }) } promise() .then(function() { //成功的事 return new Promise(function(resolve, reject) { //異步請求 setTimeout(function() {reslove()}) }) }) .catch(() => { //錯誤處理 }) .then(function() { //成功的事 return new Promise(function(resolve, reject) { //異步請求 setTimeout(function() {reslove()}) }) }) .catch(() => { //錯誤處理 }) .then(function() { })
Promise鏈式調用的原因?
因為Promise.prototype.then方法和Promise.prototype.catch方法都返回Promise對象。所以可以鏈式調用
Promise對象的其他用法。
1.Promise.all()
將多個Promise實例,包裝成一個新的Promise實例
let promise = Promise.all([promiseOne,promiseTwo]);
而且,只有當promiseOne 和 promiseTwo 都成功的時候,promise才會成功
2.Promise.race()
該方法同樣是將多個Promise實例,包裝成一個新的Promise實例。只不過在這種情況下,只要其中一個被成功調用,promise 就會被成功調用。
繼續研究參考:https://segmentfault.com/a/1190000011742644
axios
基於http客戶端的promise,面向瀏覽器和nodejs
安裝:
使用 npm:
$ npm install axios
使用 bower:
$ bower install axios
引入axios.js
在bowe_components中引入axios.js
axios請求
axios.get(‘http://h6.duchengjiu.top/shop/api_goods.php‘) .then(response => { console.log(response.data); });
generator & yield
1.生成器函數(Generator Function)
//聲明式 function* gene() { //... }
//定義式 const gene = function*() { //... }
2.yield
yield的作用與return相似,但是yield不會退出函數體,而是切出當前函數的運行時(此處為一個類協程,Semi-coroutine),並與此同時可以講一個值(可以是任何類型)帶到主線程中。
繼續理解:生成器(Generator)
3.使用方法:
構建生成器函數
function* genFn() { let a = 2 yield a while (true) { yield a = a / (2 * a + 1) } }
執行generator函數
generator函數不能直接作為函數來使用,執行generator函數會返回一個生成器對象,將用於運行生成器內容和接受其中的值。
const gen = genFn()
運行生成器內容
for (const a of gen) { if (a < 1/100) break console.log(a) }
叠代器
1.for-in
都知道for-in循環用來遍歷對象,但是細心的你也會發現,for-in無法控制遍歷的順序,它永遠都是從第一個到最後一個。
2.for-of
for-of是es6的新語法,它用來配合叠代器,叠代對象,我們可以控制叠代順序,
3.Symbol.iterator
對象被叠代的條件是它需要有一個Symbol.iterator屬性,他是一個獨一無二的屬性,暫不詳細介紹。
4.叠代器長啥樣?
iterator[Symbol.iterator] = function () { return { next: function () {} } } //iterator[Symbol.iterator]() 它會返回一個類似於{next: function() {}}對象,原型是Array Iterator let iterator = iterator[Symbol.iterator](); //iterator.next(),會返回一個類似於{value: …, done: [true/false]}的對象, iterator.next();
那麽next()內部大概是這樣的:
table[Symbol.iterator] = function () { var keys = Object.keys(this).sort(); var index = 0; return { next: function () { return { value: keys[index], done: index++ >= keys.length }; } } }
針對對象,自己寫一個叠代器
{ let obj={ start:[1,3,2], end:[7,9,8], [Symbol.iterator](){ let self=this; let index=0; let arr=self.start.concat(self.end); let len=arr.length; return { next(){ if(index<len){ return { value:arr[index++], done:false } } else { return { value:arr[index++], done:true } } } } } // 遍歷叠代器 let iterator = obj[Symbol.iterator](); console.log(iterator); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); }
5.惰性執行:
如果next()函數永遠不被調用的話,我們就浪費了性能。所以讓我們來優化它:
table[Symbol.iterator] = function () { var _this = this; var keys = null; var index = 0; return { next: function () { if (keys === null) { keys = Object.keys(_this).sort(); } return { value: keys[index], done: index++ >= keys.length }; } } }
6.內置叠代器
String,Array,TypedArray,Map和Set都是內置叠代器,因為它們的原型中都有一個Symbol.iterator方法
7.Generator函數
function* iterator(arr) { for(let item of arr) { yield item; } } let iter = iterator([1,2,3,5,6,7]); for(let k of iter) { console.log(k); }
這兩種都可以用來叠代,iter是一個叠代器,像上面我們分析的那樣,
它內部會返回 {next: function() { } }, for-of也是同樣。
//iter.next();
//for(let k of iter) {}
8.iterables
iterable是一個概念,表示有Symbol.iterator屬性的object,
這個屬性指向一個generator函數,調用這個函數,會返回一個關於這個對象的iterator,
在ES6中所有的集合類對象(array, set, maps)和字符串都是iterable,並且有自己默認的iterator,
所以在使用for-of叠代的時候,每次都是利用了對象上的iterator,調用next(),
9.向叠代器中傳遞參數
function* createIterator() { let first = yield 1; let second = yield first + 2; yield second + 3; } let i= createItreator() i.next() // {value:1 done: false} i.next(5) // {value: 7 done: false} i.next(3) // {value: 6 done: false}e}
10.應用實例
function run(taskDef) { let task = taskDef(); let value = task.next() function step() { if (!value.done) { value = task.next(value.value) step() } } step() } run(function*(){ let first = yield 1; let second = yield first + 3; yield second + 4; })
11.應用實例2
es6 學習筆記(一)