這篇文章主要是winter提出的一些問題加上一些個人思考,若有不對,但願你們能夠指出。javascript
1、爲何有的編程規範要求使用void 0 代替 undefined?
這篇文章主要介紹JavaScript中的屬性描述符、ES6中的module、箭頭函數。undefined類型的值爲undefined,當一個變量聲明未賦值時,它的值就是undefined。undefined是全局對象的一個屬性,也就是說它是全局做用域的一個##變量##。它##不是一個關鍵字和保留字##,這是JavaScript語言公認的設計失誤之一。undefined在全局做用域中不能被篡改,但在非全局做用域(如函數)中能夠被當作標識符(變量名)來從新賦值。而void運算能夠把任意一個表達式變成undefiend,因此爲避免無心中被篡改,建議使用void 0 來獲取undefined值。
void運算符: 對給定的表達式進行求值,而後返回 undefined。用法 void expression 。通常使用void(0)(等同於void 0)。
表達式: 表達式是由運算符構成,並運算產生結果的語法結構。每一個表達式都會產生一個值,它能夠放在任何須要一個值的地方。html
var a = 3 + 2; // 3 + 2是表達式 var b = (function () {return 25;})(); // (function () {return 25;})() 是表達式
語句: 語句能夠理解成一個行爲,循環語句和if語句就是經典的語句,一個程序是有一系列語句組成的。語句是由";(分號)"分隔的句子或命令。它代表"只有表達式,而沒有其餘語法元素的語句"。若是在表達式後面加一個";"分隔符,這句被稱爲"表達式語句"。
通常JavaScript中的語句分爲如下幾種:
(1)聲明語句: 變量聲明和函數聲明
(2)賦值語句
(3)控制語句: 可以對語句執行順序發生改變,包括條件語句和循環語句,還有比較特殊的標籤語句
(4)表達式語句: 這些語句去掉最後的分號,都也可當表達式用的。常見的有: 對象(new、delete)、函數調用(函數執行,必有返回值)等前端
參考來自:
MDN--undefined
MDN--voidjava
2、字符串有最大長度嗎?
String 有最大長度是 2^53 - 1,這個所謂最大長度不是字符數,而是字符串的 UTF16 編碼,咱們字符串的操做 charAt、charCodeAt、length 等方法針對的都是 UTF16 編碼。因此,字符串的最大長度,其實是受字符串的編碼長度影響的。express
3、0.1 + 0.2 爲何不等於 0.3?
解釋一:根據雙精度浮點數的定義,Number 類型中有效的整數範圍是-0x1fffffffffffff 至 0x1fffffffffffff,因此 Number 沒法精確表示此範圍外的整數。浮點數運算的精度問題會致使等式左右的結果並非嚴格相等,而是相差了個微小的值。
解釋二:對於計算機而言,兩個數字在相加時是以二進制形式進行的,在呈現結果時才轉換成爲十進制。先按照 IEEE 754 雙精度64位浮點數 轉成相應的二進制,而後進行對階運算。當十進制小數的二進制表示的有限數字超過52位時,在JavaScript裏是不能精確存儲的,這時候就存在舍入偏差。因此,精度可能損失在進制之間的轉換和對階運算過程當中,只要這兩步中產生了精度損失,計算結果就會出現誤差。編程
進一步提問:
1.如何讓 0.1 + 0.2 == 0.3?
在不進行轉換的狀況下,使用 Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON
,檢測等式左右兩邊差的絕對值是否小於最小精度。
Number.EPSILON: ES6 在Number對象上面,新增一個極小的常量Number.EPSILON。根據規格,它表示 1 與大於 1 的最小浮點數之間的差。 (來自 ECMAScript6入門)
2.爲何 0.2 + 0.3 = 0.5 ?
這個能夠看參考文章的第一篇,主要是由於在進行計算的時候知足了精度運算的要求。segmentfault
擴展: JavaScript使用Number類型表示數字(整數和浮點數),遵循 IEEE 754 標準 經過64位來表示一個數字。在內存中,第0位:符號位,0表示正數,1表示負數(s)。第1位到第11位:儲存指數部分(e)。第12位到第63位:儲存小數部分(即有效數字)f。瀏覽器
注:當數字 大於9007199254740992( Math.pow(2, 53) )進行加法時,精度也會發生丟失。
解釋二的參考文章:
0.1 + 0.2不等於0.3?爲何JavaScript有這種「騷」操做?
JS 0.1+0.2的理解
0.1 + 0.2 = 0.30000000000000004怎樣理解app
4、爲何給對象添加的方法可以用在基本類型上?
爲了方便操做基本類型值,ECMAScript提供了幾個特殊的引用類型: Boolean、Number、String、Symbol。每當讀取一個基本類型值的時候,後臺就會建立一個對應的基本包裝類型的對象,從而讓咱們可以調用一些方法來操做這些數據。
基本包裝類型的運行過程:函數
let s1 = 'some text'; let s2 = 's1.substring(2)';
後臺自動完成的處理:
1) 建立String類型的一個實例
2) 在實例上調用指定的方法
3) 銷燬這個實例
基本包裝類型和引用類型的主要區別是對象的生存期。使用 new 操做符建立的引用類型的實例,在執行流離開當前做用域以前都一直保存在內存中。而自動建立的基本包裝類型的對象,則只存在於一行代碼的執行瞬間,而後當即被銷燬。因此不能給運行時爲基本類型的值添加屬性和方法。
來源: JavaScript高級程序設計(第3版) 基本包裝類型
進一步提問: 實現 if(a== 1 && a== 2 && a== 3)爲true
let a = { val: 1, toString() { return this.val++; }, valueOf() { return this.val++; } } if (a == 1 && a == 2 && a == 3) { console.log('hello world'); }
裝箱轉換: 每一種基本類型 Number、String、Boolean、Symbol 在對象中都有對應的類,所謂裝箱轉換,正是把基本類型轉換爲對應的對象,它是類型轉換中一種至關重要的種類。
拆箱轉換: 在 JavaScript 標準中,規定了 ToPrimitive 函數,它是對象類型到基本類型的轉換。對象到 String 和 Number 的轉換都遵循「先拆箱再轉換」的規則。經過拆箱轉換,把對象變成基本類型,再從基本類型轉換爲對應的 String 或者 Number。拆箱轉換會嘗試調用 valueOf 和 toString 來得到拆箱後的基本類型。若是 valueOf 和 toString 都不存在,或者沒有返回基本類型,則會產生類型錯誤 TypeError。
5、爲何12.toString會報錯?
由於在JS中十進制的Number能夠帶小數,小數點先後部分均可以省略,但不能同時省略。所以一個小數能夠表現爲 '.01'、'12.'、'12.01',當使用12.toString時,12.會被當作省略了小數點後面部分的數字而當作一個總體。因此想讓這個表達式正確執行,須要加入一個空格('12 .toString()')或者再加一個.('12..toString()')。
6、JavaScript到底要不要寫分號?
結論是加不加分號均可以,若是不加分號有些地方須要注意一下。
須要注意的地方:
1) 若是下一行的第一個token是 ( , [ , / , + , - 這五個字符之一的話, Javascript 將不會自動在上一行句尾加上分號。因此,當下一行的第一個token是以上字符時,應當在上一行或者行首加上分號
2) continue、return、break、throw後自動插入分號。因此當 return 出一個值,千萬不要將那個值與 return 不在同一行,否則返回的結果是 undefined 而不是你指望的值。
3) ++ , -- 後綴表達式做爲新行開始,會在行首自動插入分號,
參考連接:
知乎--JavaScript 語句後應該加分號麼?
JavaScript ASI 機制詳解
7、在script標籤寫export爲何會拋錯?
由於沒有在script上設置type="module"屬性。在JavaScript中有兩種源文件,一種是腳本,一種是ES6的模塊。在模塊中可使用import和export,而腳本中不行,會報錯。現代瀏覽器能夠支持script標籤引入模塊或腳本。script標籤的默認type屬性爲type="application/javascript",表示腳本,它能夠省略。ES6的模塊要想加載,須要設置type="module"屬性,否則瀏覽器就會覺得是在腳本中寫了export,所以而報錯。
這篇文章就是JavaScript系列的最後一篇了,也是重學前端這個系列的最後一篇文章了。以上內容若有不對,但願你們指出,謝謝。