這是一個「然並卵」的問題,由於沒有人願意在代碼中給本身找這種麻煩,看到書上講到這個問題忍不住想順勢總結下,就從表達式提及吧。php
在js中,同通常的語言同樣,表達式分不少種。c++
var arr1 = []; //空數組 var arr2 = [1,2,3+5]; var arr3 = [1,,3,,6]; var obj1 = {}; //空對象 var obj2 = {x:3, y:5};
逗號之間能夠空着不寫,js默認將其定義爲undefined,而對象的屬性在有空格時須要加引號以構成字符串的屬性名,屬性值能夠是任意類型。嵌套定義也能夠。經過這個中直接聲明而來的,通常將其稱爲原始值或直接量,由於它們與真正經過new關鍵字獲得的對象數組有一點差異。數組
var vl = function(){ document.write("function to a var.<br/>"); }; vl();
var arr = [1,2,3]; document.write(arr[0]+"<br/>"); var obj = {x:1, y:5}; document.write(obj.x+" "+obj["y"]);
function fun(){ ; } fun(); //函數調用 function Game(name){ //構造函數 this.name = name; this.fly = function(){;} } var flappy_bird = new Game("flappy_bird"); flappy_bird.fly(); //方法調用
相似於對對象屬性的引用,方法調用也會先計算點號左邊是不是一個對象,不是對象的話將會拋出類型錯誤。app
var arr = new Array(1,2,3); var o = new Object; var date = new Date();
還有跟運算符相關的算術表達式、關係表達式、邏輯表達式等、賦值表達式等,值得注意的是js的邏輯表達式並不必定返回布爾類型的true和false,如ide
var ret1 = 5 && [1,2,3]; document.write("ret1: type=>"+typeof(ret1)+" val:"+ret1+"<br/>"); var ret2 = 0 || 5; document.write("ret2: type=>"+typeof(ret2)+" val:"+ret2+"<br/>");
輸出 函數
可是在其餘語言,好比php中,邏輯表達式的最終結果必定是布爾型的,這點須要區別。this
咱們更容易忘記的是最簡單的情形:原始表達式。所謂原始表達式是表達式的最小單位,它不在包含其餘表達式,它就是最簡單的常量、變量、原始值或關鍵字,如spa
//原始值 15; "hello"; /[A-Z]\d+/; //關鍵字 null; false; //變量 index; sum;
跟運算符扯上關係的,確定要考慮運算符的優先級、結合性,優先級高的先運算,優先級高的先運算,還要看看是從左到右仍是從右到左,好比常常用的連續賦值code
var a = b = c = 1;
由於賦值運算符的結合性是從右到左,因此上面又等價於下面這樣的:對象
var a = (b = (c = 0));
最後一點是運算符的運算順序,一般咱們只須要考慮優先級與結合性就夠了,談到運算順序,它涉及的的是子表達式(父子關係老是相對的),以下面一段計算式
w = x + y * z
子表達式就是w、x、y、z,由於是最簡單的變量,因此它們是原始表達式,js是按照從左到右的順序來計算子表達式的,這裏先依次計算w、x、y、z的子表達式的值,而後根據優先級和結合性,先計算y+z的值,再與x相加,將結果賦值給表達式w所指代的某個變量。
而咱們通常碰到的狀況是,計算x子表達式的時候,對y不會產生什麼影響,一旦產生了影響(使用特殊運算符),如改變了y子表達式的值,這稱爲運算符的反作用(side effect)。能改變子表達式的值,確定要對它賦值,因此通常具備賦值做用的運算符容易產生反作用,嚴格的說等號具備反作用,固然通常用等號確定就是要改變等號左邊表達式的值,談個毛線反作用。
回到(i++)+(++i),使用具備隱式賦值做用的自增運算符,自減天然也算,就產生反作用了,前面的先各一個i子表達式的初始值,假設i初始值爲1,而後計算i++時,因爲自增緣由,自增計算過程當中對 i 進行了賦值運算,i++這個總體表達式的值仍爲1,再計算++i 時,i 這個子表達式的值已是2(前面的賦值改變了它的大小),因此後面 i++的值是3,總的結果就是4。其餘的,c/c++等的理解方式幾乎相同。
放佛又回到曾今被老師坑慘的c語言考試題=_=