1. 程式人生 > >談談JavaScript版本演進史及ES3、ES5區別和特性

談談JavaScript版本演進史及ES3、ES5區別和特性

根據RedMonk釋出的2018年初程式語言排行榜顯示,JavaScript高居榜首,說明JavaScript的火熱程度,其從90年代初誕生到現在經歷了幾個大的版本迭代:

  • ES3,JavaScript 的第三版,從 1999 年開始
  • ES5,2009 年釋出
  • ES6,2015年6月17日,ECMAScript 6釋出正式版本,即ECMAScript 2015

作為開發人員,我們需要擁抱變化,掌握並使用新版本,同時也要了解版本之間的差異,評估歷史遺留程式碼是不是需要改進、甚至重構。本文討論ES5的新特性及ES3和ES5的區別。

1、保留關鍵字

Javascript 的保留關鍵字不可以用作變數、標籤或者函式名。有些保留關鍵字是作為 Javascript 以後擴充套件使用。ES5較ES3新添加了幾個保留關鍵字:
1)class:類,ES6引入
2)const:常量,ES6引入
3)enum:
4)extends:類繼承,ES6引入
5)import:模組匯入,ES6引入
6)export:模組匯出,ES6引入
7)super:呼叫父類的建構函式,ES6引入

2、瀏覽器相容性

參考:https://caniuse.com/#search=ES5說明
在這裡插入圖片描述
1)ES3,可以認為所有瀏覽器都支援;
2)ES5,現代瀏覽器都支援(>=IE9), IE9不支援嚴格模式。

3、ES5豐富了物件方法、屬性處理

1)ES5屬性增加getter、setter儲存器,看個demo就明白了:

// ES3
var o = (function(){
    var age = 0;
    return {
        get_age:function(){ return age; },
        set_age:function(v){ age =
v; } } })(); console.log(o.get_age()); // 0 o.set_age(12); console.log(o.get_age()); // 12 // ES5 var o = (function(){ var age = 0; return { get age (){return age;}, set age (v){ age = v; } } })(); console.log(o.age); // 0 o.age =12; console.log
(o.age); // 12

2)ES5屬性增加可讀寫、可遍歷、是否可刪除設定,看個案例:

  • Configurable:表示能否通過delete刪除屬性或者刪除後從新定義值,或者能把屬性修改為訪問器屬性,預設true。
  • Enumerable:表示能否通過for-in遍歷屬性的值,預設為true。
  • Writable:表示能否直接定義屬性的值,預設為true。
  • Value:表示屬性對應的值,預設值為undefined。
var o5={}
Object.defineProperty(o5,"name",{
	writable:false, 		//可賦值?
	configurable:false, 	//可刪除?
	enumerable:true,		//可遍歷?
	value:"oes5" 			//當前name屬性的具體值
})
console.log(o5.name)		//oes5	

o5.name="321"				
console.log(o5.name)		//writable為false, 賦值失效, name依然為"oes5"

delete o5.name
console.log(o5.name)		//因為configurable為false所以不能刪除, name依然為“oes5”

3)Object增加了很多方法

  • Object.defineProperties(obj, propName, descriptorSet) 定義物件屬性,上文DEMO已經提及
  • Object.create(protoObj, descriptorSet),物件建立函式,一個很關鍵的函式,可以解決物件繼承問題;
  • Object.getOwnPropertyNames(obj),獲取物件自有屬性名稱
  • Object.getPrototypeOf(obj),獲取物件原型物件,=== obj.proto
  • Object.getOwnPropertyDescriptor(obj, propName),獲取屬性定義描述物件{configurable,enumerable,value,writable}
  • Object.preventExtensions(obj),阻止物件擴充套件,物件不能增加新屬性
  • Object.isExtensible(obj),判斷物件是否可擴充套件
  • Object.seal(obj),密封物件,保護物件屬性除值外,其餘定義屬性都不能修改,也不能新增、刪除屬性;
  • Object.isSealed(obj):判斷物件是否被密封;
  • Object.freeze(obj):物件凍結,物件屬性不能修改,包括值;
  • Object.isFrozen(obj):判斷物件是否被凍結;
  • Object.keys(obj):獲取物件可列舉的自有屬性名稱,是getOwnPropertyNames(obj)的子集。

4、ES5的函式特性,新增bind方法

參考MDN web docs,The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
The bind() 建立了一個新function,this執行bind物件,看個DEMO。

var module = {
     x: 42,
     getX: function() {
       return this.x;
     }
   }
var unboundGetX = module.getX;
console.log(unboundGetX()); 	//全域性作用域, ->undefiend

var boundGetX = unboundGetX.bind(module);	//bind, this->module
console.log(boundGetX());						//this.x = module.x = 42

ES3中,我們可以通過apply或者call實現bind操作。

5、ES5 陣列增加很多方法

2個索引方法:indexOf() 和 lastIndexOf();
5個迭代方法:forEach()、map()、filter()、some()、every();
2個歸併方法:reduce()、reduceRight(),具體如下:

  • Array.prototype.indexOf()
    Returns the first (least) index of an element within the array equal to the specified value, or -1 if none is found.
  • Array.prototype.lastIndexOf
    Returns the last (greatest) index of an element within the array equal to the specified value, or -1 if none is found.
  • Array.prototype.every
    Returns true if every element in this array satisfies the provided testing function.
  • Array.prototype.some
    Returns true if at least one element in this array satisfies the provided testing function.
  • Array.prototype.forEach
    Calls a function for each element in the array.
  • Array.prototype.map
    Creates a new array with the results of calling a provided function on every element in this array.
  • Array.prototype.filter
    Creates a new array with all of the elements of this array for which the provided filtering function returns true.
  • Array.prototype.reduce
    Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value.
  • Array.prototype.reduceRight
    Apply a function against an accumulator and each value of the array (from right-to-left) as to reduce it to a single value.
    看個DEMO。
var dataArray = [1, 7, 5, 6, 1, 7, 3];
console.log(dataArray.indexOf(7));          // 1 預設從0即第一項開始查詢
console.log(dataArray.indexOf('7'));        // -1, ===比較,7!=='7'
console.log(dataArray.indexOf(7, 's'));     // 1 格式不正確, 從第一項開始查詢
console.log(dataArray.indexOf(7, 2));       // 5 從第三個項開始查詢

console.log(dataArray.lastIndexOf (7));     // 5 預設從末尾第一項開始查詢
console.log(dataArray.lastIndexOf (7, 's'));// -1 格式不正確, 從第一項開始查詢
console.log(dataArray.lastIndexOf (7, 2));  // 1 從末尾第三項往前查詢

// 陣列每個元素是否>1
var every_rst = dataArray.every(function(ele) {
	return ele > 1;
})
console.log("every_rst: ", every_rst);

//陣列是否有元素>5
var some_rst = dataArray.some(function(ele) {
	return ele > 5;
})
console.log("some_rst: ", some_rst);

var filter_rst = dataArray.filter(function(ele) {
	return ele > 5;
})
console.log("filter_rst: ", filter_rst);

var map_rst = dataArray.map(function(ele) {
	return ele + 5;
})
console.log("filter_rst: ", map_rst);

var forEach_rst = "";
dataArray.forEach(function(ele, index) {
	forEach_rst += (index == 0) ? ele : ',' + ele;
});
console.log("forEach_rst: ", forEach_rst);

var reduce_rst = dataArray.reduce(function(prev, cur) {
	return prev + cur
});
console.log("reduce_rst: ", reduce_rst);
// reduceRight,從右向左

6、JSON

ES5提供一個內建的(全域性)JSON物件,可用來序列化( JSON.stringfy )和反序列化( parse )物件為JSON格式。

  • JSON.stringify(),js物件轉換成json字串
  • JSON.parse(),解析json字串,構建js物件,看個DEMO。
var jsonObj = { x: 5, y: 6 };
var jsonStr = JSON.stringify(jsonObj);
var jsonObj2 = JSON.parse(jsonStr);
console.log(jsonStr);	//{"x":5,"y":6}
console.log(jsonObj2, jsonObj == jsonObj2);//Object { x: 5, y: 6 } false

7、Strict Mode

In ES3 or ES5-nonstrict, Failure is silent. Execution will proceed assuming success. And we can’t check after every assignment to see if it succeeded. In ES5, Failed assignments throw. A subset intended to provide more thorough error checking and avoid error-prone constructs.
ES5引入了嚴格模式,預設不啟用,可以通過2種生效方式:

  • 全域性生效,包括通過src引入的js檔案,在js程式碼第一行 “use strict”;
  • 函式生效,函式第一行 “use strict”;
    關於Javascript嚴格模式詳細說明,大家可以參考:
    1)Javascript 嚴格模式詳解
    2)MDN web docs: Strict mode

啟用嚴格模式後,js程式碼語法和行為將會發生一定改變,具體可以參考上述兩篇博文,其中this為undefined時,不再指向global,本文之前的一個DEMO在嚴格模式下,js會報錯。

	"use strict";
	var module = {
		  x: 42,
		  getX: function() {
		    return this.x;
		  }
		}

	var unboundGetX = module.getX;
	console.log(unboundGetX()); 	//全域性作用域, ->undefiend

	var boundGetX = unboundGetX.bind(module);	//bind, this->module
	console.log(boundGetX());					//this.x = module.x = 42

執行該段程式碼,會報 TypeError: this is undefined,原因:
非嚴格模式下,this為undefined時,會指向global;而嚴格模式下不會,所以取this.x值就報錯了。