JavaScript深入【詞法結構,類型,值和變量】原來也不簡單


 

 

博主留言 (茗洋芳竹  


我自己本身是個ASP.NET開發者,前后台數據庫都搞,所以各個方面都不是那么精通,連個JavaScript,最后也想偷懶,用了Jquery,忘了原生的高深莫測的Javascript,特寫博客,系統學習Javascript,本文不太適合零基礎學習的人,至少有其他編程語言小基礎的的javascript學習者。

當你系統的學習Javascript的時候,你會覺得還是有必要的,這就是超過別的程序員的地方

本文開頭看似很簡單,但當我寫完這篇博客的時候我發現,我有好多不知道的。

  比如說

       字符串的原理

       字符集,Unicode,字符的長度到底怎么算出來的,比如 var b="caf\u00e9"var c="cafe\u0301"; b的長度是多少,c的長度是多少,答案是一個是4,一個是5

       JavaScript的浮點數到點是怎么計算的,比如 1.4738223E-32是什么意思,0.3-0.2等於0.1嗎?.4-.3等於0.1嗎

       當遇到財務計算,要求精度,你會怎么做

      字符串一些處理方法,比如slice方法,字符串的正則 方法處理

      兩個字符串的比較原理

      null與undefined

      Infinity和-Infinity,NaN

      全局對象的真正理解,而不再淺淺的理解

      原始值與對象的相互轉換

      valueOf與toString

      還有個很神奇,跟其他比如C#,Java不一樣的函數作用域,而不是塊級作用域,作用域嵌套

      var這個關鍵字,聲明時真的可寫可不寫嗎

      等等

      

我相信如果你不是Web前端開發人員,你肯定受益匪淺。

 

JavaScript簡單調試(茗洋芳竹


你可以打開火狐,谷歌或者IE,現在好多瀏覽器自帶了 開發者工具,作為簡單的入門調試環境

例如我打開了谷歌瀏覽器,按下F12,然后點擊Console,截圖如下

image

此刻你可以直接在下面寫JavaScript代碼,然后進行學習和測試

小提示:

例如我們寫下 alert("Hello Javascipt!") 然后按下回車,會彈出對話框

image

但是如果超過兩行Javascript代碼測試時候

我們可以寫完一行代碼時候,按下Shift+Enter執行換行

然后繼續編寫代碼

 

后期,我們主要用SublimeText去寫代碼,當然你也可以用其他文本編輯器或者 web開發工具,例如 adobe Dreamweaver CS系列,最新的好像是cs 6

 

JavaScript小Tip(茗洋芳竹


1. Javascript 程序是用Unicode字符集編寫的

    Unicode是ASCII和Latin-1的超集,並支持地球上幾乎所有在用的語言

2. Javascript 區分大小寫,但是HTML不區分大小寫(嚴格講XHTML區分大小寫,但是瀏覽器糾錯能力強大,還是可以寬容地正確解析渲染)

   星星在HTML中,標簽和屬性名可以使用大寫也可以小寫,而在JavaScript中必須小寫。

        例如:在HTML中設置事件處理程序時,onclick可以寫成onClick,但在Javascript中,必須小寫onclick

3. 在編寫Javascript代碼中可以隨意使用空格和換行,因此編寫的代碼可以弄整齊,一致的縮進,提高代碼可讀性

4. 為了支持使用老舊技術的程序員,javascript定義了一種特殊序列,使用6個ASCII字符來代表任意16位Unicode內碼

    形式:\u為前綴,其后跟隨4個十六進制數。例如 \u0020表示空格

    這種Unicode轉義寫法可以用在Javascript字符串直接量、正則表達式直接量和標志符中(關鍵字除外)

    image=>true

5. Unicode允許使用多種方法對同一個字符進行編碼

    比如,字符“é”可以使用Unicode字符\u00E9表示,也可以使用普通的ASCII字符e加上一個語調符\u0301。

<script>
 var a="café";
 var b="caf\u00e9";
 var c="cafe\u0301";
 alert(b+"  "+c);
</script>

    顯示效果

image

    我們順便借這個機會測試一下其他方面的東西,例如字符長度

<script>
 var a="café";
 var b="caf\u00e9";
 var c="cafe\u0301";
 alert(b+"  "+c);   
 alert(a===b);
 alert(b==c);
 alert("caf\u00e9的長度等於"+b.length+"\ncafe\u0301"+"的長度等於"+c.length);
</script>
 
結果: 
   a===b // =>true      
   b==c   //=>false                                         

         b.length是4,而c.length是5                                 

      所以這兩種編碼的顯示結果一模一樣,但他們的二進制編碼表示是不一樣的,在計算機里面也不相等

 

6. 注釋

    // 單行注釋

   /* 只是另一段注釋 */

   /*

   *這又是一段注釋

   *這個注釋可以寫多行

   */

 

7. 直接量(literal)

   程序中直接使用的數據值

   12 //數字

   1.2 //小數

   "Hello world”    //字符串文本

   ‘Hi’     //另一個字符串

    true    //布爾值

    /javascript/gi      //正則表達式直接量(用做模式匹配)

    null         //空

   更多復雜的表達方式,可以寫成數組或對象直接量

  {x:1,y:2} //對象

  [1,2,3,4,5]  //數組

 

8. 標識符

   標識符就是一個名字,標識符用來 對變量和函數進行命名,或者用做JS代碼中某些循環語句中的跳轉位置的標記。JS標識符必須以字母、下划線(_)或美元符($)開始,后續的字符可以是字母、數字(不允許作為首字符出現)、下划線或者美元符。

   例如

         i

         my_mingyangfangzhu_blog

         v13

         _dummy

        $str

   出於可移植性和易於書寫的考慮,通常我們只使用ASCII字母和數字來書寫標識符。然而需要質疑的是,Javascript允許標識符中出現Unicode字符全集中的字母和數字。我們也可以使用非英語語言數字符號來書寫標識符

  例如: var sí=true;

           var π =3.14;

 

9. 保留字

    Javascript把一些 標識符拿出來 用作自己的關鍵字。所以我們就不能再在程序中把這些關鍵字用作標識符了。

    如果學過其他語言的,一聽就懂了。標識符就是一個變量名,有些特殊的變量名不能再定義了,那就是保留字

    JS中,例如

    break delete function return typeof case do if switch var catch else in this void continue false instanceof throw

    while debugger finally new true with default for null try等

    JS還定義了很多全局變量和函數

    arguments                      encodeURI                             Infinity             Number                    RegExp

    Array                             encodeURIComponent              IsFinite            Object                       String          

    Boolean                         Error                                     IsNaN              parseFloat                  SyntaxError

    Date                              eval                                      JSON                parseInt                     TypeError

    decodeURI                      EvalError                               Math                 RangeError                  undefined

    decodeURIComponent      Function                                NaN                 ReferenceError              URIError

    等

    JavaScript的具體實現可能定義獨有的全局變量和函數,每一個特定的JavaScript運行環境(客戶端、服務器端等)都有自己的一個全局屬性列表,這一點需要牢記。每個瀏覽器可能自帶某些js內置函數

 

10.可選的分號

   例如代碼

    例一                                                

      a=3;

      b=4;

   考慮如上代碼,因為兩條語句用兩行書寫,第一個分號是可以省略掉的,但是如果這樣寫,就不可省略掉了

     a=3;b=4;

   例二                                 

  var a

  a

  =

  3

  console.log(a)

 

Javascript將其解析為

var a;a=3;console.log(a);

Javascript給第一行換行處添加了分號,因為如果沒有分號,JavaScript就無法解析代碼var a a.

第二個a可以單獨當做一條語句”a;”,但JavaScript並沒有給第二行結尾填補分號,因為他可以和

第三行內容一起解析成"a=3”;

 

   例三                                    

var y=x+f

(a+b).toString()

看似兩行,你也想到了,JavaScript會把這段代碼看做: var y=x+f(a+b).toString(); 

f被看做是一個方法,所以要達到的自己的本意,必須手動填寫行尾的顯示分號

不同的人,不同的JavaScript編碼風格,有的程序員喜歡保守地在語句前加上一個分號,這樣哪怕之前的語句被修改了、分號被誤刪除了,當前語句還是會正確的解析

     var x=0

     ;[1,2+1,3+2].forEach(…) //前面的分號保證了正確地語句解析

 

  例四                               

return

true;

JavaScript會解析成:

return;true;

而你的本意是 return true;

也就是說,在return、break和continue和隨后的表達式之間不能有換行。

 

還有個例外,例如

x

++

y

這段代碼將解析為 “x;++y”而不是“x++;y”

 

 

 

JavaScript 類型、值和變量 (茗洋芳竹 


這幾個字我覺得比較抽象,如果做過其他語言學習的人那就最簡單的了,懶得說大定義,會感悟出來的

一句話概括:

   計算機程序的運行需要對 值(value) 進行操作。

   在編程語言中,能夠表示,並操作的值的類型,稱作數據類型(type)

    編程語言最基本的特性就是能夠支持多種數據類型。當程序需要將值保存起來以備將來使用時,便將其賦值給一個變量(variable)

 

JavaScipt的數據類型分為兩類:原始類型和對象類型

JavaScipt中有兩個特殊的原始值:null(空)和undefined(未定義),它們不是數字,字符串和布爾值。

JavaScipt中除了數字、字符串、布爾值、null和undefined之外的就是對象了

JavaScipt解釋器有自己的內存管理機制,可以自動對內存進行垃圾回收

JavaScipt是一種面向對象的語言

從技術上將,只有JavaScript對象才能擁有方法。然后數字、字符串和布爾值也可以擁有自己的方法。只有null和undefined是無法擁有方法的值。

JavaScipt變量是無類型的,變量可以被賦予任何類型的值,同樣一個變量也可以重新賦予不同類型的值。使用 var 關鍵字來聲明變量。JavaScipt采用詞法作用域(lexical scoping)。

不在任何函數內聲明的變量稱作全局變量(global variable),它在JavaScript程序中的任何地方都是可見的。在函數內聲明的變量具有函數作用域(function scope),並且只在函數內可見。

 

以上的很多東西,在編寫代碼中會慢慢領悟的

 

【數字】

 1. JavaScipt 不區分整數值和浮點數值JavaScipt 中的所有數字均用浮點數值表示。

    最大值:±1.7976931348623157 × 10的308次方

    最小值:±5× 10的負324次方

2.JavaScipt 除了常見十進制,JavaScipt 同樣也能識別十六進制值(以“0x”或“0X”開頭,然后跟着0~9或者A~F或者a~f字母組成,A(a)~F(f)分別代表數字10~15)

   例如:

      0xff         //從右往左數到X(x)停住,16的0次方,16的1次方,f代表15,所以轉換成十進制后是

                       15乘以16的1次方+15乘以16的0次方,最后等於255

image

盡管ECMAScript標准不支持八進制直接量,但JavaScript的某些實現可以允許采用八進制形式的整數,八進制以數字0開始,其后跟隨一個由0~7之間的數字組成的序列

例如

  0377     //從右往左數到開頭的0停住,8的0次方,8的1次方,8的2次方,所以轉換成十進制后是

                       3乘以8的2次方+7乘以8的1次方+7乘以8的0次方,最后等於

                        3*64+7*8+7*1=255

image

 

3.浮點型

  就是 一個實數由 整數部分+小數點+小數部分   組成

  例如:

     3.14

     2345.678

     .33333333

     6.02e23         //特別說明:等同於 6.02 ×clip_image002_thumb[1]

    1.4342E-23     //特別說明:等同於 1.4342 ×clip_image002

   除了加(+)減(-)乘(*)除(/)求余(%)幾個運算外,還有很多

    JavaScript還支持更加復雜的算數運算

<script>
 
 //Math類運算
 var a=Math.pow(2,53);     //=>9007199254740992   也就是2的53次冪
 var b=Math.round(.6);     //=>1.0       四舍五入
 var c=Math.ceil(.6);      //=>1.0   向上求整,大於它的最小整數
 var d=Math.floor(.6);     //=>0.0    向下求整,小於它的最大整數
 var e=Math.abs(-5);       //=>5;      求絕對值
 
 
 var f=Math.max(3,5,1);     //返回最大值
 var g=Math.min(3,5,1);     //返回最小值
 
 
 var h=Math.random();       //生成一個大於等於0小於1.0的偽隨機數
 var pi=Math.PI;            //π,圓周率
 var i=Math.E;              //自然對數的地鼠
 var j=Math.sqrt(3);        // 3的平方根
 var k=Math.pow(3,1/3);     // 3的立方根,這里第二個參數 指的是 冪右上角的指數,讀作3的三分之一次方
 var l=Math.sin(0);         //三角函數,還有Math.cos,Math.atan等等
 var m=Math.log(10);        //10的自然對數
 var n=Math.log(100)/Math.LN10 ;   //以10為底100的對數
 var o=Math.log(512)/Math.LN2 ;    // 以2為底512的對數
 var p=Math.exp(3);                //e的三次冪
 
 
</script>

 

JavaScript 中的算數運算在 溢出(overflow),下溢(underflow)或被零整除時候不會報錯。當數字運算結果超過了JavaScript所能表示的數字上限(溢出),結果為無窮大(infinity)值,在JavaScript中以Infinity表示,同樣地,當負數的值超過了JavaScript所能表示的負數范圍,結果則為負無窮大,在JavaScript中以-Infinity表示

下溢 是當運算結果無限接近於零並比JavaScript能表示的最小值還小的時候發生的一種情形。這種情況,JavaScript會返回0.當一個負數發生下溢時,JavaScript返回一個特殊的值“負零”。這個零(負零)幾乎和正常的零是一樣的

被零整除在JavaScript並不報錯;只是簡單的返回無窮大(Infinity)或者負無窮大(-Infinity)。

零除以零無意義,返回NaN,任何無意義的,例如給任意負數做開方,都將返回NaN

JavaScript 預定了全局變量 InfinityNaN,用來表示正無窮大和非數字值。ECMAScript5將它們定義為只讀的。在ECMAScript3中

Number對象定義的屬性值也是只讀的,

比如:

  Infinity                             //將一個可讀/寫的變量初始化為infinity

  Number.POSITIVE_INFINITY    //同樣的值,只讀

  如下:則會顯示個  true

 var aa= Number.POSITIVE_INFINITY;
 alert(aa==Infinity);

1/0       //這也是同樣的值

  image

Number.MAX_VALUE+1      //還是Infinity

 

以下幾個是負無窮大

Number.NEGATIVE_INFINITY,-Infinity,-1/0,Number.MAX_VALUE-1

 

以下幾個是NaN

NaN,Number.NaN,0/0

 

以下幾個是負零

-0,-Number.MIN_VALUE/2,-1/Infinity

 

Number.MIN_VALUE/2 發生下溢,計算結果為0

 

注意:JavaScript中的非數字有一點特殊,第一種判斷是false,isNaN()方法,如果cc是NaN,則為true,否則為false

<script>
 
 var cc=NaN;
 if(cc==NaN){
     alert("是NaN");
  }else{
     alert("不是NaN"); 
       }
 
 if(isNaN(cc)){
      alert("是NaN");
     }else{
     alert("不是NaN"); 
       }
</script>

 

還有個 函數 isFinite()方法,除 NaN,Infinity,-Infinity其他都是true

var dd2=-Infinity;
var dd3=NaN;
var dd4="22";
var dd5=true;
//inFinite()
alert(isFinite(dd1));  // false
alert(isFinite(dd2));  // false
alert(isFinite(dd3));  // false
alert(isFinite(dd4));  // true
alert(isFinite(dd5));  // true
 
 
 
負零值也有些特殊,這兩個值幾乎一模一樣,除了做除數之外;
var zero=0;
var negz=-0;
alert(zero===negz);           // true   正零值和負零值相等
alert(1/zero===1/negz);       // false  正無窮大和負無窮大不等
 
 
 
 
 

4.當在JavaScript 中使用實數的時候,常常只是真實值的一個近似表示

    JavaScript 采用了IEEE-754浮點數表示法(幾乎所有現代編程語言所采用),這是一種二進制表示法,可以精確地表示分數,比如1/2,1/8,1/1024,分子是2的n次方數,遺憾的是,我們常用分數(特別在金融計算方面)都是十進制分數1/10,1/100等。

所以二進制浮點數表示法冰冷精確表示類似0.1這樣簡單的數字

 

var x=.3-.2;
var y=.2-.1;
alert(x==y);   //=>false
alert(x==.1);  //=>false
alert(y==.1);  //=>true
 

所以在任何使用二進制浮點數的編程語言都會有這個問題。例如,要使用整數“分”而不要使用小數“元”進行基於貨幣單位的運算。

 

5.日期和時間

   JavaScript 語言核心包括Date()構造函數,用來創建表示日期和時間的對象

var then=new Date(2013,2,20);  //2013年3月20日
var later=new Date(2013,2,20,17,10,30); //同一天,當地時間 5:10:30pm
var now=new Date();   //當前日期和時間
var elapsed=now-then;  //日期減法,計算時間間隔的毫秒數
var year=later.getFullYear(); //2013
var month=later.getMonth();   //0, 從0開始計數的月份
var day=later.getDate();     //20,從1開始計算天數
var week=later.getDay();     //3,0代表星期日,3代表星期三,6代表星期6
var hours=later.getHours();   //17,當地時間17:10pm中的小時數字
var lc=later.getUTCHours()  //使用UTC表示小時的時間,基於時區
 

 

6.字符串直接量 例如 "" //空字符串

       "茗洋芳竹123"
      'myname="myfz"'
     "it's  a  book"
      "lala\n123\n

π

"     //      \n代表轉行
         等等
 

在ECMAScript3中,字符串直接量必須寫在一行中 在ECMAScript5中,字符串直接量可以拆分數行,每行必須以反斜線(\)結束,如果希望在字符串直接量中另起一行,可以使用轉義字符\n

var newLine="long\
  long\
             ago";
             alert(newLine);

注意 當使用單引號來 定界字符串時,需要格外小心英文中的縮寫和所有格寫法,比如 it’s 和 can’t。

         因為撇號和單引號是同一個字符,所以必須使用反斜線(\)來轉義所有的撇號

 

7. 轉義字符

  反斜線符號后面加一個字符,就不在表示他們的字面含義了

   例如\n 表示一個換行符

         \'  表示單引號(或撇號)

   通過十六進制數表示Latin-1或Unicode的任意字碼。例如\x09 表示版權符號,版權符號的Latin-1編碼是十六進制數A9。

   同樣,\u表示由4個十六進制數指定的任意Unicode字符,比如\u03c0表示 π

     類似的還有很多,例如 \"  表示 雙引號(\u0022

        \\  表示 反斜線(\u005c)                                      

      \r  表示 回車符(\u000d)                                        

      \t  表示 水平制表符(\u0009)                                   

     \v   表示 垂直制表符(\u000B)                                  

     \b   表示 退格符(\u0008)                                       

     \xXX 表示 由兩位十六進制數XX指定的Latin-1字符         

     \xXXXX  由4位十六進制數XXXX指定的Unicode字符       

 

 

 

8. 字符串使用

   ①連接字符串用+號     var c=”Chris”+”  Li”;

   ②字符串.length    獲得字符串長度

  常用方法

<script>
   var s="hello world";
   var s1=s.charAt(0);                         // h :獲得第一個字符
   var s2=s.charAt(s.length-1);                // d :獲得最后一個字符
   var s3=s.substring(1,4);                    //ell: 第2-4個字符
   var s4=s.substr(2,5);                       //llo w: 從0開始,第一個字符是h,第二個l,第三個字符就是l,然后取5個長度的字符
   var s5=s.slice(1,4);                        //ell: 第2-4個字符
   var s6=s.slice(-3);                         //rld:最后3個字符
   var s7=s.slice(3);                          //lo world:從第3個字符開始,取到末尾
   var s8=s.indexOf("l");                      //2,從0開始,首次出現l的位置
   var s9=s.lastIndexOf("l");                  //9,從0開始,字符l最后出現的位置 
   var s10=s.indexOf("l",3);                   //3,在位置3及之后首次出現字符l的位置
   var s11=s.split(" ");                       //["hello","world"] 分割成字符串
   var s12=s.replace("h","H");                  //"Hello world": 全文字符替換
   var s13=s.toUpperCase();                     //"HELLO WORLD" :轉換成大寫字母
   
</script>

記住,在JavaScript中字符串是固定不變的,類似replace()和toUpperCase()的方法都返回新字符串,原字符串本身並沒有發生改變

在ECMAScript5中,字符串可以當做只讀數組。

 var s="hello world";
    alert(s[0]);        //h
    alert(s[s.length-1]); //d

這種類似於charAt 函數方法,加上數字索引 訪問數組中的單個字符

 

9.模式匹配

  JavaScript 定義了RegExp()構造函數,用來創建表示文本匹配模式的對象,這就是正則表達式

  String和RegExp對象均定義了 利用正則表達式 進行模式匹配和查找與替換的函數

  RegExp和Date一樣,只是一種具有實用API的特殊對象。這里只是正則表達式的一個概述,具體后面講

  例如:

       /^HTML/      //匹配以HTML開始的字符串

      /[0-9][0-9]*/      //匹配一個非零數字,后面是任意個數字

     /\bjavascript\b/i   //匹配單詞“javascript”,忽略大小寫

 

字符串同樣具有可以接受RegExp參數的方法

  var text="testing:1,2,3";
  var pattern=/\d+/g;      //匹配所有包含一個或多個數字的實例 ,\d代表數字,+號對前面的數字進行約束,表示至少一個
  alert(pattern.test(text));      //true
  var succLo=text.search(pattern);     //9 首次匹配成功的位置
  var arrSucc=text.match(pattern);     //所有符合匹配要求的,所有匹配組成的數組 ["1","2","3"]
  var replaceSucc=text.replace(pattern);   //testing,#,#,#
  var splitSucc=text.split(/\D+/);          //用非數字字符 作為 分組條件 ["","1","2","3"]
  alert(splitSucc.length);       //4

 

 

10.布爾值

    布爾值(bool) 表示真假,保留字為true和false

     一個表達式最終會成不成立,就是 true或者false

    一個邏輯最終成不成立,就是true或者false

   

  注意 JavaScript的值都可以轉換成布爾值,下面這些值會被轉換成false

            undefined,null,0,-0,NaN

           ””

     &&運算執行了邏輯與(And)操作

     || 運算 執行了布爾或(OR)操作

      !運算 執行了非(NOT)操作

     例子:a1是true,a2是true,所有a1&&a2是true;a3是false進行了非操作,取反,則是true

             然后 true||true,或操作是只要有一個是真,整個條件就為真,所以最終返回true

 var x=0,y=0,z=2;
  var a1=x==0;
  var a2=y==0;
  var a3=z==0;
 
  var a4=(a1&&a2)||(!a3);
  alert(a4);

 

 

 

11. null和undefined

    對null執行typeof運算,結果返回字符串object,也就是說,可以將null值認為是一個特殊對象值

    對undefined執行typeof算,結果返回字符串undefined,用未定義的值表示更深層次的“空值”。他是變量的一種取值,表明變量沒有初始化。如果要查詢對象屬性或數組元素的值返回undefined則說明這個屬性或元素不存在

    盡管null和undefined是不同的,但他們都表示值的空缺,兩者往往可以互換。判斷相等運算符“==”認為兩者是相等個(要使用嚴格相等運算符“===”來區分它們),它們不包括任何屬性和方法,放入[]數組會產生類型錯誤

    如果你想將它們賦值給變量或者屬性,或將他們作為參數傳入函數,最佳選擇用null

 

 

 

12.全局對象的屬性時全局定義的符號,JavaScript程序可以直接使用

   全局屬性:比如undefined,Infinity和 NaN

   全局函數,比如isNaN(),parseInt()和Eval()

   構造函數  比如Date(),RegExp(),String(),Object()和Array()

   全局對象  比如Math和JSON

 

 

13.包裝對象

    JavaScript 通過“.”符號來引用屬性值。當屬性值是一個函數的時候,稱其為方法。通過o.m()來調用對象o中的方法

   下面一段代碼是錯誤的,返回undefined,第二行代碼創建一個臨時字符串對象,並給其len屬性賦值給4,隨即銷毀這個對象。第三行通過原始的字符串值創建一個新字符串對象,當你嘗試讀取其len屬性,這個屬性自然不存在

 var bao="test";
  bao.len=4;
  alert(bao.len);

 

  需要注意的是,可通過String(),Number()或 Boolean()構造函數來顯示創建包裝對象

  var s="test",n=1,b=true;
  var S=new String(s);     //一個字符串對象
  var N=new Number(n);     //創建一個數值對象
  var B=new Boolean(b);   //創建一個布爾對象

 

 

14.天使不可變的原始值和可變的對象引用

     關於這個,我感覺很重要,不僅僅對於JavaScript語言來講的

      1.JavaScript的原始值(undefined、null、布爾值、數字和字符串)與對象(包括數組和函數)有着根本區別。原始值不可更改

      2.字符串看起來是字符組成的數組,我們希望通過索引修改字符串中的字符,Js是進制這樣做的。字符串中所有的方法看上去返回了一個修改后的字符串,實際上是一個新的字符串。

  var s="hello world";
  var t=s.toUpperCase();
  alert(s+"   "+t);

      把 s 的一個副本轉換成了大寫,然后返回給了t,原始的s值沒有改變。

      3.原始值的比較是值的比較,只有在他們的值相等時他們才相等。數字、布爾值、null、undefined都是這樣比較的,因為沒有其他辦法

      4.兩個單獨的字符串比較,當且僅當他們的長度相等且每個索引的字符都相等時,JavaScript才認為他們相等

  var array1=[1,4,5];
  var array2=[1,4,5];
  var array3=[3,4,5];
  
  
  alert(equalArray(array1,array2));
  alert(equalArray(array1,array3));
    
  function equalArray(a,b){
      //先比較兩個數組的長度
      if(a.length!=b.length)return false;
      //如果數組中的任意元素不相等,則數組不相等
      for(var i=0;i<a.length;i++){
        if(a[i]!=b[i])return false;  
          }
          
          return true;
      }

      

       5.對象與原始值不同,他們的值是可以修改的

var o1={x:1};    //定義一個對象
    o1.x=2;       //通過修改對象屬性值來更改對象
    o1.y=3;       //再次更改這個對象,給它增加一個新屬性
    
alert(o1["x"]+"  "+o1.x+"   "+o1.y);     //2      2      3

 

      6.數組也是一樣

      var o2=[1,2,3] ;     //數組也可以修改
      alert(o2.length);    //3
      o2[0]=0;              //更改
      o2[3]=4;              //新增
      
      alert(o2[0]+"  "+  o2[3]+"   "+o2.length);      //0     4     4

 

     7.對象的比較並非的比較;即使兩個對象包含同樣的屬性及相同的值,他們也是不相等的。各個索引元素完全相等的兩個數組也不想等。我們通常將對象稱為引用類型(reference type)

        對象值都是引用,對象的比較均是引用的比較,當且僅當他們引用  同一個基對象(父對象)時,它們才相等

var o={x:1},p={x:1};  
     alert(o==p);     //都是false
     alert(o===p);    //都是false
     //兩個單獨的對象永不相等,它們存在內存中的地址不一樣,地址唯一不重復的,所以永不相等
     
     var a=[],b=[];
     alert(a==b);     //都是false
     alert(a===b);    //都是false,跟上面一樣的,兩個單獨的數組永不

    

      為了證明引用,寫個例子

     var a=[];   //定義一個引用空數組的變量a
     var b=a;    //把a在內存中的地址  給b,此時它們指向的是同一個內存中的地址
     b[0]=1;      //b添加了一個值,由於它們引用了同一個地址,所以修改的是它們公用的內存,所以a也變了
     alert(a[0]);    //   1

    那么如果我們想要一個備份的數組怎么辦,我們可以通過循環來完成數組賦值

     var a=["a","b","c"];
     var b=[];
     for(var i=0;i<a.length;i++){
         b[i]=a[i];
         }
    //此時我們修改b,a不會被修改,因為 a,b兩個在內存中的地址不一樣,"a","b","c"都是原始值,賦值時都是備份
      alert(a[0]+"   "+b[0]);  //復制完后
      b[0]="abc";    //開始修改
     alert(a[0]+"   "+b[0]); 

 

     下面我自己寫了一段代碼,只要記住,引用類型不復制值,每一次都是一個對象在內存中的地址的 指向,你就記清楚了

     var a=[1,2,3];
     var b=[];
     
     var c=[a,"a",3];
     var d=[];  //我們把c中的值復制給d
     
    // alert(c[0][0]);  //1,  變量c中的 第一個索引位置,即a變量,a變量是個數組,然后在a變量中的第一個索引位置,即1
     
     for(var i=0;i<c.length;i++){
         if(i==0){
    
             b=c[i];        //將c中的第一個索引的位置,即a在內存中的地址給b,此時公用一個地址
              
             d[i]=b;            //將b 放在d對象的  第一個索引的位置上,此時b和a還是公用的
         }else{
             d[i]=c[i];
             }
         }
        
     //這個時候 我修改 b,會怎么樣,d中的第一個值中的會怎么樣
     alert(b[0]);      //1
     b[0]=5;
     alert(a[0]);     //5
     alert(c[0][0]);  //5
     alert(d[0][0]);  //5

 

 

15.類型轉換

   下面有一張表,可以參考一下

       image

 

例如:JavaScript期望使用一個數字,它將把給的值轉換成數字,轉換無意義,比如把abc字符轉換成數字,這不可能的,就會返回NaN

       下面有些小例子,看看就領悟出來了

        10+”objects”             //會自動變成字符串 “10objects”,數字10將會自動轉換成字符串,+號是連接字符串的

        ”7”*"4”                    //28,兩個字符串均轉換成 數字了,因為*代表乘號,代表一種運算,不像加號特殊

        var n=1-“x”;            //有減號在,x將被轉換成數字,結果失敗,當然無意義了,返回NaN,所以變量最終是NaN

        此時 n+”objects”        //n轉換成字符串是NaN,所以最終返回 NaNobjects

 

原始值到對象的轉換非常簡單,通過調用 String()  、Number() 、Boolean()構造函數,即可轉換為它們各自的包裝對象,null和undefined例外,轉換時無法正常轉換

 

 

轉換和相等性

由於JavaScript可以做靈活的類型轉換,“==”相等運算符的含義也有變化

下面這些結果都是true

     alert(null==undefined);    //這兩個值認為相等過的
     alert("0"==0);             //在比較之前字符串轉換成數字
     alert(0==false);           //在比較之前布爾值轉換成了數字
     alert("0"==false);    //在比較之前字符串和布爾值都轉成了

 

后面我們講解 “==”等於運算符在判斷兩個值是否相等時做了哪些類型轉換,並同樣介紹了“===”恆等運算符在判斷相等時並未做任何類型轉換。

注意:一個轉換為另一個值並不意味着兩個值相等

例如  alert(false==undefined);  //false

如果在期望使用布爾值的地方使用了undefined,它將會轉換為false,但這並不表明undefined==false。

 

 

顯示類型轉換

 

盡管JavaScript可以自動做許多類型轉換,但有時我們仍需做顯示轉換,或者只是為了代碼更容易讀

1.除了null和undefined之外的任何值都有toString()方法,這個方法的執行效果通常和String()方法的返回結果一樣。

  javaScript中的某些運算符會做隱式的類型轉換,比如特殊的 + 號,有時是運算,有時連接字符串的,此時它就會把不是字符串的轉換成字符串,作為連接字符串的效果,還有!號,取布爾值的反

           x+””        //等價於String(x)

           +x          //等價於Number(x),也可以寫成x-0

           !!x          //等價於Boolean(x),雙感嘆號

           Number(“3”)    // 3

           String(false)    //”false”      或者false.toString()

          Boolean([])      //true

           Object(3)         //new  Number(3)

 

2.關於 字符串轉數字,數字轉字符串,更高級的,十進制轉2進制,8進制,16進制

var tenNumber=17;
var binary_string=tenNumber.toString(2);      //  "10001"
var otcal_string="0"+tenNumber.toString(8);     //轉換成 "021"
var hex_string="0x"+tenNumber.toString(16);    //轉換成 "0x11"
var summary="數字"+tenNumber+"轉換成二進制是"+binary_string+";\n轉換成八進制是"+otcal_string+";\n轉換成十六進制是"+hex_string;
alert(summary);

3.處理財務,科學計數時候可能需要,下面的幾個方法

var n=123456.789;
var a=n.toFixed(0);       //"123457"四舍五入,0代表不保留任何小數,那么同理1就代表保留1位小數
var b=n.toFixed(2);       //"123456.79"
var c=n.toFixed(5);        //"123456.78900"
 
//指數計數法,toExponential(參數),參數代表了,小數位有幾位數字
var d=n.toExponential(1);     //  "1.2e+5" ,代表1.2乘以10的5次方
var e=n.toExponential(3);     //  "1.235e+5"
 
//指數計數法,toPrecision(參數),參數代表了,包括整數和小數部分一共要有幾個有效數字
var f=n.toPrecision(4);       // "1.235e+5",這里是參數是4,代表了整數部分1個,加上小數部分3個,總共湊滿4個有效數字
var g=n.toPrecision(7);       // "123456.8"   //參數超過了整數部分數字的個數
var h=n.toPrecision(10);      //"123456.7890"  //不足部分補0
    

    

4.parseInt()只解析整數,parseFloat() 整數和浮點數都解析

    var  dd=Number("12.14");
//    alert(dd);       // 12.14
    var d1=parseInt("3 blind mice");       //3
    var d2=parseFloat("3.14 meters")        //d2
    var d3=parseInt("-12.74");               //-12,不四舍五入的,只取整數部分
    var d4=parseInt("0xff");                // 255
    var d5=parseInt("-0xff");               //-255
    var d6=parseFloat(".1");                 //0.1
    var d7=parseInt(".1");                 //0
    var d8=parseInt(".1");                 //NaN,整數不能以點數開始
    var d9=parseFloat("$222.22");          //NaN,數字不能以$開

   

5.parseInt()第二個參數,指定數字的轉換的基數,合法的范圍是2~36

    var d10=parseInt("11",2);      // 3 (1*2+1*1)   相當於將十進制11轉換成2進制
    var d11=parseInt("ff",16);     // 255 (15*16+15*1)   相當於轉換成十六進制 
    var d12=parseInt("077",8);     // 63 (7*8+7*1)   相當於轉換成8進制

 

 

 

6.對象轉換成 原始值

    所有對象都將轉換成true,對於包裝對象也是的,new Boolean(false) 是一個對象而不是原始值,它將轉換為true

     所有的對象都繼承了兩個轉換方法

    1. toString():返回一個反應這個對象的字符串

         ({x:1,y:2}).toString()      //=> “[object object]”

       很多類定義了很多特定版本的toString()方法,例如 數組類的toString()方法將每個數組元素轉換為一個字符串,在元素之間添加逗號后合並成結果字符串,函數類的toString()方法返回這個實現定義的表示方法,還有日期類,正則類什么的

    var tos1=[1,2,3].toString();    //1,2,3
    var tos2=(function(x){ f(x); }).toString();    //  function(x){ f(x); }
    var tos3=/\d+/g.toString();                    //   /\d+/g
    var toS4=new Date(2013,2,22).toString();       //  Fri Mar 22 2013 00:00:00 GMT+0800 (中國標准時間)     
    console.log(toS4);

     

    2.valueOf()

       這個方法的任務並未詳細定義:如果存在任意原始值,它將默認將對象轉換為表示它的原始值。

        對象是復合值,而且大多數對象無法真正表示一個原始值,因為默認的valueOf()方法簡單的返回對象本身,而不是返回一個原始值。數組、函數和正則表達式簡單地繼承了這個默認方法,調用這些類型的是你的valueOf方法只是簡單的返回對象本身,日期類定義的valueOf()方法會返回它的一個內部表示,1970年1月1日以來的毫秒數

       var d=new Date(2010,0,1);      //2010年1月1日

       alert(d.valueOf())                    //1262332800000

    原理太多不講了,感興趣的可以查一下關於 toString()和valueOf()

 

 

16. 變量聲明

    

     1.使用var聲明,不在乎什么類型,聲明了一個變量,未初始化時,初始值都是undefined

       2.形式

             var i;

             var k=”22”;

             var a,b,c;

             var i=0,j=0,k=0;   

            for(var i=0;i<10;i++)console.log(i);           //當循環體只有1條語句時,花括號可以省略

            for(var i=0,j=10;j<10;i++,j—)console.log(i*j);

            for(var p in o)console.log(p);

     3. 編程語言分動態(類型)語言和靜態(類型)語言,動態類型語言是指在 運行期間才做數據類型檢查的語言。例如Python,Ruby,JavaScript等典型的動態類型語言。靜態類型語言,它的數據類型是在編譯期間檢查的,也就是說在寫程序時要聲明所有變量的數據類型,C/C++,Java,C#等

      4.例如var i=10;i=”ten”;  在JavaScript中是合法的

      5. 使用var語句重復聲明變量是合法無害的。如果重復聲明帶有初始化器,那么這就和一條簡單的賦值語句沒什么兩樣

          如果給一個未聲明的變量賦值,這個不好的習慣會造成很多bug,你應該始終使用var來聲明變量

 

17.變量作用域

 

     定義:一個變量的作用域是程序源代碼中定義這個變量的區域。全局變量擁有全局作用域,在JavaScript代碼中的任何地方都有定義的。然而在函數內聲明的變量只在函數體內有定義。他們是局部變量,作用域是局部性的。函數參數是局部變量,它們只在函數體內有定義。

      1.在函數體內,局部變量優先級>同名的全局變量。如果在函數內聲明的一個局部變量或者函數參數中帶有的變量和局部變量重名,那么全局變量就被局部變量所遮蓋

var scope="global";
function checkscope(){
    var scope="local";
    return scope;
    }
alert(checkscope());      //local

 

    2. 盡管在全局作用域編寫代碼時可以不寫var語句,但聲明局部變量時則必須使用var語句

scope="scope";
function checkscope2(){
    scope="local";
    myscope="local";
    return [scope,myscope];
    }
alert(checkscope2().toString());     //local,local

 

     3.函數定義是可以嵌套的,每個函數都有自己的作用域 ,估計很少有人這樣去寫

var scope="global scope"; //全局
function checkscope3(){
     var scope="local scope";
 
      function nested(){
          var scope="nested scope";
          return scope;
          }
 
      return nested();
    }
alert(checkscope3());       //嵌套作用域
 
 

18.函數作用域和聲明提前

    在一些類似C語言的編程語言中,花括號類的每一段代碼都具有各自的作用域,而且變量在聲明他們的代碼段之外是不可見的,我們稱為塊級作用域,Js中是沒有的。Js有的是 函數作用域:變量在聲明它們的函數體以及這個函數體嵌套的任意函數體內都是有定義的

    例 1                    

 

function test(o){
    var i=0;
    if(typeof o =="object"){
        var j=0;
        for(var k=0;k<10;k++){
            console.log(k);
            }
        console.log(k);    //k已經定義了,輸出10,這個在C#或者java中肯定不可以的
        }
    console.log(j);         //0,j已經定義了, var j=0
    }
    
test([1,2,3]);
 
總結:JavaScript的函數作用域是指在函數內聲明的所有變量在函數體內始終可見的。有意思的是,這意味着變量在聲明致歉甚至已經可用。JavaScript這個特性被稱為  聲明提前(hoisting)
     即JavaScript函數里聲明的所有變量(但不涉及賦值)都被“提前”至函數體的頂部。
聲明提前這步驟是在JavaScript引擎的“預編譯”時進行的,是在代碼開始運行之前
 
 
 
    例 2                   
 
var scope="global";
function f1(){
    console.log(scope);    
    }
 
function f2(){
    console.log(scope);       //輸出 "undefined"  而不是 "global"
    var scope="local";        //變量本身在函數體內任何地方均是有定義的
    console.log(scope);    //輸出 “local”
    }
 
f2();

     image

上面的f2方法代碼等同於

function f3(){
    var scope;
    console.log(scope);       //輸出 "undefined"  而不是 "global"
    scope="local";
    console.log(scope);    //輸出 “local”
    }

函數體內,聲明提前,結果優先級高過了同名的全局變量。

 

所以在 具有 塊級作用域 的編程語言中,在狹小的作用域里讓變量聲明和使用變量的代碼盡可能靠近彼此,這個變成習慣非常不錯。但在JavaScript沒有塊級作用域,因此程序員 特意將變量聲明放在函數體頂部。這樣做使他們的源代碼非常清晰地反映了真實的變量作用域。

 

JavaScript全局變量是全局對象的屬性,這是在ECMAScript規范中強制規定的。對於局部變量沒有如此規定。JavaScript可以允許使用this關鍵字來應用全局對象,卻沒有方法可以引用局部變量中存放的對象。

var truevar=1;        //聲明一個不可刪除的全局變量
fakevar=2;             //創建一個全局對象的一個不可刪除的屬性
this.fakevar2=3;      //創建一個全局對象的一個不可刪除的屬性
 
delete truevar;            //false,變量並沒有被刪除
delete fakevar;           //true,變量被刪除
delete this.fakevar2;    //true,變量被刪除
 
console.log(truevar);
console.log(fakevar);
console.log(this.fakevar2);

 

image

 

19.作用域鏈

  在大大小小的一個個作用域里面,就組成了一個作用域鏈,比如,當JavaScript需要查找x的值的時候,它從鏈中的第一個對象開始查找。如果這個對象有一個名為x的屬性,那就直接使用了,查找結束

第一個對象沒有不存在名為x的屬性,JavaScipt會繼續查找鏈上的下一個對象。以此類推,如果作用域鏈上沒有任何一個對象含有屬性x,那么就認為這段代碼的作用域鏈上不存在x,並最終拋出一個引用錯誤(ReferenceError)異常。

  在JavaScript的最頂層代碼中,作用域鏈由一個全局對象組成。在不包含嵌套的函數體內,作用域鏈上有兩個對象,第一個是定義函數參數和局部變量的對象,第二個是全局對象。

  在一個嵌套的函數體內,作用域鏈上至少有3個對象。理解對象鏈非常重要。當定義一個函數時,它實際上保存一個作用域鏈。

image

 

 

作用域的概念對於理解with語句是非常有幫助的,對理解 閉包的概念也至關重要

 

相關資源下載: http://download.csdn.net/download/yangyanghaoran/5168489

 

 

額外贈送:

   Win7小技巧--將資源管理器 默認打開 改成 我的電腦,手動點點設置,就可完成

 

 第一步:右擊 資源管理器展開,再右擊 打開后的列表中 紅色圈住部分,點擊屬性

  

   

    第二步:將紅色區域,目標  右邊的文本框 代碼改成  %SystemRoot%\explorer.exe /e,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}

    

快捷鍵右側的  文本框  按下  win+E鍵

 

第三步:點擊確定。

第四步:你在單擊一下資源管理器,默認就打開我的電腦了,而不再是不常用的 庫了



免責聲明!

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



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