vue項目開發前的es6的知識儲備


 let命令 學習筆記

1、let所聲明的變量,只在let命令所在的代碼塊內有效。

2、不存在變量提升:所聲明的變量一定要在聲明后使用,否則報錯。

  一定要先聲明,再去使用。let x=x;這樣就是錯誤的

ES6明確規定,如果區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。

 3、不允許重復聲明:let不允許在相同作用域內,重復聲明同一個變量。即不能在函數內部重新聲明參數。

塊級作用域

1、為什么需要塊級作用域?

  ES5 只有全局作用域和函數作用域,沒有塊級作用域,這帶來很多不合理的場景。
  第一種場景,內層變量可能會覆蓋外層變量。

var tmp = new Date();
function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world';
  }
}
f(); // undefined

  第二種場景,用來計數的循環變量泄露為全局變量。下面代碼中,變量i只用來控制循環,但是循環結束后,它並沒有消失,泄露成了全局變量

var s = 'hello';
for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}
console.log(i); // 5

2、ES6 的塊級作用域:外層作用域無法讀取內層作用域的變量。內層作用域可以定義外層作用域的同名變量。

  下面的函數有兩個代碼塊,都聲明了變量n,運行后輸出5。這表示外層代碼塊不受內層代碼塊的影響。如果兩次都使用var定義變量n,最后輸出的值才是10。

function f1() {
  let n = 5;
  if (true) {
    let n = 10;
    console.log(n);
  }
  console.log(n); // 5
}
f1()

   塊級作用域的出現,實際上使得獲得廣泛應用的立即執行函數表達式(IIFE)不再必要了。

// IIFE 寫法
(function () {
  var tmp = ...;
  ...
}());

// 塊級作用域寫法
{
  let tmp = ...;
  ...
}

  塊級作用域用法:考慮到環境導致的行為差異太大,應該避免在塊級作用域內聲明函數。如果確實需要,也應該寫成函數表達式,而不是函數聲明語句

// 函數聲明語句
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// 函數表達式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}

  ES6 的塊級作用域允許聲明函數的規則,只在使用大括號的情況下成立,如果沒有使用大括號,就會報錯。

3、do 表達式 

  本質上,塊級作用域是一個語句,將多個操作封裝在一起,沒有返回值。想要解決方法:使得塊級作用域可以變為表達式,也就是說可以返回值,辦法就是在塊級作用域之前加上do,使它變為do表達式,然后就會返回內部最后執行的表達式的值。

let x = do {
  let t = f();
  t * t + 1;
};

 const 命令

  const聲明一個只讀的常量。一旦聲明,常量的值就不能改變。const一旦聲明變量,就必須立即初始化,不能留到以后賦值。

  const的作用域與let命令相同:只在聲明所在的塊級作用域內有效。

   const命令聲明的常量也是不提升,同樣存在暫時性死區,只能在聲明的位置后面使用。

  const聲明的常量,也與let一樣不可重復聲明。

箭頭函數

  1、省略了function,花括號‘{}’用‘=>’代替了。這種寫法更簡潔了。

  2、優點,就是函數體內的this的指向始終是指向定義它所在的對象,而不會指向調用它的對象,我們知道es5中的函數是誰執行它,它就指向誰。

  參考:es6箭頭函數講解   es6學習筆記10--箭頭函數

ES6---數組array新增方法 

   參考:http://blog.csdn.net/wbiokr/article/details/65939582

Promise 對象

  一、Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。Promise對象是一個構造函數,用來生成Promise實例.

    補充知識:與 ‘new’ 運算符一起使用用來創建對象並初始化對象的‘函數’就是構造函數; 實例化(在面向對象的編程中,通常把用類創建對象的過程稱為實例化。)對象就是創建對象的過程!

var request = new XMLHttpRequest();

    “new XMLHttpRequest();” 這句話就是一個標准的構造函數!我們 “var” 聲明了一個 “request” 對象,用構造函數 “new XMLHttpRequest();” 來初始化這個 “request” 對象為它賦初始值。

  所謂Promise,簡單說就是一個容器,里面保存着某個未來才會結束的事件(通常是一個異步操作)的結果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。

  二、Promise對象有以下兩個特點。

       (1)對象的狀態不受外界影響。Promise對象代表一個異步操作,有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。

       (2)一旦狀態改變,就不會再變,任何時候都可以得到這個結果。Promise對象的狀態改變,只有兩種可能:從pending變為fulfilled和從pending變為rejected。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果,這時就稱為 resolved(已定型)。如果改變已經發生了,你再對Promise對象添加回調函數,也會立即得到這個結果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的。

  Promise對象有缺點:

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

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

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

  下面代碼創造了一個Promise實例。

var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 異步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

  Promise構造函數接受一個函數作為參數,該函數的兩個參數分別是resolvereject。它們是兩個函數,由 JavaScript 引擎提供,不用自己部署。

  Promise實例生成以后,可以用then方法分別指定resolved狀態和rejected狀態的回調函數。

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});

 下面是一個Promise對象的簡單例子。

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}

timeout(100).then((value) => {
  console.log(value);
});

  上面代碼中,timeout方法返回一個Promise實例,表示一段時間以后才會發生的結果。過了指定的時間(ms參數)以后,Promise實例的狀態變為resolved,就會觸發then方法綁定的回調函數。一般情況不調用setTimeout指定時間,Promise 新建后就會立即執行。

三、Promise.prototype.then()

  then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。因此可以采用鏈式寫法,即then方法后面再調用另一個then方法。

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function funcA(comments) {
  console.log("resolved: ", comments);
}, function funcB(err){
  console.log("rejected: ", err);
});

上面代碼中,第一個then方法指定的回調函數,返回的是另一個Promise對象。這時,第二個then方法指定的回調函數,就會等待這個新的Promise對象狀態發生變化。如果變為resolved,就調用funcA,如果狀態變為rejected,就調用funcB。如果采用箭頭函數,上面的代碼可以寫得更簡潔。

getJSON("/post/1.json").then(
  post => getJSON(post.commentURL)
).then(
  comments => console.log("resolved: ", comments),
  err => console.log("rejected: ", err)
);

四、Promise.prototype.catch()

  Promise.prototype.catch方法是.then(null, rejection)的別名,用於指定發生錯誤時的回調函數。

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 處理 getJSON 和 前一個回調函數運行時發生的錯誤
  console.log('發生錯誤!', error);
});

  上面代碼中,getJSON方法返回一個 Promise 對象,如果該對象狀態變為resolved,則會調用then方法指定的回調函數;如果異步操作拋出錯誤,狀態就會變為rejected,就會調用catch方法指定的回調函數,處理這個錯誤。另外,then方法指定的回調函數,如果運行中拋出錯誤,也會被catch方法捕獲。

getJSON('/post/1.json').then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // some code
}).catch(function(error) {
  // 處理前面三個Promise產生的錯誤
});

  Promise 對象的錯誤具有“冒泡”性質,會一直向后傳遞,直到被捕獲為止。也就是說,錯誤總是會被下一個catch語句捕獲。

  一般來說,不要在then方法里面定義Reject狀態的回調函數(即then的第二個參數),總是使用catch方法。

// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });

  上面代碼中,第二種寫法要好於第一種寫法,理由是第二種寫法可以捕獲前面then方法執行中的錯誤,也更接近同步的寫法(try/catch)。因此,建議總是使用catch方法,而不使用then方法的第二個參數。

const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行會報錯,因為x沒有聲明
    resolve(x + 2);
  });
};

someAsyncThing().then(function() {
  console.log('everything is great');
});

setTimeout(() => { console.log(123) }, 2000);
// Uncaught (in promise) ReferenceError: x is not defined
// 123

  上面代碼中,someAsyncThing函數產生的 Promise 對象,內部有語法錯誤。瀏覽器運行到這一行,會打印出錯誤提示ReferenceError: x is not defined,但是不會退出進程、終止腳本執行,2秒之后還是會輸出123。這就是說,Promise 內部的錯誤不會影響到 Promise 外部的代碼,通俗的說法就是“Promise 會吃掉錯誤”。

  一般總是建議,Promise 對象后面要跟catch方法,這樣可以處理 Promise 內部發生的錯誤catch方法返回的還是一個 Promise 對象,因此后面還可以接着調用then方法

五、Promise.all() 

  Promise.all方法用於將多個 Promise 實例,包裝成一個新的 Promise 實例。

   var p = Promise.all([p1, p2, p3]); 

  Promise.all方法接受一個數組作為參數,p1p2p3都是 Promise 實例,如果不是,就會先調用下面講到的Promise.resolve方法,將參數轉為 Promise 實例,再進一步處理。

  p的狀態由p1、p2、p3決定,分成兩種情況:
    (1)只有p1、p2、p3的狀態都變成fulfilled,p的狀態才會變成fulfilled,此時p1、p2、p3的返回值組成一個數組,傳遞給p的回調函數。
    (2)只要p1、p2、p3之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數。

六、Promise.race()

  Promise.race方法同樣是將多個Promise實例,包裝成一個新的Promise實例。

   var p = Promise.race([p1, p2, p3]); 上面代碼中,只要p1p2p3之中有一個實例率先改變狀態,p的狀態就跟着改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數。

七、Promise.resolve() 

  有時需要將現有對象轉為Promise對象,Promise.resolve方法就起到這個作用。

八、模塊語法

  1、ES6 在語言標准的層面上,實現了模塊功能,而且實現得相當簡單,完全可以取代 CommonJS 和 AMD 規范,成為瀏覽器和服務器通用的模塊解決方案。

  ES6 模塊不是對象,而是通過export命令顯式指定輸出的代碼,再通過import命令輸入

// ES6模塊
import { stat, exists, readFile } from 'fs';

  上面代碼的實質是從fs模塊加載3個方法,其他方法不加載。這種加載稱為“編譯時加載”或者靜態加載,即 ES6 可以在編譯時就完成模塊加載,效率要比 CommonJS 模塊的加載方式高。

  2、嚴格模式

    • 變量必須聲明后再使用
    • 函數的參數不能有同名屬性,否則報錯
    • 不能使用with語句
    • 不能對只讀屬性賦值,否則報錯
    • 不能使用前綴0表示八進制數,否則報錯
    • 不能刪除不可刪除的屬性,否則報錯
    • 不能刪除變量delete prop,會報錯,只能刪除屬性delete global[prop]  
    • eval不會在它的外層作用域引入變量
    • evalarguments不能被重新賦值
    • arguments不會自動反映函數參數的變化
    • 不能使用arguments.callee
    • 不能使用arguments.caller
    • 禁止this指向全局對象
    • 不能使用fn.callerfn.arguments獲取函數調用的堆棧
    • 增加了保留字(比如protectedstaticinterface

  尤其需要注意this的限制。ES6 模塊之中,頂層的this指向undefined,即不應該在頂層代碼使用this。

  3、export 命令

  模塊功能主要由兩個命令構成:exportimportexport命令用於規定模塊的對外接口,import命令用於輸入其他模塊提供的功能。

  一個模塊就是一個獨立的文件。該文件內部的所有變量,外部無法獲取。如果你希望外部能夠讀取模塊內部的某個變量,就必須使用export關鍵字輸出該變量。下面是一個 JS 文件,里面使用export命令輸出變量。

// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {firstName, lastName, year};

   export命令除了輸出變量,還可以輸出函數或類(class)。下面代碼對外輸出一個函數multiply

export function multiply(x, y) {
  return x * y;
};

  export輸出的變量就是本來的名字,但是可以使用as關鍵字重命名。

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion
};

  上面代碼使用as關鍵字,重命名了函數v1v2的對外接口。重命名后,v2可以用不同的名字輸出兩次。需要特別注意的是export命令規定的是對外的接口,必須與模塊內部的變量建立一一對應關系。

// 寫法一
export var m = 1;

// 寫法二
var m = 1;
export {m};

// 寫法三
var n = 1;
export {n as m};

  上面三種寫法都是正確的,規定了對外的接口m。其他腳本可以通過這個接口,取到值1。它們的實質是,在接口名與模塊內部變量之間,建立了一一對應的關系。functionclass的輸出,也必須遵守這樣的寫法。

   另外,export語句輸出的接口,與其對應的值是動態綁定關系,即通過該接口,可以取到模塊內部實時的值。

export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);

  上面代碼輸出變量foo,值為bar,500毫秒之后變成bazexport命令可以出現在模塊的任何位置,只要處於模塊頂層就可以。如果處於塊級作用域內,就會報錯

  3、import 命令

  使用export命令定義了模塊的對外接口以后,其他 JS 文件就可以通過import命令加載這個模塊。

// main.js
import {firstName, lastName, year} from './profile';

function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}

  import命令接受一對大括號,里面指定要從其他模塊導入的變量名。大括號里面的變量名,必須與被導入模塊(profile.js)對外接口的名稱相同。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM