javascript
ECMAScript5 严格模式,JSON,及其它
ECMAScript5 嚴格模式,JSON,及其它
ECMAScript5 規范自推出以來, 對javascript的發展產生了蠻大的影響。這篇文章是我翻譯自John Resig(jQuery作者)的一篇博文 ?《ECMAScript 5 Strict Mode, JSON, and More》
----------
之前我分析了ES5的對象和屬性系統。這是這門語言的一大亮點。
同樣有許多其他新特性和API也需要我們注意。最主要的有嚴格模式(Strict Mode)和原生JSON支持(native JSON support)。
嚴格模式(Strict Mode)
嚴格模式在ES5中是個新特性,它允許你在一個“嚴格”的環境中執行你的代碼。嚴格的環境會阻止采用一些特定的代碼行為,拋出更多的異常(總體上說給用戶更多的信息和規范編碼)。
自ES5對ES3進行兼容后,所有在ES3中可以正常使用,但在ES5中注為“不推薦”的特性將在嚴格模式下失效(或者拋出異常)。
嚴格模式將以如下這些方式推進代碼規范:
-
捕獲一些常見的代碼漏洞,拋出異常
-
當一些相對“不安全”的代碼被執行時,進行阻止或拋出異常(例如獲取全局對象訪問)
-
禁掉那些令人疑惑或者欠考慮的特性
大多數關于嚴格模式的信息可以在ES5規范[PDF]223頁找到。
應該注意的是ES5的嚴格模式與FireFox提供的嚴格模式不同(可以通過about:config來啟動javascript.options.strict)。ES5關注編碼規范上的潛在錯誤。(而FireFox的嚴格模式只是強調一些最佳實踐)。
如何啟動嚴格模式?
很簡單。在你的代碼前加上"use strict",為你所有代碼啟動嚴格模式:
| 1 | "use strict"; |
或者只在一個執行上下文內,如:
| 1 2 3 4 | function?imStrict() { ????"use strict"; ????// ... your code... } |
看吧,啟動嚴格模式的語法,不能再簡單了,就一條語句"use strict"就行了。沒有新的語法,不需要什么復雜的配置,并且對老的瀏覽器也沒什么副作用。
ES5并沒有對語言語法進行添加或者更改。所以可以在老瀏覽器中進行優雅降級。
在一個函數中定義嚴格模式,你可以在其中定義自己的javascript庫,而不影響外部的代碼。
| 1 2 3 4 5 6 7 | // Non-strict code... (function() { ????"use strict"; ????? ????// Define your library strictly... })(); // Non-strict code... |
當前很多庫用上面的這種包裹技術(把整個庫包在一個自動執行的匿名函數中)。
那么當你把腳本置于嚴格模式后,會發生什么呢?很多事情
變量和屬性
嘗試賦值foo = 'bar';如果'foo'沒有事先定義,那么將失敗。在這之前,foo會被賦值,并且foo會作為全局對象window的屬性window.foo,現在這會拋出異常。確保避免一些惱人的bug。
對任何writable屬性(attribute)為false的屬性(property)進行寫操作,configurable屬性(attribute)為false的屬性(property)進行刪除操作,extensible屬性(attribute)為false的對象進行添加屬性(property)都會導致報錯。傳統上,當嘗試這些行為時錯誤不會被拋出,將靜靜地失敗。
刪除變量,一個函數,一個參數將導致錯誤。
| 1 2 3 4 5 6 7 8 9 | var?foo =?"test"; function?test() {} delete?foo;???// Error delete?test;??// Error function?test2(arg) { ????delete?arg;???????// Error?????????? } |
在一個字面對象中不止一次定義一個同名屬性,將導致異常拋出
| 1 2 | // Error { foo:?true, foo:?false?} |
eval
幾乎任何嘗試使用'eval'這個名稱的操作都會被禁止.
| 1 2 3 4 5 6 7 8 9 | // All generate errors... obj.eval = ... obj.foo = eval; var?eval = ...; for(var?eval?in?...) {} function?eval() {} function?test(eval) {} function(eval) {} new?Function("eval") |
除此之外,通過eval引入的新變量無效
| 1 2 | eval("var a = false;"); print(typeof?a);?// undefined |
Functions
試圖去覆寫arguments對象將導致出錯:
| 1 | arguments = [...];?// now allowed |
定義同名的參數會導致錯誤:function(foo, foo)
對arguments.caller和arguments.callee的訪問將拋出異常。因此任何你想引用的匿名函數要給個名稱,像這樣:
| 1 2 3 4 | setTimeout(function?later() { ????// do stuff... ????setTimeout(later, 1000); }, 1000); |
其他函數的arguments和caller屬性不在存在,并且定義它們的能力被禁止:
| 1 2 3 4 5 6 7 | function?test() { ????function?inner() { ????????// Don't exist, either ????????test.arguments = ...;?// Error ????????inner.caller = ...;?// Error ????} } |
最后一個長期困擾的(并且很惱人的)bug被解決了:像如下用例中,null或者undefined被強制轉換為全局對象。嚴格模式現在阻止這樣的事情發生,并會拋個異常。
| 1 | (function() { ... }).call(null);?// Exception |
with
with語句在嚴格模式中完全被干掉了,事實上它的出現會作為語法錯誤。
ES5嚴格模式對代碼的改變是多樣的。觀察開發者如何開始采用這些規范和它如何改變javascript開發,將是個有趣的過程。
JSON
ECMAScript語言第二個主要的特性是加入了對JSON的原生支持。
我已經擁護此項推進很久了,如今我很高興的看到它被寫入了規范。
有2個主要的方法用于處理JSON:JSON.parse(把一個JSON字符串轉成一個javascript對象)和JSON.stringify(把一個javascript對象轉成一個序列化的字符串)。
JSON.parse(text)
把一個序列化的JSON字符串轉成一個javascript對象。
| 1 2 3 | var?obj = JSON.parse('{"name": "John"}'); // Prints 'John' print(obj.name); |
JSON.parse(text, translate)
使用一個轉換函數 轉換值或者進行移除
| 1 2 3 4 5 6 7 8 9 10 11 12 | function?translate(key, value) { ????if( key ===?"name") { ????????return?value +?" Resig"; ????} } var?obj = JSON.parse('{"name": "John", "last": "Resig"}', translate); // Prints 'John Resig' print( obj.name ); // Undefined print( obj.last ); |
JSON.stringify(obj)
把一個對象轉成一個序列化的JSON字符串
| 1 2 3 | var?str = JSON.stringify({name:?"John"}); // Prints {"name": "John"} print( str ); |
JSON.stringify(obj, ["white", "list"])
只序列化白名單指定的屬性
| 1 2 3 4 | var?list = ["name"]; var?str = JSON.stringify({name:?"John", last:?"Resig"}, list); // Prints {"name": "John"} print( str ); |
JSON.stringify(obj, translate)
用轉換函數來序列化對象
| 1 2 3 4 5 6 7 8 9 | function?translate(key, value) { ????if(key ===?"name") { ????????return?value +?" Resig"; ????} } var?str = JSON.stringify({"name":?"John",?"last":?"Resig"}, translate); // Prints {"name": "John Resig"} print( str ); |
JSON.stringify(obj, null, 2)
給輸出增加指定的空格數
| 1 2 3 4 5 6 | var?str = JSON.stringify({ name:?"John"?},?null, 2); // prints // { //?? "name": "John" // } print( str ); |
JSON.stringify(obj, null, "\t")
使用特定的字符來做分隔
| 1 2 3 4 | var?str = JSON.stringify({ name:?"John"?},?null,?"\t"); // Prints: // {\n\t"name": "John"\n} print( str ); |
另外,一些基礎類型添加了新的通用方法,但是,恕我直言,它們并不有趣。來自String,Boolean和Number的結果等同于調用valueOf(), Date的結果等同于調用toISOString()
| 1 2 3 4 5 | // Yawn String.prototype.toJSON Boolean.prototype.toJSON Number.prototype.toJSON Date.prototype.toJSON |
.bind()
內置bind()方法的引入很受歡迎,它可以使一個函數的執行環境得到改變(幾乎等同于prototype framework中的bind實現)
| 1 | Function.prototype.bind(thisArg, arg1, arg2...) |
使得函數的this關鍵字指向一個特定的對象,并傳入任何你要指定的參數。
| 1 2 3 4 5 6 7 | var?obj = { ????method:?function(name) { ????????this.name = name; ????} }; setTimeout(obj.method.bind(obj,?"John"), 100); |
Date
首先,如果所給的值是ISO格式,Date構造函數會試圖去解析該日期,接著再處理它接受的其他輸入。
| 1 2 3 4 | var?date =?new?Date("2009-05-21T16:06:05.000Z"); // Prints 2009-05-21T16:06:05.000Z print( date.toISOString() ); |
另外,date對象現在有個新的toISOString()方法,以ISO格式輸出日期
.trim()
一個原生,內置的trim()方法被String對象支持,和我們自己實現的trim方法功能一樣,但是原生的效率更高。
Array
JavaScript Array擴展方法包括: indexOf, lastIndexOf, every, some, forEach, map, filter, reduce 和 reduceRight
另外一個新方法Array.isArray(譯者注:可以理解為Array的static方法)被包含了進來, 提供和下面這段代碼同樣地功能:
| 1 2 3 | Array.isArray =?function( array ) { ????return?Object.prototype.toString.call( array ) ===?"[object Array]"; } |
總結
以上是生活随笔為你收集整理的ECMAScript5 严格模式,JSON,及其它的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里云存储OSS中设置上传文件conte
- 下一篇: 华为和天津移动搞了一个5G大动作 运营效