從零開始學習前端JAVASCRIPT — 1、JavaScript基礎


一、定義:javascript是一種弱類型、動態類型、解釋型的腳本語言。

弱類型:類型檢查不嚴格,偏向於容忍隱式類型轉換。

強類型:類型檢查嚴格,偏向於不容忍隱式類型轉換。

動態類型:運行的時候執行類型檢查。

靜態類型:編譯的時候就知道每個變量的類型。

解釋型:程序不需要編譯,程序在運行的時候才翻譯成機器語言,每執行一次都要翻譯一次,因此效率比較低,但是跨平台性好。

編譯型:程序在執行之前需要一個專門的翻譯過程,把程序編譯為機器語言的文件,運行時直接使用編譯的結果就行了。

標記語言:標記語言的存在就是用來被讀取(瀏覽)的,而其本身是沒有行為能力的,在標記語言里你會看到<和>這些尖括號,這是用來寫出“層次”和”屬性”的,換句話說,它是被動的。並不具備與訪問者互動的能力。

編程語言:它是具有邏輯性和行為能力,這是主動的。說通俗一點,它是有思想的。

腳本語言:它介於標記語言和編程語言之間,腳本語言不需要編譯,可以直接用,由解釋器來負責解釋。

二、JS由來及其發展史

1)Netsape發明了javascript。 

1994年,網景公司(Netscape)發布了Navigator瀏覽器0.9版。這是歷史上第一個比較成熟的網絡瀏覽器,轟動一時。但是這個版本的瀏覽器只能用來瀏覽,不具備與訪問者互動的能力。比如,網頁上有一欄用戶名需要填寫,瀏覽器無法判斷用戶是否真的填寫了,只有讓服務器去判斷。如果沒有填寫就返回錯誤,要求用戶重新填寫。太浪費時間和服務器資源了。更何況在那個用調制解調器上網的年代
Javascript歷史

2)JS之父Brendan Eich(布蘭登 · 艾奇) 

網景公司急需一種網頁腳本語言,使得瀏覽器可以與網頁互動。當時工程師Brendan Eich就是負責開發這種新語言。
Javascript歷史

 3)為什么叫JavaScript

1995年Sun公司將Oak語言改名為Java,正式向市場推出。Sun公司大肆宣傳,允諾這種語言可以”一次編譯,到處運行”。很有可能成為未來市場的主宰。 網景公司動了心,決定與Sun公司結成聯盟。它不僅允許JAVA程序以applet(小程序)的形式,直接在瀏覽器中運行。甚至還考慮直接將Java作為腳本語言嵌入網頁,只是因為這樣使 HTML網頁過於復雜,后來才不得不放棄。 總之,因為Sun公司完全介入網頁腳本語言的決策。Js后來就是網景公司和Sun兩家公司一起攜手推向市場的,這種語言被命名為java+script不是偶然的。
Javascipt歷史

 

4)JS和JAVA語言沒有任何關系

JS之父並不喜歡JAVA,為了應付公司安排的任務,他只用了十天就把JS設計出來了。因為設計時間太短,語言的一些細節考慮的並不太嚴謹。 設計思路: 1:借鑒C語言的基本語法。 2:借鑒JAVA語言的數據類型和內存管理。 3:借鑒Scheme語言,將函數提升到”第一等公民的地位”。 4:借鑒Self語言,使用基於原型(prototype)的繼承機制。 所以,JS實際是兩種語言風格的混合產物:(簡化的)函數式編程+(簡化的)面向對象編程。
Javascript歷史

5)JS標准化---ECMAScript

因為javascript1.0的成功,netscape在navigator 3.0中發布1.1版。此時微軟決定進軍瀏覽器,在IE3.0種搭載了javascript的克隆版,叫JScript。在微軟進來以后,有三種不同的javascript版本存在,即navigator3.0的javascript、IE的JScript、以及Cenvi中的ScriptEase。 由於javascript沒有一個標准來統一其語法和特性,3種不同版本的恰恰突出了這個問題,這個語言的標准化顯然勢在必行。 1997年,javascript1.1作為一個草案提交給歐洲計算機制造協會(ECMA)。最后定義為ECMAScript的全新腳本語言。從此,瀏覽器開始努力將ECMAScript作為Javascript的基礎。
Javascrip歷史

三、JS組成 

四、文件引入

 <script>標簽用於定義客戶端腳本。它既可以包含腳本語句,也可以通過src屬性指定外部腳本文件。

屬性:

language:用來指定<script>標簽中的腳本類型,即javascript。已廢棄,大多數瀏覽器已經忽略它了,所以不要在使用。

type:它也是用來指定<script>標簽中的腳本類型,即text/javascript。它也是type的默認值,所以可以忽略指定。

src:指定外部的腳本文件。如果指定該屬性,script標簽包含的JS腳本不會執行。

不可以使用單標簽,即<script type=“text/javascript”/>。

1) 引入外部文件

<script type="text/javascript" src="JS文件"></script>

2.存放在HTML的<head>或<body>中

<script type="text/javascript">
    Js代碼內容
</script>
  • HTML的head中
  • HTML的body代碼塊底部(推薦)

3) 為什么要放在<body>代碼塊底部?

  • HTML代碼從上到下執行,先加載CSS,避免html出現無樣式狀態;
  • 將JavaScript代碼塊放在<body>最后,可以讓網頁盡快的呈現給用戶,減少瀏覽者的等待時間,避免因為JS代碼塊阻塞網頁的呈現。

五、js注釋

注釋可用於提高代碼的可讀性。Javascript不會執行注釋,用戶也不會看到注釋,注釋只是方便開發者更好的理解JS代碼。

單行注釋:以//開頭。

// 這是一行單行注釋 

多行注釋:以/*開頭,以*/結尾。 

/* 第一行注釋 第二行注釋 */

文檔注釋:以/**開頭,以*/結尾。 

/** 這是文檔的注釋 */

重要注釋:以/*!開頭,以*/結尾 

/*! 這是非常重要的注釋 */ 

六、js變量

變量是存儲信息的容器,用var關鍵詞來聲明(創建)變量。

1)變量定義(聲明):

先定義后賦值:

var age;    //var 是關鍵字,age是變量名

age = 20;  //20是數據 “=”是賦值

定義的同時賦值: var age=20;

一條語句中聲明多個變量,該語句以var開頭,並使用英文逗號分隔。

  var x= '加數', y= '加數',z='和';

2)變量的分類

全局變量:在所有的函數外部定義的變量和函數內部不使用var關鍵字則為全局變量 

局部變量:在函數內部定義的變量且必須以var開頭申明

<script type="text/javascript"> 
    // 全局變量 
    name = 'xiaoming';
     function func(){ 
            // 局部變量 
            var age = 18; 
            // 全局變量 
            sex = "man" 
    } 
</script>                    

  

var a = 5;
var b = 6;
var c = 12;
//在此之前定義的三個變量都是全局變量(頁面關閉后被刪除)
function sum() {
    var c = a + b;//局部變量(生存周期:函數執行完畢后被刪除)
    console.log(c);//在此輸出的是局部變量,則輸出結果:11
}
sum();
console.log(c); //在此輸出的變量是全局變量,則輸出的結果:12

  

var a = 5;//全局變量
(function () {
	var a = 7;//局部變量,作用域為此函數代碼塊內
	sum();
})();

function sum() {
	console.log(a + 4);//a的值是全局變量的值,故輸出的結果為9
}

   

注:1, 變量也可以不定義,但強烈不推薦。 2, 變量必須先賦值再使用

七、變量命名規則及常用命名法 

  1)變量命名規則:以字母、數字、下划線和$組成,但是不能以數字開頭。且JS語句和JS變量都是嚴格區分大小寫不能用拼音來命名。

  2)變量常用命名法推薦西班牙命名法,以 小寫字母b,f,i,s開頭表示類型,后接大寫開頭的有意義的單詞。

駝峰命名法(Camel):第一個單詞的首字母小寫,后面的單詞首字母大寫。

帕斯卡命名法(Pascal):所有單詞的首字母大寫。

匈牙利命名法(Hungarian):在變量名最前面添加相應小寫字母來標識變量的類型,后面的單詞首字母大寫。 

// 駝峰命名法 //

var haveGoodGoods = '有好貨';

// 帕斯卡命名法

 var HaveGoodGoods;

// 匈牙利命名法

 var sHaveGoodGoods = '有好貨';

  

 3)盡量使用有意義的單詞作為變量名(語義化),也盡量不要與HTML、CSS中的關鍵字沖突。

                  保留關鍵字列表

八、數據類型

  • 基本數據類型:字符串類型(string)、數值類型(number)、布爾類型(boolean)、undefined、null。

1)字符串類型:必須要由成對的單引號或雙引號包起來。內容可以是任意文本,只要不包含包圍字符串的引號就可以。如果一定要包含,則用反斜杠轉義。

// 字符串類型
var data = 'this is a string';

//字符串包含引號轉義

 var data = '"this is a str\'ing'; 

\0 空字節 \n 換行 \t 制表 \b 空格 \r 回車 \f 進紙 \\ 斜杠 \' 單引號 \" 雙引號  

 

2)數值類型:可以帶小數點,也可以不帶小數點。
 var number = 123;
 var number = 123.4;
 var number = '123.4';

轉換:

parseInt(..)    將某值轉換成整數,不成功則NaN

parseFloat(..) 將某值轉換成浮點數,不成功則NaN

特殊值:

   NaN,非數字。可以使用 isNaN(num) 來判斷,切記不能用if(typeof(num)==NaN)。

  Infinity,無窮大。可以使用 isFinite(num) 來判斷。

 

3)布爾類型:只有兩個值:true,false。

// 布爾類型 true 和 false
 var bool = true;

 

4)undefined:表示變量未定義。

 

5)null:用來表示尚未存在的對象

  • 引用數據類型:對象(object),函數(function)。

1)定義對象(冒號前面的字符串稱為鍵,冒號后面的是值)
   var person = {name: '小明', age: 20};  //name鍵    小明值 

2)定義數組
   var arr = ['小白', '男', 20]; 

3)定義函數(此處數據類型不進行深究)

// 普通函數(聲明式創建函數)
 function func(arg){
     return true;
 } 
// 匿名函數 (表達式創建函數)
var func = function(arg){ 
    return "nick"; 
} 
// 自執行函數 
(function(arg){ 
    console.log(arg); 
})('nick')
// 通過構造函數的方式創建函數
// 構造函數:出現在new運算符后的函數,稱為構造函數
var funcName = new Function ();
document.write(typeof func); //typeof來查看變量的類型
// 執行函數 

func();

九、運算符

  • 算術運算符:+、-、*、/、%(取余)、++(遞增)、--(遞減)

  +運算符:可用於把字符串變量連接起來。

  var  a=1+"5"  //結果為15(字符串)

  //當用/運算符的時候,Math.round的用法(四舍五入)。

 var a = 9 ,b = 7; 
// Math.round:四舍五入到整數位 表達式Math.round(9/7)=1,如果想四舍五入到某小數位則先乘后除 
var c = Math.round(9 / 7 * 100) / 100; 
document.write(c);

parseInt:將字符串轉換成整數,從字符串左側依次查找數值,直到碰到非數值的字符結束

parseFloat:將字符串轉換成浮點數(帶有小數點的數值)。

NaN:not a number  (NaN類型是Number,可用typeof來查看相關類型)

  var a = '0.128.6.7px';   var b = parseInt(a);   //b=0   var b = parseFloat(a);  //b=0.128   document.write(b);  

  

var a = 10.4, b = 7;
//var c = a% b ;
/*按照正常算法3.4,但是js定義的變量都是弱類型,精度相對來說較低出來的結果大概是
3.400000000000000000004,結果接近我們處理的方式如下:*/ 
var c = a * 10 % b / 10;
document.write(c);

    

// ++ (自增) => 前自增(++a)、后自增(a++)
var a = 5; 
// a的前自增:變量本身先自增1,然后再將結果賦予當前位置 
// a的后自增:變量的值先賦予當前位置,然后變量本身再自增1 
var b = 4 + a++; 
document.write(a); // 6 
document.write(b); // 9

  --a和a--原理同++a和a++

	var a = 4, b = 3;
	var c = (a++ + ++b + b-- + --a) % 5;
	//表達式對應值:4+4+4+4 
	/*對應位置a、b的值:
	先4參與運算后加a=5、
	先加++b在運算b=4、 
	先4參與后減b=3、
	先減--4后運算a=4 */
	document.write(a); //4
	document.write(b); //3
	document.write(c); //1

 

  賦值運算符:=、+=、-=、*=、/=、%=

var a = 4, b = 5;
a += b; // a = a + b; 
a %= b; // a = a % b; 
document.write(a); 
document.write(b);
  • 關系(比較)運算符:>、<、>=、<=、==、===、!=、!==

===與==的區別:

對於string和number等基本類型,不同類型之間比較:

1、==比較會將變量隱式轉換成同一類型的值進行比較。

2、===如果類型不同,其結果就是不等。

如果是array和object等引用類型,==和===沒有區別.如果兩個的變量是同一個對象就為true,否則為false。

基本類型和引用類型進行比較,==會將引用類型轉換成基本類型,再進行值比較。而===因為類型不同,結果為false。

// == 和 === 
// 基本數據類型 
var a = 5, b = '5'; 
document.write(a == b); //true 
document.write(a === b);//fasle 

// 引用數據類型:看兩側的變量是否為同一個對象,是則true,不是則false 
var a = {}, b = {}; 
document.write(a == b); //false a、b不同的對象直接返回false
document.write(a === b); //false a、b不同的對象直接返回false
  • 邏輯運算符:&&、||、!

  •  三目運算符(簡化代碼):? :
// 三目運算符:condition ? if_true : if_false;

var c = 5 > 4 ? '恩' : '哦'; alert(c); //c=恩 

十、運算符的優先級(自上而下遞減 ,水平同級) 

1》.(對象、類的屬性或字段訪問)     [](數組下表)       ()(函數調用)    :(三目表達式的分組—表達式的分組)

2》++、--、!、delete(刪除對象的某個屬性及屬性值)、new(創建構造函數和創建對象)、typeof

3》*、/、%

4》+、-、+  加、減、字符串連接

5》關系運算符、instanceof(判斷某個對象是否是某個類的一個實例)

6》邏輯運算符

7》賦值運算符

()作用:可以表達式分組、改變運算符的優先級、函數調用。

例:a=!6<7  =>   true

推理:a=(!6)<7    =>     a=false<7     =>    a=0<7    =>        true               

十一、強制轉換

強制轉換主要指使用Number、String和Boolean三個構造函數,手動將各種類型的值,轉換成數字、字符串或者布爾值。

1>Number強制轉換

參數為原始類型值的轉換規則:

原始類型的值主要是字符串、布爾值、undefined和null,它們都能被Number轉成數值或NaN。

NaN:not a number,當數學計算得不到數字結果時,該值就是NaN(Number類型)。

isNaN:判斷變量是否為NaN。

Number(324) 值:324 字符串如果可以被解析為數值,則轉換為相應的數值
Number('324abc')  值:NaN 字符串:如果不可以被解析為數值,返回NaN
Number('')  值:0 空字符串轉為0
Number(true) 、Number(false) 值:1、0 布爾值:true 轉成1,false 轉成0
Number(undefined) 值:NaN undefined:轉成 NaN
Number(null) 值:0 null:轉成0

Number函數將字符串轉為數值,要比parseInt函數嚴格很多。基本上,只要有一個字符無法轉成數值,整個字符串就會被轉為NaN。

參數為對象的轉換規則:簡單的規則是,Number方法的參數是對象時,將返回NaN。

Number({a: 1}) // NaN

Number([1, 2, 3]) // NaN

實際上,Number背后的真正規則復雜得多,內部處理步驟如下:

1:調用對象自身的valueOf方法。如果返回原始類型的值,則直接對該值使用Number函數,不再進行后續步驟。

2:如果valueOf方法返回的還是對象,則改為調用對象自身的toString方法。如果返回原始類型的值,則對該值使用Number函數,不再進行后續步驟。

3:如果toString方法返回的是對象,就報錯。

2>String強制轉換

參數為原始類型值的轉換規則:

    • 數值:轉為相應的字符串。
    • 字符串:轉換后還是原來的值。
    • 布爾值:true轉為"true",false轉為"false"。
    • undefined:轉為"undefined"。
    • null:轉為"null"。

參數為對象的轉換規則:String方法的參數如果是對象,返回一個類型字符串;如果是數組,返回該數組的字符串形式。

String內部處理步驟如下:

1:先調用對象自身的toString方法。如果返回原始類型的值,則對該值使用String函數,不再進行以下步驟。

2:如果toString方法返回的是對象,再調用valueOf方法。如果返回原始類型的值,則對該值使用String函數,不再進行以下步驟。

3:如果valueOf方法返回的是對象,就報錯。

3>Boolean強制轉換

參數為原始類型值的轉換規則:轉換規則相對簡單:除了以下六個值的轉換結果為false,其他的值全部為true。

undefined、null、-0、0或+0、NaN、''(空字符串)

參數為對象的轉換規則:所有對象(包括空對象)的轉換結果都是true。 

十二、自動轉換

自動轉換具有不確定性,而且不易除錯,建議在預期為布爾值、數值、字符串的地方,全部使用Boolean、Number和String函數進行顯式轉換。

自動轉換的規則:預期什么類型的值,就調用該類型的轉換函數。比如,某個位置預期為字符串,就調用String函數進行轉換。如果該位置可能是字符串,也可能是數值,那么默認轉為數值。

1:自動轉換為布爾值:當JavaScript遇到預期為布爾值的地方(比如if語句的條件部分),就會將非布爾值的參數自動轉換為布爾值。系統內部會自動調用Boolean函數。

if ( !undefined && !null && !0 && !NaN && !'' )

{ console.log('true'); } // true

// 寫法一 expression ? true : false

// 寫法二 !! expression

2:自動轉換為字符串:當JavaScript遇到預期為字符串的地方,就會將非字符串的數據自動轉為字符串。系統內部會自動調用String函數。字符串的自動轉換,主要發生在加法運算時。當一個值為字符串,另一個值為非字符串,則后者轉為字符串。(+號的拼接字符串的作用)

自動轉換為字符串舉例
'5' + 1 // '51'  '5' + true // "5true" '5' + false // "5false"  '5' + {} // "5[object Object]"
'5' + [] // "5" '5' + function (){} // "5function (){}" '5' + undefined // "5undefined“ '5' + null // "5null"

3:自動轉換為數值:當JavaScript遇到預期為數值的地方,就會將參數值自動轉換為數值。系統內部會自動調用Number函數。

自動轉換為數值舉例
'5' - '2' =3  '5' * '2'=10 false - 1=-1 true - 1= 0
'5' * [] = 0 '1' - 1  = 0   false / '5'    = 0 'abc' - 1 = NaN


4.除加法運算符有可能把運算子轉為字符串,其他運算符都會把運算子自動轉成數值。

+'abc' // NaN         -'abc' // NaN              +true // 1             -false // 0

 特殊:(具體原因通過度娘尋根問底)

null == undefined   // true

null == false        // false

undefined == false // false

var str;
//undefined
console.log("只定義未初始化的str類型"+typeof(str)+"只定義未初始化的str值"+str)
var strone="";
//string
console.log("初始化為\"\"的str類型"+typeof(strone)+"初始化為\"\"的str值"+strone)
var strtwo=new String();
//無值相當於"";
if(""==strtwo)
console.log("初始化為new String()的str類型"+typeof(strtwo)+"初始化為new String()的str值"+strtwo)
var strthree=null;
//object
console.log("初始化為null的str類型"+typeof(strthree)+"初始化為null的str值"+strthree)		
var strfour={};
//object
console.log("初始化為{}的str類型"+typeof(strfour)+"初始化為{}的str值"+strfour)

十三、三大結構

1.順序結構

 

2.選擇結構

3.循環結構(當循環結構和直到型循環結構)

十四、JavaScript語句

(一)選擇語句

1)if語句

(1)單一選擇結構:if(){}  

var x=5,y=8; if(y>x) { 
  alert("x>y");
}

(2)二路選擇結構:if(){}else{} 

// 判斷:如果第一個值大於第二個值則alert(OK!)
var x=5,y=8;
if(y> x){
   document.write('OK!');
}
else{
  document.write('NOT OK!');
}  

(3)三目運算符:?: (condition ? if_true : if_false;) 

var x=5,y=8; alert(x> y? 'OK!' : 'NOT OK!')

(4)多路選擇結構:if(){}else if(){}else if(){}else{}

多路選擇結構流程圖:

//此處給出主要代碼為例
if(sScore >= 0 && sScore < 60) { alert('不及格,平常干啥啦!'); } else if(sScore >= 60 && sScore < 70) { alert('剛剛及格,繼續努力!'); } else if(sScore >= 70 && sScore < 80) { alert('一般,再接再厲!'); } else if(sScore >= 80 && sScore < 90) { alert('良好,穩住,你可以的!'); } else if(sScore >= 90 && sScore < 100) { alert('優秀,戒驕戒躁,爭取滿分!'); } else if(sScore == 100) { alert('勞逸結合,注意身體!'); } else { alert('分數非法!'); }

2)switch語句(考慮多路選擇的案例轉換為switch實現,提示:case后的是具體的情況,多路選擇是以表達式的方式進行判斷,即點和面的關系。如:80-90范圍這個面通過除以10,然后通過parseInt進行取整。(面轉成點))

語法:switch(condition){case :break;default:}

break具體講解:阻止代碼向下一個case運行。防止case穿透(穿透性用的好還是挺6的,有時間后續補充案例:給定依據具體日期得出這是本年的第多少天的案例)。

default具體講解:匹配不存在時做的事情。

switch:嚴格檢查類型(形似===的檢查),如果不統一,條件不成立(比如說數字的字符串和case后的Number后的數字無法匹配,需轉成相同的類型)

  // 判定
  switch(iWeekday){
    //利用穿透性
    case 0:
    case 7:
      alert('星期天');
      break;
    case 1:
      alert('星期一');
      break;
    case 2:
      alert('星期二');
      break;
    case 3:
      alert('星期三');
      break;
    case 4:
      alert('星期四');
      break;
    case 5:
      alert('星期五');
      break;
    case 6:
      alert('星期六');
      break;
    default:
      alert('非法數據!');
  }                         

  (二)循環語句

1)for循環語句

// for循環語法
/*
	for(var i = 0; i < 10; i++){
		code...
	}
*/

for(var a = 4; a < 10; a++) {
	document.write(a);
}

// for循環的嵌套
for(var i = 0; i < 5; i++) {
	for(var j = 0; j < 5; j++) {
		document.write(i*j + '、');
	}
	document.write('<br>');
}

 

/* 第1步:聲明變量i = 0; 第2步:判斷條件i < 4,條件成立執行第三步,不成立則退出循環 第3步:執行代碼塊。 第4步:執行i++ 第5步:判斷條件,i < 4,條件成立執行第6步,不成立則退出循環 第6步:執行代碼塊。 第7步:執行i++ 第8步:判斷條件,i < 4,條件成立執行第9步,不成立則退出循環 */
for(var i = 0; i < 4; i++) { document.write(i); }
for執行步驟

 

2)for in語句(可以遍歷數組和對象,經常用於遍歷對象)

遍歷數組

var names = ["nick", "jenny"];
 
for(var index in names){
    console.log(index);
    console.log(names[index]);
}

遍歷對象 

var obj = {name: '張三', age: 24, hobby: ['打籃球', '搏擊', '打乒乓球']};
for(var attr in obj) {
    console.log(obj[attr]);
}

 3)while循環語句

/*
  while語法
while(condition){
  code...
}
*/
var a = 4;

while(a < 10) {
 	document.write(a);
	a++;
}

 4)do-while語句 

/*
do...while語法
do{
  code...
}while(condition);
*/
var a = 4;
do{
  document.write(a);
  a++;
}
while(a < 10);
// while和do...while的區別:執行的順序不一樣
//do...while至少會執行一次代碼塊,while有可能一次都不執行。

  (三)Label語句 

	//label語句   跳出雙重循環   例:條件 i=5 j=5 時  跳出嵌套的雙重for循環   num=55;
	var num = 0;
        outPoint:
        for (var i=0;i<10;i++) {
            for (var j=0;j<10;j++) {
                if (i==5 && j==5) {
                    break outPoint;
                }
                num++;
            }
        }
        console.log(num); //控制台輸出

 (四)異常處理 

try {
    //這段代碼從上往下運行,其中任何一個語句拋出異常該代碼塊就結束運行
}
catch (e) {
    // 如果try代碼塊中拋出了異常,catch代碼塊中的代碼就會被執行。
    //e是一個局部變量,用來指向Error對象或者其他拋出的對象
}
finally {
     //無論上述代碼怎么,finally代碼塊始終會執行
}

 補充:break和continue的區別 

// break和continue
for(var i = 0; i < 10; i++) {
if(i === 5) {
break;
}
document.write(i);
}
for(var i = 0; i < 10; i++) {
if(i === 5) {
continue;
}
document.write(i);
}
// 區別:break終止循環,continue跳過當前循環。
// 共同點:都不會執行后面的代碼。

十五、函數

函數的概念:函數就是把完成特定功能的一段代碼抽象出來,使之成為程序中的一個獨立實體,起個名字(函數名)。可以在同一個程序或其他程序中多次重復使用(通過函數名調用)。
注:編寫好的函數代碼只有通過調用才會執行,不調用的時候不會執行(自執行函數特例)。
函數的作用(好處):
1,使程序變得更簡短而清晰
2,有利於程序維護
3,可以提高程序開發的效率 ,
4,提高了代碼的重用性(復用性)

1>函數的創建方式

// 函數聲明式的方式創建函數
  function funcName() {}

// 函數表達式的方式創建函數
  var funcName = function () {};

// 通過構造函數的方式創建函數
// 構造函數:出現在new運算符后的函數,稱為構造函數
  var funcName = new Function ();

函數聲明式和函數表達式的區別

// 函數聲明式的方式必須指定函數名
function sum() {
	alert(1);
}
sum();
// 函數表達式的方式可以沒有名字
 (function () {
	alert(1);
 })();

2>函數的調用方式

 //創建函數
function hello() {
   document.write('hello ');
   document.write('world ');
 } 
// 方式1:手動調用
 hello();
// 方式2:事件驅動的方式
 var oBox = document.getElementById('box');
oBox.onclick = function () {
   hello();
 };

3>函數的參數(形參和實參)

1.手動傳遞的形參和實參

//函數定義時,定義的變量為形參:a,b
function sum(a, b) {
    alert(a + b);
}
//函數調用時,傳遞的參數值為實參:4,8 sum(4, 8);

補充:對象中,冒號前面的數據可以稱為鍵、下標、或者key,冒號后面的值稱為值或者value

2.JS解析器內置定義的arguments (在函數內部的內置的對象參數,無需自定義可直接使用)

 arguments 值類型(對象類型),包含的是實參的個數和數據

function sum(a, b) { // 通過下標的方式獲取某一個值 console.log(arguments[0]); // 通過遍歷的方式獲取所有的值(下標0起始) for(var i = 0; i < arguments.length; i++) { console.log(arguments[i]);//分別控制台打印5,3,8 } a++;
//a和arguments[0]和指向相同結果可想而知,相同為6
console.log(arguments[0]);//6 
console.log(a);//6 } //手動調用函數 sum(5, 3, 8);

3.return(返回函數執行的結果) 

 // return關鍵詞
 function sum(a, b) {
	 var c = a + b;
	 return c;/*!return只能返回參數只能有一個。return a,b,c 最終返回的結果是c的結果,不會報錯*/
	 /*!return 后面的代碼不會執行*/
	 alert('hello world!');//永遠不會被執行
	 // 函數默認返回的值是undefined
 }
 var d = sum(4, 7);
 console.log(d);

十六、js的解析順序

 第一步:加載第一個script代碼塊
 第二步:語法檢查
 第三步:預解析(將var聲明的變量和聲明式創建的函數放到代碼的最前面)
 第四步:開始正式執行代碼,從上往下。
 第五步:加載第二個script代碼塊。

 

sum();
var sum = function () {
	console.log(a + 8);
}
alert(a);   //undefined
alert(b);   //報錯 
var a = 5;

//代碼預解析時,先將a和sum變量放到代碼最前方,然后創建代碼  var a,sum;然后自上而下執行代碼
//預編譯的代碼結構:
//var a,sum;
//sum();
//var sum = function () {
//	console.log(a + 8);
//}
//alert(a);   //undefined
//alert(b);   //報錯 
//a = 5;

十七、對象

由若干個鍵值對組成的無序集合。每個屬性存放一個原始值,對象或函數

屬性:用屬性值來描述他的狀態

行為:用來改變隊形的行為方法

1>對象申明

var obj = {
 	name: 'jimmy',
 	introduce: function () {
		console.log('我叫jimmy!');
 	}
};

// 通過Object構造函數創建對象
// var obj = new Object();

// 通過自定義的構造函數創建對象
// function Animal() {}

// var dog = new Animal();

// console.log(dog);

 

2>對象的操作

創建對象:

 var bird = {feather: '羽毛', 'color': 'white', "type": '鳥類'};

 var dog = {};

<1>對象調用

console.log(bird.feather);
console.log(bird["feather"]);

<2>對象增加

 

方式1:通過.的方式
 dog.name = '旺財';
 dog.wagTails = function () {
   console.log('旺財正在搖尾巴!');
};

// dog.wagTails();//調用


方式2:通過[]的方式
dog["name"] = '大黃';
dog['tongues'] = function () {
  alert('大黃正在吐舌頭!');
}
//dog.tongues();
//console.log(dog);
 

<3>對象修改 

bird.feather = 'wing';
bird.color = 'pink'; 

<4>對象刪除

delete bird.feather;

<5>對象清空

bird = {};

<6>對象銷毀 

// JS的垃圾回收機制:JS引擎檢測內存,如果某個對象沒有被變量引用,那么就會直接回收該對象
var obj = {size: 100000000}; 

obj = null; 

十八、值傳遞和址傳遞(引用傳遞)

  •  值傳遞:如果變量的值是基本數據類型,那么傳遞值的時候采用的是值傳遞(把值復制一份給另外一個變量)。
  •  址傳遞:如果變量的值是引用數據類型,那么傳遞值的時候采用的是址傳遞(把地址復制一份給另外一個變量)。
  • 相關聯想函數指針(地址)
  •  值類型和引用類型內存存儲的位置分為棧(小區域少量數據)和堆(大片區域大量數據) 
//值類型(值相同,重新開辟內存空間)
var a= 10;
var b = a;
a = 0;
console.log(b);//10

//引用類型(地址相同,一起變)
var a = {num: 10};
var b = a;
a.num = 0;
console.log(b.num);//0

  

var a = {
	name: '張三'
};
var b = {
	name: a
};

var c = b;

var d = {
	name: '李四'
};

c.name = d;

console.log(b.name.name);//張三  

十九、常用函數類型

1>回調函數(指針:通過函數名稱的方式執行的函數) 

*function sum(a, b, fn) {
	var c = a + b;
	if(c > 9) {
		fn();
	}
	console.log(c);
}


sum(7, 5, function () {
	alert(1);
});

 2>遞歸函數(自身調用自身的函數) 

/*
遞歸函數調用分析:
	{
		var num = 1;
		num++; // 2
		if(num < 5) {
			{
				var num = 2;
				num++; // 3
				if(num < 5) {
					{
						var num = 3;
						num++; // 4
						if(num < 5) {
							{
								var num = 4;
								num++; // 5
								if(num < 5) {
									print(num);
								}
								console.log(num); // 5
							}
						}
						console.log(num);
					}
				}
				console.log(num);
			}
		}
		console.log(num);
	}
*/

function print(num) {
	num++;
	if(num < 5) {
		print(num);
	}
	console.log(num);
}

print(1);

 3>匿名函數

(function () {})();

4>構造函數

function Person() {
	alert(1);
}

var obj = new Person();

console.log(obj);

二十、數組 

定義:數組是一個可以存儲一組或一系列相關數據的容器。

為什么要使用數組?

   1:為了解決大量相關數據的存儲和使用的問題。

   2:模擬真實的世界(班級、軍隊)。

1>數組的操作

1)創建數組

  (1)構造函數的方式:var a=new Array();

  (2)隱式聲明的方式:var b=[];

2)數組的賦值

構造函數函數的方式

(1)直接賦值:var a=new Array(數據1,數據2,…);

    注:var a=new Array(數值)       如果括號中只有一個元素,並且這個元素是數值類型的,那么他就是指定數組的長度。 並且它的值都是undefined。

  數組的屬性:length 屬性(獲取整個數組的長度)。

(2)先聲明后賦值:var a=new  Array(); a[0]=1;  a[1]=2;  a[2]=3;

隱式聲明賦值

(1)直接賦值: var a=[1,2,3,4];

(2)聲明以后再賦值: var a=[]; a[0]=1;  a[1]=2;  a[2]=3;

注:JS數組可以存儲任何類型的值。eg: arr[3] = function () {}; 

3)訪問數組 

  通過數組的(中括號)下標訪問。 

    arr[0-(length-1)] //數組下標從0開始,他的最大值,是length-1。

  arr['name'] //關聯數組 通過下表字符串進行訪問

4) 修改數據:arr[3] = '修改的數據';

5)刪除數據:delete arr[1]; 

6)遍歷數組

1:for循環。

for(var i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

2:while循環。

var i = 0;
while(i < arr.length) {
  console.log(arr[i]);
  i++;
}  

3:for in循環。(遍歷數組不常用)

  數組的遍歷。

for(var attr in arr){

  //attr 數組的下標

  console.log(arr[attr])

}

  對象屬性的遍歷。

  // 使用for in 遍歷對象

  var obj = {name: '小明', age: 24, hobby: ['打籃球', '搏擊', '打乒乓球']};

  for(var attr in obj) {
    console.log(obj[attr]);
  }

2>數組分類

1:按照下標的類型

     1.下標是數字的類型叫做(索引數組)

  var arr = ['1', '2' , '3']; 

     2.下標是字符串類型叫做(關聯數組),必須通過對象模擬的形式才能實現,一般不用。

var arr = [];
arr['name'] = '張三';
arr['age'] = '28';

2:按照維度來分類

  1.一維數組常用的數組就是一維數組

  2.二維數組,通過對象模擬的形式才能實現。

  聲明二維數組:

  var arr=[[1,2,3],[4,5,6]];    alert(arr[1][1]); //值5

3>數組的屬性 

(1)length: 設置或返回數組元素的數目。(可讀可寫)

length屬性控制數組的讀:console.log(arr.length-1);

length屬性控制數組的寫:arr.length = 6; 

(2)constructor:返回構造函數的引用。(輸出constructor的返回值:Array)

4>數組的方法(加粗常用)

  前五個對原始對象的操作

1. arr.push(數組元素1,數組元素2,........)   向數組的末尾加入新元素 | 返回值:新數組的長度

 eg:arr.push('追加元素1','追加元素2');

2.arr.unshift(數組元素1,數組元素2,........)  向數組的開頭加入新元素 | 返回值是新數組的長度。

 eg:arr.unshift(開頭新元素1,開頭新元素2)

3. arr.pop()    刪除數組的最后一個元素 | 返回值是刪除的元素。 

var first = arr.pop();

4. arr.shift()  刪除數組的第一個元素 | 返回刪除的元素。

var first = arr.shift();

5.萬能的添加刪除函數 arr.splice(index,數量,添加的元素.....)  注:前倆個元素必須有 

   (1)index   從何處開始添加或刪除,必須是數值類型(數組的下標) 

   (2)數量    規定了刪除的個數,如果是0,則不刪除。 

   (3)需要添加的元素,可以當作替換的元素。 

   (4)如果有刪除的元素,以數組的方式返回刪除的元素。 

// 添加元素
arr.splice(2, 0, '王五');
// 修改元素
arr.splice(1, 1, '王五');
//修改與添加
arr.splice(1, 1, '王五','李四');
// 刪除元素 
var del = arr.splice(1, 1); 

 6.arr.join([分隔符])   把數組元素按照指定分隔符組合成一個字符串,如果沒有指定分隔符,默認是用“,”分割 | 返回結果就是組合成的字符串。   

var param = {
	q: '棉衣',
	commend: 'all',
	search_type: 'item'
};

var aParam = [];
for(var attr in param) {
	aParam.push(attr + '=' + param[attr]);
}
console.log(aParam.join('&'));  //以字符&分割連接數組
//結果:q=棉衣&commend=all&search_type=item

  7.arr.slice()  數組的分割。從截取指定的開始位置,到結束位置(不包括)的元素。如果不指定結束位置,則從指定的開始位置,取到結尾(數組的下標)。 

支持負數(-1開頭)  返回的是新數組。 不改動原來的數組。正數和負數都是向右查找 

var arr = ['宋江', '盧俊義', '武松', '楊雄', '石秀', '魯智深'];
var newArr = arr.slice();相當於拷貝數組
var newArr = arr.slice(2);//不指定結束為止,默認為截取到最后
var newArr = arr.slice(2, 5);//結果為下標為2、3、4的數組元素,不包含為指定結尾下標數的元素
var newArr = arr.slice(-2, -1);  //從末尾開始計數分割  只能按照從左向右的順序進行截取,即不支持arr.slice(-1, -2)   結果:'石秀'

8. arr.concat()   連接兩個或更多的數組,並返回新數組,對原數組沒有任何影響。 

eg:arr1.concat(arr2)  //將數組arr1和arr2連接成新數組返回

9.arr.reverse()  數組翻轉方法。改變原數組 

arr.reverse(arr)  //將數組翻轉

 

10.arr.sort()   對數組進行排序,如果沒有參數,則按照字母的編碼進行排序,如果要按照其他的順序來排序,要提供一個函數。

回調函數會提供兩個參數(a,b)。

 

a<b  a在b前。

a=b  順序按照原樣輸出。

a>b  b在a前。 

eg:

['d', 'c', 'b', 'a'].sort()  // ['a', 'b', 'c', 'd'] 

[4, 3, 2, 1].sort()  // [1, 2, 3, 4] 

[11, 101].sort()  // [101, 11] 

[10111, 1101, 111].sort()  // [10111, 1101, 111] 

如果想讓sort方法按照自定義方式排序,可以傳入一個函數作為參數,表示按照自定義方法進行排序。該函數本身接受兩個參數,表示進行比較的兩個元素。如果返回值大於0,表示第一個元素排在第二個元素后面;其他情況下,都是第一個元素排在第二個元素前面。

返回值正直交換   零、負值不交換  負值降序   正值升序

 [10111, 1101, 111].sort(function (a, b) { 

     return a - b; //回調函數

})   //輸出結果: [111, 1101, 10111] 

[ { name: "張三", age: 30 }, { name: "李四", age: 24 }, { name: "王五", age: 28 } ].sort(function (o1, o2) { 

    return o1.age - o2.age;

})   // [ { name: "李四", age: 24 }, { name: "王五", age: 28 }, { name: "張三", age: 30 } ] 

二十一、排序

1>冒泡排序 

// 冒泡排序:從前往后對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的往上冒
var arr = [23, 34, 11, 22, 19, 18]; /* 冒泡排序的思路分析: 第1輪 第1步:[23, 34, 11, 22, 19, 18] 第1輪 第2步:[23, 11, 34, 22, 19, 18] 第1輪 第3步:[23, 11, 22, 34, 19, 18] 第1輪 第4步:[23, 11, 22, 19, 34, 18] 第1輪 第5步:[23, 11, 22, 19, 18, 34] 第2輪 第1步:[11, 23, 22, 19, 18, 34] 第2輪 第2步:[11, 22, 23, 19, 18, 34] 第2輪 第3步:[11, 22, 19, 23, 18, 34] 第2輪 第4步:[11, 22, 19, 18, 23, 34] 第3輪 第1步:[11, 22, 19, 18, 23, 34] 第3輪 第2步:[11, 19, 22, 18, 23, 34] 第3輪 第3步:[11, 19, 18, 22, 23, 34] 第4輪 第1步:[11, 19, 18, 22, 23, 34] 第4輪 第2步:[11, 18, 19, 22, 23, 34] 第5輪 第1步:[11, 18, 19, 22, 23, 34] */
冒泡排序的思路推演

  

for(var i = 1; i < arr.length; i++) {
	// 內層for循環確定每輪的步數
	for(var j = 0; j < arr.length - i; j++) {
		// 兩兩比較
		if(arr[j] > arr[j + 1]) {
			var temp = arr[j];
			arr[j] = arr[j + 1];
			arr[j + 1] = temp;
		}
	}
}

2>選擇排序 

//選擇排序:兩兩比較,找到最大值(或者最小值)之后,將其放在正確的位置,其他數的位置不變。 /* 選擇排序的思路分析: 第1輪 第1步:var iMinK = 0; 第1輪 第2步:23 和 34比較,什么也不做 第1輪 第3步:23 和 11比較,iMinK = 2 第1輪 第4步:11 和 22比較,什么也不做 第1輪 第5步:11 和 19比較,什么也不做 第1輪 第6步:11 和 18比較,什么也不做 第1輪 第7步:下標0和下標2進行位置交換 [11, 34, 23, 22, 19, 18] 第2輪 第1步:var iMinK = 1; 第2輪 第2步:34 和 23比較,iMinK = 2 第2輪 第3步:23 和 22比較,iMinK = 3 第2輪 第4步:22 和 19比較,iMinK = 4 第2輪 第5步:19 和 18比較,iMinK = 5 第2輪 第6步:下標1和下標5進行位置交換 [11, 18, 23, 22, 19, 34] */
選擇排序的思路推演

 

// 外層for循環確定輪數
for(var i = 0; i < arr.length - 1; i++) {
	// 記錄最小值的下標
	var iMinK = i;
	for(var j = i + 1; j < arr.length; j++) {
		if(arr[iMinK] > arr[j]) {
			iMinK = j;
		}
	}
	// 交換數據
	if(iMinK !== i) {
		var temp = arr[i];
		arr[i] = arr[iMinK];
		arr[iMinK] = temp;
	}
}

  3>插入排序

在要排序的一組數中,假設前面的數已經是排好順序的,現在要把第n個數插到前面的有序數中,使得這n個數也是排好順序的。如此反復循環,直到全部排好順序。


/*
插入排序的思路分析:
第1輪 第1步:[23, 34, 11, 22, 19, 18]


第2輪 第1步:[23, 11, 34, 22, 19, 18]
第2輪 第2步:[11, 23, 34, 22, 19, 18]


第3輪 第1步:[11, 23, 22, 34, 19, 18]
第3輪 第2步:[11, 22, 23, 34, 19, 18]
第3輪 第3步:[11, 22, 23, 34, 19, 18]


第4輪 第1步:[11, 22, 23, 19, 34, 18]
第4輪 第2步:[11, 22, 19, 23, 34, 18]
第4輪 第3步:[11, 19, 22, 23, 34, 18]
第4輪 第4步:[11, 19, 22, 23, 34, 18]


第5輪 第1步:[11, 19, 22, 23, 18, 34]
第5輪 第2步:[11, 19, 22, 18, 23, 34]
第5輪 第3步:[11, 19, 18, 22, 23, 34]
第5輪 第4步:[11, 18, 19, 22, 23, 34]
第5輪 第5步:[11, 18, 19, 22, 23, 34]
*/
插入排序的思路分析

 

for(var i = 1; i < arr.length; i++) {
	// 內層的for循環
	for(var j = i; j > 0; j--) {
		if(arr[j] < arr[j - 1]) {
			var temp = arr[j];
			arr[j] = arr[j - 1];
			arr[j - 1] = temp;
		} else {
			break;
		}
	}
}

   4>快速排序

//選擇一個基准元素,通常選擇第一個元素或者最后一個元素。
//通過一趟掃描,將待排序列分成兩部分,一部分比基准元素小,一部分大於等於基准元素。
//此時基准元素在其排好序后的正確位置,然后在用同樣的方法遞歸的排序划分的兩部分。


/*
排序數組:23, 35, 34, 11, 22, 19, 18
快速排序的思路分析:
第一步:base = 23 , arr = [35, 34, 11, 22, 19, 18]
第二步:left = [], right = []
第三步:[11, 22, 19, 18] 23 [35, 34]
第四步: [] 11 [22, 19, 18] 23 [34] 35 []
第五步:[] 11 [19, 18] 22 [] 23 [34] 35 []
第六步:[11, 18, 19, 22, 23, 34, 35]
*/


/*
if(arr.length <= 1) {
return arr; 
}
var iBase = arr.shift();
var left = [], right = [];


for(var i = 0; i < arr.length; i++) {
if(arr[i] < iBase) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
left: [11, 22, 19, 18] iBase: 23 , right: [35, 34]

從上開始正推返回表達式:return quickSort(left即[11,22,19, 18]).concat(iBase=23, quickSort(right即[35,34]));


從下開始逆推返回值:return [11, 18, 19, 22].concat(23, [35,34]);//合並后的數組:[11,18,19,22,23,34,35]


-------------------------------------------我是單次遞歸分割線-----------------------------------------------


if(arr.length <= 1) {
return arr; 
}
var iBase = arr.shift();
var left = [], right = [];


for(var i = 0; i < arr.length; i++) {
if(arr[i] < iBase) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}


left: [] iBase: 11 right: [22, 19, 18]

從上開始正推返回表達式:return quickSort(left即[]).concat(iBase=11, quickSort(right即[22,19,18]));


從下開始逆推返回值:return [].concat(11, [18, 19, 22]); //合並后的數組:[11, 18, 19, 22]


-------------------------------------------我是單次遞歸分割線-----------------------------------------------


if(arr.length <= 1) {
return arr; 
}
var iBase = arr.shift();
var left = [], right = [];


for(var i = 0; i < arr.length; i++) {
if(arr[i] < iBase) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}


left: [19, 18] iBase: 22 right: []

從上開始正推返回表達式:return quickSort(left即[19, 18]).concat(iBase=22, quickSort(right即[]));


從下開始逆推返回值:return [18, 19].concat(22, []); //合並后的數組: [18, 19, 22]


-------------------------------------------我是單次遞歸分割線-----------------------------------------------


if(arr.length <= 1) {
return arr; 
}
var iBase = arr.shift();
var left = [], right = [];
for(var i = 0; i < arr.length; i++) {
if(arr[i] < iBase) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
left: [18] iBase: 19, right: []
從上開始正推返回表達式:return quickSort(left即[18]).concat(iBase=19, quickSort(right即[]));
從下開始逆推返回值:return [18].concat(19, []); //合並后的數組: [18, 19]

*/
快速排序思路推演

  

var arr = [23, 35, 34, 11, 22, 19, 18, 18];
function quickSort(arr) {
	if(arr.length <= 1) {
		return arr;	
	}
	var iBase = arr.shift();
	var left = [], right = [];

	for(var i = 0; i < arr.length; i++) {
		if(arr[i] < iBase) {
			left.push(arr[i]);
		} else {
			right.push(arr[i]);
		}
	}

	return quickSort(left).concat(iBase, quickSort(right));
}

var newArr = quickSort(arr);

console.log(newArr);

附錄:

進制間的轉換(二進制、八進制、十進制、十六進制)

1>10進制轉換為16進制:(10).tostring(16)

2>8轉16:(012).tostring(16)

3>16轉10:(0x).tostring(10)

4>10轉2:(111111).tostring(2)

5>16轉8:(0x16).tostring(8)

6>parseInt(10,2)

7>parseInt(12,16)

8>parseInt(12,8)

 


免責聲明!

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



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