1. 程式人生 > 實用技巧 >JavaScript基本語法(全)

JavaScript基本語法(全)

JavaScript 是什麼

  • JavaScript 是世界上最流行的語言之一,是一種執行在客戶端的指令碼語言 (Script 是指令碼的意思)
  • 指令碼語言:不需要編譯,執行過程中由 js 直譯器( js 引擎)逐行來進行解釋並執行
  • 現在也可以基於 Node.js 技術進行伺服器端程式設計

JavaScript的作用

  • 表單動態校驗(密碼強度檢測) ( JS 產生最初的目的 )
  • 網頁特效
  • 服務端開發(Node.js)
  • 桌面程式(Electron)
  • App(Cordova)
  • 控制硬體-物聯網(Ruff)
  • 遊戲開發(cocos2d-js)

HTML/CSS/JS 的關係

HTML/CSS 標記語言--描述類語言

  • HTML 決定網頁結構和內容( 決定看到什麼 ),相當
    於人的身體
  • CSS 決定網頁呈現給使用者的模樣( 決定好不好看 ),
    相當於給人穿衣服、化妝
  • JS 指令碼語言--程式設計類語言
    實現業務邏輯和頁面控制( 決定功能 ),相當
    於人的各種動作

瀏覽器執行 JS 簡介

瀏覽器分成兩部分:渲染引擎和 JS 引擎

  • 渲染引擎:用來解析HTML與CSS,俗稱核心,比如 chrome 瀏覽器的 blink ,老版本的 webkit
  • JS 引擎:也稱為 JS 直譯器。 用來讀取網頁中的JavaScript程式碼,對其處理後執行,比如 chrome 瀏覽器的 V8
    瀏覽器本身並不會執行JS程式碼,而是通過內建 JavaScript 引擎(直譯器) 來執行 JS 程式碼 。JS 引擎執行程式碼時逐行解釋
    每一句原始碼(轉換為機器語言),然後由計算機去執行,所以 JavaScript 語言歸為指令碼語言,會逐行解釋執行。

JS 的組成

  • ECMAScript:ECMAScript 規定了JS的程式設計語法和基礎核心知識,是所有瀏覽器廠商共同遵守的一套JS語法工業標準。
  • 文件物件模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴充套件標記語言的標準程式設計介面。
    通過 DOM 提供的介面可以對頁面上的各種元素進行操作(大小、位置、顏色等)。
  • BOM (Browser Object Model,簡稱BOM) 是指瀏覽器物件模型,它提供了獨立於內容的、可以與瀏覽器視窗進行
    互動的物件結構。通過BOM可以操作瀏覽器視窗,比如彈出框、控制瀏覽器跳轉、獲取解析度等。

JS的使用

JS 有3種書寫位置,分別為行內、內嵌和外部。

  1. 行內式 JS
<input type="button" value="點我試試" onclick="alert('Hello World')" />

2.內嵌 JS

<script>
alert('Hello World~!');
</script>

3.外部 JS檔案

<script src="my.js"></script>

利於HTML頁面程式碼結構化,把大段 JS程式碼獨立到 HTML 頁面之外,既美觀,也方便檔案級別的複用

  • 引用外部 JS檔案的 script 標籤中間不可以寫程式碼
  • 適合於JS 程式碼量比較大的情況

JS註釋

  • 單行註釋
    為了提高程式碼的可讀性,JS與CSS一樣,也提供了註釋功能。JS中的註釋主要有兩種,分別是單行註釋和多行註釋。
    單行註釋的註釋方式如下:
// 用來註釋單行文字( 快捷鍵 ctrl + / )
  • 註釋多行
/*  用來註釋多行文字( 預設快捷鍵 alt + shift + a )*/


快捷鍵修改為: ctrl + shift + /

vscode - 首選項按鈕 -鍵盤快捷方式 -查詢 原來的快捷鍵 - 修改為新的快捷鍵 - 回車確認

JavaScript 輸入輸出語句

為了方便資訊的輸入輸出,JS中提供了一些輸入輸出語句,其常用的語句如下:

方法 說明 歸屬
alert() 瀏覽器彈出警示框 瀏覽器
console.log() 瀏覽器控制檯列印輸出資訊 瀏覽器
prompt() 瀏覽器彈出輸入框,使用者可以輸入 瀏覽器

注意:alert() 主要用來顯示訊息給使用者,console.log() 用來給程式設計師自己看執行時的訊息。

什麼是變數

  • 通俗:變數是用於存放資料的容器。 我們通過 變數名 獲取資料,甚至資料可以修改。
  • 變數在記憶體中的儲存
    本質:變數是程式在記憶體中申請的一塊用來存放資料的空間。
    類似我們酒店的房間,一個房間就可以看做是一個變數。

變數的使用

變數在使用時分為兩步: 1. 宣告變數 2. 賦值

  1. 宣告變數
    // 宣告變數
var age; // 宣告一個 名稱為age 的變數
  • var 是一個 JS關鍵字,用來宣告變數( variable 變數的意思 )。使用該關鍵字宣告變數後,計算機會自動為變數分配記憶體空間。
  • age 是程式設計師定義的變數名,我們要通過變數名來訪問記憶體中分配的空間
  1. 賦值
age = 10; // 給 age 這個變數賦值為 10
  • = 用來把右邊的值賦給左邊的變數空間中 此處代表賦值的意思
  • 變數值是程式設計師儲存到變數空間裡的值
  1. 變數的初始化
var age = 18; // 宣告變數同時賦值為 18

宣告一個變數並賦值, 我們稱之為變數的初始化。
注意:一個變數被重新復賦值後,它原有的值就會被覆蓋,變數值將以最後一次賦的值為準。

4.同時宣告多個變數

同時宣告多個變數時,只需要寫一個 var, 多個變數名之間使用英文逗號隔開。

var age = 10, name = 'zs', sex = 2;

5.變數命名規範

-  由字母(A-Za-z)、數字(0-9)、下劃線(_)、美元符號( $ )組成,如:usrAge, num01, _name
-  嚴格區分大小寫。var app; 和 var App; 是兩個變數
- 不能 以數字開頭。 18age 是錯誤的
- 不能 是關鍵字、保留字。例如:var、for、while
- 變數名必須有意義。 
- 遵守駝峰命名法。首字母小寫,後面單詞的首字母需要大寫。 myFirstName

資料型別

1.為什麼需要資料型別
在計算機中,不同的資料所需佔用的儲存空間是不同的,為了便於把資料分成所需記憶體大小不同的資料,充分利用儲存空間,於是定義了不同的資料型別。

2.變數的資料型別
變數是用來儲存值的所在處,它們有名字和資料型別。變數的資料型別決定了如何將代表這些值的位儲存到計算機的記憶體中。
JavaScript 是一種弱型別或者說動態語言。這意味著不用提前宣告變數的型別,在程式執行過程中,型別會被自動確定。

var age = 10; // 這是一個數字型
var areYouOk = '是的'; // 這是一個字串
var x = 6; // x 為數字
var x = "Bill"; // x 為字串

在程式碼執行時,變數的資料型別是由 JS引擎 根據 = 右邊變數值的資料型別來判斷 的,執行完畢之後, 變數就確定了資料型別。
JavaScript 擁有動態型別,同時也意味著相同的變數可用作不同的型別:

var x = 6; // x 為數字
var x = "Bill"; // x 為字串

資料型別的分類

  1. JS 把資料型別分為兩類:
  • 簡單資料型別 (Number,String,Boolean,Undefined,Null)
  • 複雜資料型別 (object)
  1. 簡單資料型別(基本資料型別)
    JavaScript 中的簡單資料型別及其說明如下:
簡單資料型別 說明 預設值
Number 數字型,包含整型值和浮點型值,如21. 0.21 0
Boolean 布林值型別,如true、 false, 等價於1和0 false
String 字串型別,如'張三'注意咱們js裡面,字串都帶引號 ''
Undefined var a;聲明瞭變數a但是沒有給值,此時a = undefined undefined
Null vara=null;聲明瞭變數a為空值 null
  1. 數字型範圍
    JavaScript中數值的最大和最小值
alert(Number.MAX_VALUE); // 1.7976931348623157e+308
alert(Number.MIN_VALUE); // 5e-324
  • 最大值:Number.MAX_VALUE,這個值為: 1.7976931348623157e+308
  • 最小值:Number.MIN_VALUE,這個值為:5e-32
  1. 數字型三個特殊值
alert(Infinity); // Infinity
alert(-Infinity); // -Infinity
alert(NaN); // NaN
- Infinity ,代表無窮大,大於任何數值
- -Infinity ,代表無窮小,小於任何數值
- NaN ,Not a number,代表一個非數值

5.isNaN()
用來判斷一個變數是否為非數字的型別,返回 true 或者 false

var usrAge = 21;
var isOk = isNaN(userAge);
console.log(isNum); // false ,21 不是一個非數字
var usrName = "andy";
console.log(isNaN(userName)); // true ,"andy"是一個非數字

6.字串型 String
字串型可以是引號中的任意文字,其語法為 雙引號 "" 和 單引號''

var strMsg = "我愛北京~"; // 使用雙引號表示字串
var strMsg2 = '我愛北京~'; // 使用單引號表示字串

注意:因為 HTML 標籤裡面的屬性使用的是雙引號,JS 這裡我們更推薦使用單引號。
7.字串引號巢狀
JS 可以用單引號巢狀雙引號 ,或者用雙引號巢狀單引號 (外雙內單,外單內雙)

var strMsg = '我要"親親"寶寶'; // 可以用''包含""
var strMsg2 = "我要'親親'寶寶"; // 也可以用"" 包含''

8.字串轉義符
類似HTML裡面的特殊字元,字串中也有特殊字元,我們稱之為轉義符。
轉義符都是 \ 開頭的
轉義符都是 \ 開頭的,常用的轉義符及其說明如下:

轉義符 解釋說明
\n 換行符,n 是 newline 的意思
\ \ 斜槓 \
' ' 單引號
" ”雙引號
\t tab 縮排
\b 空格 ,b 是 blank 的意思

9.字串是由若干字元組成的,這些字元的數量就是字串的長度。通過字串的 length 屬性可以獲取整個字串的長度。
(注意空格也是一個字串哦)

var strMsg = "我餓了!";
alert(strMsg.length); // 顯示 4

10.字串拼接

  • 多個字串之間可以使用 + 進行拼接,其拼接方式為 字串 + 任何型別 = 拼接之後的新字串
  • 拼接前會把與字串相加的任何型別轉成字串,再拼接成一個新的字串
//1 字串 "相加"
alert('hello' + ' ' + 'world'); // hello world
//2 數值字串 "相加"
alert('100' + '100'); // 100100
//3 數值字串 + 數值
alert('11' + 12); // 1112

11.布林型 Boolean
布林型別有兩個值:true 和 false ,其中 true 表示真(對),而 false 表示假(錯)。
布林型和數字型相加的時候, true 的值為 1 ,false 的值為 0。

console.log(true + 1); // 2
console.log(false + 1); // 1

12.Undefined 和 Null
一個聲明後沒有被賦值的變數會有一個預設值 undefined ( 如果進行相連或者相加時,注意結果)

var variable;
console.log(variable); // undefined
console.log('你好' + variable); // 你好undefined
console.log(11 + variable); // NaN
console.log(true + variable); // NaN

一個宣告變數給 null 值,裡面存的值為空(學習物件時,我們繼續研究null)


var vari = null;
console.log('你好' + vari); // 你好null
console.log(11 + vari); // 11
console.log(true + vari); // 1

獲取檢測變數的資料型別

1.typeof 可用來獲取檢測變數的資料型別

var num = 18;
console.log(typeof num) // 結果 number

注意:null的返回值不是null,是object
2.字面量
字面量是在原始碼中一個固定值的表示法,通俗來說,就是字面量表示如何表達這個值。

資料型別轉換

使用表單、prompt 獲取過來的資料預設是字串型別的,此時就不能直接簡單的進行加法運算,而需要轉換變數的資料型別。通俗來說,就是把一種資料型別的變數轉換成另外一種資料型別。
我們通常會實現3種方式的轉換:

  • 轉換為字串型別
  • 轉換為數字型
  • 轉換為布林型

1.轉換為字串

方式 說明 案例
toString( ) 轉成字串 var num= 1; alert(num.toString);
String( )強制轉換 轉成字串 var num = 1; alert(String(num);
  • toString() 和 String() 使用方式不一樣。

2.轉換為數字型(重點)

方式 說明 案例
parselInt(string)函式 將string型別轉成整數數值型 parselnt(78)
parseFloat(string)函式 將string型別轉成浮點數數值型 parseFloat(78.21')
Number()強制轉換函式 將string型別轉換為數值型 Number('12')
js隱式轉換(- * /) 利用算術運算隱式轉換為數值型 '12'-0
  • 注意 parseInt 和 parseFloat 單詞的大小寫,這2個是重點
  • 隱式轉換是我們在進行算數運算的時候,JS 自動轉換了資料型別

3.轉換為布林型

  • 代表空、否定的值會被轉換為 false ,如 ''、0、NaN、null、undefined
  • 其餘值都會被轉換為 true
方式 說明 案例
Boolean( )函式 其他型別轉成布林值 Boolean'true';
console.log(Boolean('')); // false
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean('小白')); // true
console.log(Boolean(12)); // true

運算子(操作符)

運算子的分類

運算子(operator)也被稱為操作符,是用於實現賦值、比較和執行算數運算等功能的符號。

JavaScript中常用的運算子有:
- 算數運算子
- 遞增和遞減運算子
- 比較運算子
- 邏輯運算子
- 賦值運算子

算數運算子

  • 算術運算子概述

    概念:算術運算使用的符號,用於執行兩個變數或值的算術運算。

運算子 描述 例項
+ 10+ 20= 30
- 10- 20=-10
* 10* 20= 200
/ 10/20= 0.5
% 取餘數(取模) 返回除法的餘數9%2= 1
  • 浮點數的精度問題

    ​ 浮點數值的最高精度是 17 位小數,但在進行算術計算時其精確度遠遠不如整數。

    var result = 0.1 + 0.2;//結果是:0.30000000000000004
    console.log(0.07 * 100);//結果是:7.000000000000001
    

    所以:不要直接判斷兩個浮點數是否相等 !

  • 表示式和返回值

  表示式:是由數字、運算子、變數等以能求得數值的有意義排列方法所得的組合
  ​簡單理解:是由數字、運算子、變數等組成的式子
  ​表示式最終都會有一個結果,返回給開發者,稱為返回值

遞增和遞減運算子

  • 遞增和遞減運算子概述

    ​ 如果需要反覆給數字變數新增或減去1,可以使用遞增(++)和遞減( -- )運算子來完成。

    在 JavaScript 中,遞增(++)和遞減( -- )既可以放在變數前面,也可以放在變數後面。放在變數前面時,我們可以稱為前置遞增(遞減)運算子,放在變數後面時,我們可以稱為後置遞增(遞減)運算子。

      注意:遞增和遞減運算子必須和變數配合使用。 
    
  • 遞增運算子

    • 前置遞增運算子

      ++num 前置遞增,就是自加1,類似於 num = num + 1

      使用口訣:先自加,後返回值

    var  num = 10;
    alert(++num + 10);   // 21
    
    • 後置遞增運算子

      num++ 後置遞增,就是自加1,類似於 num = num + 1

      使用口訣:先返回原值,後自加

    var  num = 10;
    alert(10 + num++);  // 20
    

總結:

1. 前置遞增和後置遞增運算子可以簡化程式碼的編寫,讓變數的值 + 1 比以前寫法更簡單
2. 單獨使用時,執行結果相同
3. 與其他程式碼聯用時,執行結果會不同
4. 後置:先原值運算,後自加(先人後己)
5. 前置:先自加,後運算(先已後人)
6. 大多使用後置遞增/減,並且程式碼獨佔一行,例如:num++; 或者 num--;

比較運算子

  • 比較運算子概述

    ​ 概念:比較運算子(關係運算符)是兩個資料進行比較時所使用的運算子,比較運算後,會返回一個布林值(true / false)作為比較運算的結果。

運算子名稱 說明 案例 結果
< 小於號 1<2 true
> 大於號 1>2 false
>= 大於等於號(大於或者等於) 2>= 2 true
<= 小於等於號(小於或者等於) 3<= 2 false
== 等號 37 == 37 true
!= 不等號 37 != 37 false
=== 全等要求值和資料型別都一致 37 === '37' false
  • 等號比較
符號 作用 用法
= 賦值 把右邊給左邊
== 判斷 判斷兩邊值是否相等
=== 全等 判斷兩邊的值和資料型別是否完全相同
console.log(18 == '18'); // true
console.log(18 === '18'); // false

邏輯運算子

  • 邏輯運算子概述

    ​ 邏輯運算子是用來進行布林值運算的運算子,其返回值也是布林值。後面開發中經常用於多個條件的判斷

邏輯運算子 說明 案例
&& “邏輯與",簡稱"與”and true && false
|| "邏輯或",簡稱"或” or true || false
! “邏輯非",簡稱“非" not ! true
  • 邏輯與&&

    ​ 兩邊都是 true才返回 true,否則返回 false

  • 邏輯或 ||

    ​ 兩邊都是 true才返回 true,否則返回 false

  • 邏輯非 !

    ​ 邏輯非(!)也叫作取反符,用來取一個布林值相反的值,如 true 的相反值是 false

    var isOk = !true;
    console.log(isOk);  // false
    

賦值運算子

​ 概念:用來把資料賦值給變數的運算子。

賦值運算子 說明 案例
= 直接賦值 var usrName ='我是值';
+= , - = 加、減一個數後在賦值 varage= 10; age+=5; // 15
*=、/=、%= 乘、除、取模後在賦值 varage= 2; age*=5;// 10.
var age = 10;
age += 5;  // 相當於 age = age + 5;
age -= 5;  // 相當於 age = age - 5;
age *= 10; // 相當於 age = age * 10;

運算子優先順序

優先順序 運算子 順序
1 小括號 ( )
2 一元運算子 ++ -- !
3 算數運算子 先* / % 後+ -
4 關係運算符 > >= < <=
5 相等運算子 == != === !==
6 邏輯運算子 先&&後||
7 賦值運算子 =
8 逗號運算子 ,
  • 一元運算子裡面的邏輯非優先順序很高
  • 邏輯與比邏輯或優先順序高

流程控制

流程控制概念

​ 在一個程式執行的過程中,各條程式碼的執行順序對程式的結果是有直接影響的。很多時候我們要通過控制程式碼的執行順序來實現我們要完成的功能。

​ 簡單理解:流程控制就是來控制程式碼按照一定結構順序來執行

​ 流程控制主要有三種結構:順序結構、分支(選擇)結構、迴圈結構

順序流程控制

分支流程控制

  • 分支結構


​ JS 語言提供了兩種分支結構語句:if 語句、switch 語句

  • if 語句

    • 語法結構
    // 條件成立執行程式碼,否則什麼也不做
    if (條件表示式) {
        // 條件成立執行的程式碼語句
    }
    

    語句可以理解為一個行為,迴圈語句和分支語句就是典型的語句。一個程式由很多個語句組成,一般情況下,會分割成一個一個的語句。

  • if else語句(雙分支語句)

    • 語法結構

      // 條件成立  執行 if 裡面程式碼,否則執行else 裡面的程式碼
      if (條件表示式) {
          // [如果] 條件成立執行的程式碼
      } else {
          // [否則] 執行的程式碼
      }
      
      
  • if else if 語句(多分支語句)

    • 語法結構

      // 適合於檢查多重條件。
      if (條件表示式1) {
          語句1;
      } else if (條件表示式2)  {
          語句2;
      } else if (條件表示式3)  {
         語句3;
       ....
      } else {
          // 上述條件都不成立執行此處程式碼
      }
      
      

總結:

if語句

語法結構

if (/* 條件表示式 */) {
  // 執行語句
}

if (/* 條件表示式 */){
  // 成立執行語句
} else {
  // 否則執行語句
}

if (/* 條件1 */){
  // 成立執行語句
} else if (/* 條件2 */){
  // 成立執行語句
} else if (/* 條件3 */){
  // 成立執行語句
} else {
  // 最後預設執行語句
}

三元表示式

  • 語法結構

    表示式1 ? 表示式2 : 表示式3;
    
  • 執行思路

    • 如果表示式1為 true ,則返回表示式2的值,如果表示式1為 false,則返回表示式3的值
    • 簡單理解: 就類似於 if else (雙分支) 的簡寫

switch分支流程控制

  • 語法結構

    switch( 表示式 ){ 
       case value1:
           // 表示式 等於 value1 時要執行的程式碼
           break;
       case value2:
           // 表示式 等於 value2 時要執行的程式碼
           break;
       default:
           // 表示式 不等於任何一個 value 時要執行的程式碼
    }
    
    • 關鍵字 switch 後面括號內可以是表示式或值, 通常是一個變數

    • 關鍵字 case , 後跟一個選項的表示式或值,後面跟一個冒號

    • switch 表示式的值會與結構中的 case 的值做比較

    • 如果存在匹配全等(===) ,則與該 case 關聯的程式碼塊會被執行,並在遇到 break 時停止,整個 switch 語句程式碼執行結束

    • 如果所有的 case 的值都和表示式的值不匹配,則執行 default 裡的程式碼

      注意: 執行case 裡面的語句時,如果沒有break,則繼續執行下一個case裡面的語句。

  • switch 語句和 if else if 語句的區別

    • 一般情況下,它們兩個語句可以相互替換
    • switch...case 語句通常處理 case為比較確定值的情況, 而 if…else…語句更加靈活,常用於範圍判斷(大於、等於某個範圍)
    • switch 語句進行條件判斷後直接執行到程式的條件語句,效率更高。而if…else 語句有幾種條件,就得判斷多少次。
    • 當分支比較少時,if… else語句的執行效率比 switch語句高。
    • 當分支比較多時,switch語句的執行效率比較高,而且結構更清晰。

迴圈結構

在javascript中,迴圈語句有三種,while、do..while、for迴圈。

for迴圈

小結:
while和do...while一般用來解決無法確認次數的迴圈。
for迴圈一般在迴圈次數確定的時候比較方便
  • 語法結構

    for(初始化變數; 條件表示式; 操作表示式 ){
        //迴圈體
    }
    
    名稱 作用
    初始化變數 通常被用於初始化一個計數器,該表示式可以使用 var 關鍵字宣告新的變數,這個變數幫我們來記錄次數。
    條件表示式 用於確定每一次迴圈是否能被執行。如果結果是 true 就繼續迴圈,否則退出迴圈。
    操作表示式 用於確定每一次迴圈是否能被執行。如果結果是 true 就繼續迴圈,否則退出迴圈。

    執行過程:

    1. 初始化變數,初始化操作在整個 for 迴圈只會執行一次。
  • 執行條件表示式,如果為true,則執行迴圈體語句,否則退出迴圈,迴圈結束。

  1. 執行操作表示式,此時第一輪結束。
  2. 第二輪開始,直接去執行條件表示式(不再初始化變數),如果為 true ,則去執行迴圈體語句,否則退出迴圈。
  3. 繼續執行操作表示式,第二輪結束。
  4. 後續跟第二輪一致,直至條件表示式為假,結束整個 for 迴圈。

雙重for迴圈

  • 雙重 for 迴圈概述

    迴圈巢狀是指在一個迴圈語句中再定義一個迴圈語句的語法結構,例如在for迴圈語句中,可以再巢狀一個for 迴圈,這樣的 for 迴圈語句我們稱之為雙重for迴圈。

  • 雙重 for 迴圈語法

    for (外迴圈的初始; 外迴圈的條件; 外迴圈的操作表示式) {
        for (內迴圈的初始; 內迴圈的條件; 內迴圈的操作表示式) {  
           需執行的程式碼;
       }
    }
    
    • 內層迴圈可以看做外層迴圈的迴圈體語句
    • 內層迴圈執行的順序也要遵循 for 迴圈的執行順序
    • 外層迴圈執行一次,內層迴圈要執行全部次數
  • 列印五行五列星星

    var star = '';
    for (var j = 1; j <= 3; j++) {
        for (var i = 1; i <= 3; i++) {
          star += '☆'
        }
        // 每次滿 5個星星 就 加一次換行
        star += '\n'
    }
    console.log(star);
    

    核心邏輯:

    1.內層迴圈負責一行列印五個星星

    2.外層迴圈負責列印五行

  • for 迴圈小結

    • for 迴圈可以重複執行某些相同程式碼
    • for 迴圈可以重複執行些許不同的程式碼,因為我們有計數器
    • for 迴圈可以重複執行某些操作,比如算術運算子加法操作
    • 隨著需求增加,雙重for迴圈可以做更多、更好看的效果
    • 雙重 for 迴圈,外層迴圈一次,內層 for 迴圈全部執行
    • for 迴圈是迴圈條件和數字直接相關的迴圈
JS要理解掌握的程式碼題型:
列印1-100之間所有數
求1-100之間所有數的和
求1-100之間所有數的平均值
求1-100之間所有偶數的和
同時求1-100之間所有偶數和奇數的和
列印正方形

// console.log 輸出重複內容的問題
// console.log 預設輸出內容介紹後有換行
var start = '';
for (var i = 0; i < 10; i++) {
  for (var j = 0; j < 10; j++) {
    start += '* ';
  }
  start += '\n';
}
console.log(start);
列印直角三角形
var start = '';
for (var i = 0; i < 10; i++) {
  for (var j = i; j < 10; j++) {
    start += '* ';
  }
  start += '\n';
}
console.log(start);

列印9*9乘法表
var str = '';
for (var i = 1; i <= 9; i++) {
  for (var j = i; j <=9; j++) {
    str += i + ' * ' + j + ' = ' + i * j + '\t';
  }
  str += '\n';
}
console.log(str);

while迴圈

while語句的語法結構如下:

while (條件表示式) {
    // 迴圈體程式碼 
}

執行思路:

  • 1 先執行條件表示式,如果結果為 true,則執行迴圈體程式碼;如果為 false,則退出迴圈,執行後面程式碼
  • 2 執行迴圈體程式碼
  • 3 迴圈體程式碼執行完畢後,程式會繼續判斷執行條件表示式,如條件仍為true,則會繼續執行迴圈體,直到迴圈條件為 false 時,整個迴圈過程才會結束

注意:

  • 使用 while 迴圈時一定要注意,它必須要有退出條件,否則會成為死迴圈

1.4 do-while迴圈

do... while 語句的語法結構如下:

do {
    // 迴圈體程式碼 - 條件表示式為 true 時重複執行迴圈體程式碼
} while(條件表示式);

執行思路

  • 1 先執行一次迴圈體程式碼

  • 2 再執行條件表示式,如果結果為 true,則繼續執行迴圈體程式碼,如果為 false,則退出迴圈,繼續執行後面程式碼

    注意:先再執行迴圈體,再判斷,do…while迴圈語句至少會執行一次迴圈體程式碼

continue和break

break:立即跳出整個迴圈,即迴圈結束,開始執行迴圈後面的內容(直接跳到大括號)

continue:立即跳出當前迴圈,繼續下一次迴圈(跳到i++的地方)

陣列

1.1 陣列的概念

  • 陣列可以把一組相關的資料一起存放,並提供方便的訪問(獲取)方式。
  • 陣列是指一組資料的集合,其中的每個資料被稱作元素,在陣列中可以存放任意型別的元素。陣列是一種將一組資料儲存在單個變數名下的優雅方式。

1.2 建立陣列

JS 中建立陣列有兩種方式:

  • 利用 new 建立陣列

    var 陣列名 = new Array() ;
    var arr = new Array();   // 建立一個新的空陣列
    

    注意 Array () ,A 要大寫

  • 利用陣列字面量建立陣列

// 建立一個空陣列
var arr1 = []; 
// 建立一個包含3個數值的陣列,多個數組項以逗號隔開
var arr2 = [1, 3, 4]; 
// 建立一個包含2個字串的陣列
var arr3 = ['a', 'c']; 


// 可以通過陣列的length屬性獲取陣列的長度
console.log(arr3.length);
// 可以設定length屬性改變陣列中元素的個數
arr3.length = 0;

  - 陣列的字面量是方括號 [ ] 
  - 宣告陣列並賦值稱為陣列的初始化
  - 這種字面量方式也是我們以後最多使用的方式
  • 陣列元素的型別

    陣列中可以存放任意型別的資料,例如字串,數字,布林值等。

    var arrStus = ['小白',12,true,28.9];
    

1.3 獲取陣列中的元素

​ 索引 (下標) :用來訪問陣列元素的序號(陣列下標從 0 開始)。
陣列可以通過索引來訪問、設定、修改對應的陣列元素,可以通過“陣列名[索引]”的形式來獲取陣列中的元素。

// 定義陣列
var arrStus = [1,2,3];
// 獲取陣列中的第2個元素
alert(arrStus[1]);    

注意:如果訪問時陣列沒有和索引值對應的元素,則得到的值是undefined

遍歷陣列

遍歷:遍及所有,對陣列的每一個元素都訪問一次就叫遍歷。

陣列遍歷的基本語法:

for(var i = 0; i < arr.length; i++) {
	// 陣列遍歷的固定結構
}
  • 陣列的長度

    陣列的長度:預設情況下表示陣列中元素的個數

    使用“陣列名.length”可以訪問陣列元素的數量(陣列長度)。

    var arrStus = [1,2,3];
    alert(arrStus.length);  // 3
    

    注意

    • 此處陣列的長度是陣列元素的個數 ,不要和陣列的索引號混淆。
  • 當我們數組裡面的元素個數發生了變化,這個 length 屬性跟著一起變化

    • 陣列的length屬性可以被修改:
  • 如果設定的length屬性值大於陣列的元素個數,則會在陣列末尾出現空白元素;

    • 如果設定的length屬性值小於陣列的元素個數,則會把超過該值的陣列元素刪除

陣列中新增元素

陣列的賦值

// 格式:陣列名[下標/索引] = 值;
// 如果下標有對應的值,會把原來的值覆蓋,如果下標不存在,
//會給陣列新增一個元素。
var arr = ["red", "green", "blue"];
// 把red替換成了yellow
arr[0] = "yellow";
// 給陣列新增加了一個pink的值
arr[3] = "pink";
JS陣列要會的題:

/* 求陣列[2,6,1,77,52,25,7]中的最大值。
分析:氣泡排序法:是一種演算法,把一系列的資料按照一定的順序進行排列顯示
(從小到大或從大到小)。
回顧:把2個變數交換資料
// 利用第三個變數
var num1 = 10;
var num2 = 20;
var temp = num1;
num1 = num2;
num2 = temp;
console.log(num1, num2);
① 宣告一個儲存最大元素的變數 max。
② 預設最大值可以取陣列中的第一個元素。
③ 遍歷這個陣列,把裡面每個陣列元素和 max 相比較。
④ 如果這個陣列元素大於max 就把這個陣列元素存到 max 裡面,
否則繼續下一輪比較。
⑤ 最後輸出這個 max。*/
var arrNum = [2,6,1,77,52,25,7];
var maxNum = arrNum[0]; // 用來儲存最大元素,預設最大值是陣列中的第一個元素
// 從0 開始迴圈數組裡的每個元素
for(var i = 0;i< arrNum.length; i++){
// 如果數組裡當前迴圈的元素大於 maxNum,則儲存這個元素和下標
if(arrNum[i] > maxNum){
maxNum = arrNum[i]; // 儲存數值到變數 maxNum
}
}
/* 刪除指定陣列元素
要求:將陣列[2, 0, 6, 1, 77, 0, 52, 0, 25, 7]中的 0 去掉後,形成一個不包含 0 的新陣列。
分析
① 需要一個新陣列用於存放篩選之後的資料。
② 遍歷原來的陣列,把不是 0 的資料新增到新數組裡面( 此時要注意採用陣列名+索引的格式接收資料)。
③ 新數組裡面的個數,用 length 不斷累加。*/

var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7];
var newArr = []; // 空陣列的預設的長度為 0
// 定義一個變數 i 用來計算新陣列的索引號
for (var i = 0; i < arr.length; i++) {
// 找出大於 10 的數
if (arr[i] != 0) {
// 給新陣列
// 每次存入一個值,newArr長度都會 +1
newArr[newArr.length] = arr[i];
}
}
console.log(newArr);

什麼是函式

把一段相對獨立的具有特定功能的程式碼塊封裝起來,形成一個獨立實體,就是函式,起個名字(函式名),在後續開發中可以反覆呼叫

函式的作用就是封裝一段程式碼,將來可以重複使用

函式的定義

  • 函式宣告
function 函式名(){
  // 函式體
}

function 是宣告函式的關鍵字,必須小寫

  • 函式表示式
var fn = function() {
  // 函式體
}
  • 特點:

    函式宣告的時候,函式體並不會執行,只要當函式被呼叫的時候才會執行。
    函式一般都用來幹一件事情,需用使用動詞+名詞,表示做一件事情 tellStory sayHello

函式的呼叫

  • 呼叫函式的語法:
函式名();// 通過呼叫函式名來執行函式體程式碼
  • 特點:

    函式體只有在呼叫的時候才會執行,呼叫需要()進行呼叫。
    可以呼叫多次(重複使用)

注意:宣告函式本身並不會執行程式碼,只有呼叫函式時才會執行函式體程式碼。

程式碼示例:

// 宣告函式
function sayHi() {
  console.log("吃了沒?");
}
// 呼叫函式
sayHi();

// 求1-100之間所有數的和
function getSum() {
  var sum = 0;
  for (var  i = 0; i < 100; i++) {
    sum += i;
  }
  console.log(sum);
}
// 呼叫
getSum();

函式的封裝

  • 函式的封裝是把一個或者多個功能通過函式的方式封裝起來,對外只提供一個簡單的函式介面

  • 簡單理解:封裝類似於將電腦配件整合組裝到機箱中 ( 類似快遞打包)

    例子:封裝計算1-100累加和

    
    /* 
       計算1-100之間值的函式
    */
    // 宣告函式
    function getSum(){
      var sumNum = 0;// 準備一個變數,儲存數字和
      for (var i = 1; i <= 100; i++) {
        sumNum += i;// 把每個數值 都累加 到變數中
      }
      alert(sumNum);
    }
    // 呼叫函式
    getSum();
    

函式的引數

  • 為什麼要有引數
    ​ 引數的作用 : 在函式內部某些值不能固定,我們可以通過引數在呼叫函式時傳遞不同的值進去。
    函式引數的運用:

    // 帶引數的函式宣告
    function 函式名(形參1, 形參2 , 形參3...) { // 可以定義任意多的引數,用逗號分隔
      // 函式體
    }
    // 帶引數的函式呼叫
    函式名(實參1, 實參2, 實參3...); 
    
    1. 呼叫的時候實參值是傳遞給形參的
    2. 形參簡單理解為:不用宣告的變數
    3. 實參和形參的多個引數之間用逗號(,)分隔
function getSum() {
  var sum = 0;
  for (var i = 1; i <= 100; i++) {
    sum += i;
  }
  console.log();
}

// 雖然上面程式碼可以重複呼叫,但是隻能計算1-100之間的值
// 如果想要計算n-m之間所有數的和,應該怎麼辦呢?
  • 語法:
// 函式內部是一個封閉的環境,可以通過引數的方式,把外部的值傳遞給函式內部
// 帶引數的函式宣告
function 函式名(形參1, 形參2, 形參...){
  // 函式體
}

// 帶引數的函式呼叫
函式名(實參1, 實參2, 實參3);
  • 形參和實參

    1. 形式引數:在宣告一個函式的時候,為了函式的功能更加靈活,有些值是固定不了的,對於這些固定不了的值。我們可以給函式設定引數。這個引數沒有具體的值,僅僅起到一個佔位置的作用,我們通常稱之為形式引數,也叫形參。
      簡單理解(函式定義時設定接收呼叫時傳入)
    2. 實際引數:如果函式在宣告時,設定了形參,那麼在函式呼叫的時候就需要傳入對應的引數,我們把傳入的引數叫做實際引數,也叫實參。
      簡單理解(函式呼叫時傳入小括號內的真實資料)
引數 說明
形參 形式_上的引數函式定義的時候傳遞的引數當前並不知道是什麼
實參 實際上的引數函式呼叫的時候傳遞的引數實參是傳遞給形參的
var x = 5, y = 6;
fn(x,y); 
function fn(a, b) {
  console.log(a + b);
}
//x,y實參,有具體的值。函式執行的時候會把x,y複製一份給函式內部的a和b,函式內部的值是複製的新值,無法修改外部的x,y
注意:在JavaScript中,形參的預設值是undefined。

小結:

  • 函式可以帶引數也可以不帶引數
  • 宣告函式的時候,函式名括號裡面的是形參,形參的預設值為 undefined
  • 呼叫函式的時候,函式名括號裡面的是實參
  • 多個引數中間用逗號分隔

函式的返回值

當函式執行完的時候,並不是所有時候都要把結果列印。我們期望函式給我一些反饋(比如計算的結果返回進行後續的運算),這個時候可以讓函式返回一些東西。也就是返回值。函式通過return返回一個返回值

返回值語法:

//宣告一個帶返回值的函式
function 函式名(形參1, 形參2, 形參...){
  //函式體
  return 返回值;
}

//可以通過變數來接收這個返回值
var 變數 = 函式名(實參1, 實參2, 實參3);

函式的呼叫結果就是返回值,因此我們可以直接對函式呼叫結果進行操作。

返回值詳解:
- 在使用 return 語句時,函式會停止執行,並返回指定的值

  • 如果函式沒有 return ,返回的值是 undefined

  • 在使用 return 語句時,函式會停止執行,並返回指定的值
    如果函式使用 return語句,那麼跟再return後面的值,就成了函式的返回值
    如果函式使用 return語句,但是return後面沒有任何值,那麼函式的返回值也是:undefined
    函式使用return語句後,這個函式會在執行完 return 語句之後停止並立即退出,也就是說return後面的所有其他程式碼都不會再執行。

    推薦的做法是要麼讓函式始終都返回一個值,要麼永遠都不要返回值。

break ,continue ,return 的區別

  • break :結束當前的迴圈體(如 for、while)
  • continue :跳出本次迴圈,繼續執行下次迴圈(如 for、while)
  • return :不僅可以退出迴圈,還能夠返回 return 語句中的值,同時還可以結束當前的函式體內的程式碼

arguments的使用

​ 當不確定有多少個引數傳遞的時候,可以用 arguments 來獲取。JavaScript 中,arguments實際上它是當前函式的一個內建物件。所有函式都內建了一個 arguments 物件,arguments 物件中儲存了傳遞的所有實參。arguments展示形式是一個偽陣列,因此可以進行遍歷。偽陣列具有以下特點:

  • 具有 length 屬性

  • 按索引方式儲存資料

  • 不具有陣列的 push , pop 等方法

  注意:在函式內部使用該物件,用此物件獲取函式呼叫時傳的實參。
  函式內部可以呼叫另一個函式,在同一作用域程式碼中,函式名即代表封裝的操作,
  使用函式名加括號即可以將封裝的操作執行。

函式的兩種宣告方式

  • 自定義函式方式(命名函式)

    利用函式關鍵字 function 自定義函式方式

    // 宣告定義方式
    function fn() {...}
    // 呼叫  
    fn();  
    
    • 因為有名字,所以也被稱為命名函式
    • 呼叫函式的程式碼既可以放到宣告函式的前面,也可以放在宣告函式的後面
  • 函式表示式方式(匿名函式)

    利用函式表示式方式的寫法如下:

    // 這是函式表示式寫法,匿名函式後面跟分號結束
    var fn = function(){...};
    // 呼叫的方式,函式呼叫必須寫到函式體下面
    fn();
    

匿名函式如何使用:

將匿名函式賦值給一個變數,這樣就可以通過變數進行呼叫
匿名函式自呼叫

關於自執行函式(匿名函式自呼叫)的作用:防止全域性變數汙染。

  • 因為函式沒有名字,所以也被稱為匿名函式
  • 這個fn 裡面儲存的是一個函式
  • 函式表示式方式原理跟宣告變數方式是一致的
  • 函式呼叫的程式碼必須寫到函式體後面

自呼叫函式

匿名函式不能通過直接呼叫來執行,因此可以通過匿名函式的自呼叫的方式來執行

(function () {
  alert(123);
})();

函式是一種資料型別

function fn() {}
console.log(typeof fn);
  • 函式作為引數

因為函式也是一種型別,可以把函式作為兩一個函式的引數,在兩一個函式中呼叫

  • 函式做為返回值

因為函式是一種型別,所以可以把函式可以作為返回值從函式內部返回,這種用法在後面很常見。

function fn(b) {
  var a = 10;
  return function () {
    alert(a+b);
  }
}
fn(15)();

除錯

  • 過去除錯JavaScript的方式
    • alert()
    • console.log()
  • 斷點除錯

斷點除錯是指自己在程式的某一行設定一個斷點,除錯時,程式執行到這一行就會停住,然後你可以一步一步往下除錯,除錯過程中可以看各個變數當前的值,出錯的話,除錯到出錯的程式碼行即顯示錯誤,停下。

  • 除錯步驟
瀏覽器中按F12-->sources-->找到需要除錯的檔案-->在程式的某一行設定斷點
  • 除錯中的相關操作
Watch: 監視,通過watch可以監視變數的值的變化,非常的常用。
F10: 程式單步執行,讓程式一行一行的執行,
這個時候,觀察watch中變數的值的變化。
F8:跳到下一個斷點處,如果後面沒有斷點了,則程式執行結束。

tips: 監視變數,不要監視表示式,因為監視了表示式,那麼這個表示式也會執行。

程式碼規範

識別符號命名規範

  • 變數、函式的命名必須要有意義
  • 變數的名稱一般用名詞
  • 函式的名稱一般用動詞

操作符規範

// 操作符的左右兩側各保留一個空格
for (var i = 1; i <= 5; i++) {
   if (i == 3) {
       break; // 直接退出整個 for 迴圈,跳到整個for迴圈下面的語句
   }
   console.log('我正在吃第' + i + '個包子呢');
}

單行註釋規範

for (var i = 1; i <= 5; i++) {
   if (i == 3) {
       break; // 單行註釋前面注意有個空格
   }
   console.log('我正在吃第' + i + '個包子呢');
}

其他規範

關鍵詞、操作符之間後加空格
小結:
1.命名規範	
    2.變數規範   
    	var name = 'zs';	
    3.註釋規範
    	// 這裡是註釋
    4.空格規範
    5.換行規範
    	var arr = [1, 2, 3, 4];
    	if (a > b) {
          
    	}
    	for(var i = 0; i < 10; i++) {
          
    	}
    	function fn() {
          
    	}

作用域概述

通常來說,一段程式程式碼中所用到的名字並不總是有效和可用的,
而限定這個名字的可用性的程式碼範圍就是這個名字的作用域。
作用域的使用提高了程式邏輯的區域性性,增強了程式的可靠性,減少了名字衝突。

JavaScript(es6前)中的作用域有兩種:
  • 全域性作用域
  • 區域性作用域(函式作用域)

全域性作用域

作用於所有程式碼執行的環境(整個 script 標籤內部)或者一個獨立的 js 檔案。

區域性作用域

作用於函式內的程式碼環境,就是區域性作用域。 因為跟函式有關係,
所以也稱為函式作用域。

JS沒有塊級作用域

  • 塊作用域由 { } 包括。

  • 在其他程式語言中(如 java、c#等),在 if 語句、迴圈語句中建立的變數,僅僅只能在本 if 語句、本迴圈語句中使用,如下面的Java程式碼:

    java有塊級作用域:

    if(true){
      int num = 123;
      system.out.print(num);  // 123
    }
    system.out.print(num);    // 報錯
    

    以上java程式碼會報錯,是因為程式碼中 { } 即一塊作用域,其中宣告的變數 num,在 “{ }” 之外不能使用;

    而與之類似的JavaScript程式碼,則不會報錯:

    Js中沒有塊級作用域(在ES6之前)

    if(true){
      var num = 123;
      console.log(123); //123
    }
    console.log(123);   //123
    

    小結:
    任何一對花括號({和})中的語句集都屬於一個塊,在這之中定義的所有變數在程式碼塊外都是不可見的,我們稱之為塊級作用域。
    在es6之前沒有塊級作用域的的概念,只有函式作用域,現階段可以認為JavaScript沒有塊級作用域

詞法作用域

變數的作用域是在定義時決定而不是執行時決定,也就是說詞法作用域取決於原始碼,通過靜態分析就能確定,因此詞法作用域也叫做靜態作用域。

在 js 中詞法作用域規則:

  • 函式允許訪問函式外的資料.
  • 整個程式碼結構中只有函式可以限定作用域.
  • 作用域規則首先使用提升規則分析
  • 如果當前作用規則中有名字了, 就不考慮外面的名字

變數的作用域

在JavaScript中,根據作用域的不同,變數可以分為兩種:
  • 全域性變數
  • 區域性變數

全域性變數

在全域性作用域下宣告的變數叫做全域性變數(在函式外部定義的變數)。
  • 全域性變數在程式碼的任何位置都可以使用
  • 在全域性作用域下 var 宣告的變數 是全域性變數
  • 特殊情況下,在函式內不使用 var 宣告的變數也是全域性變數(不建議使用)

區域性變數

在區域性作用域下宣告的變數叫做區域性變數(在函式內部定義的變數)
  • 區域性變數只能在該函式內部使用
  • 在函式內部 var 宣告的變數是區域性變數
  • 函式的形參實際上就是區域性變數

全域性變數和區域性變數的區別

  • 全域性變數:在任何一個地方都可以使用,只有在瀏覽器關閉時才會被銷燬,因此比較佔記憶體
  • 區域性變數:只在函式內部使用,當其所在的程式碼塊被執行時,會被初始化;當代碼塊執行結束後,就會被銷燬,因此更節省記憶體空間

作用域鏈

只要是程式碼都一個作用域中,寫在函式內部的區域性作用域,未寫在任何函式內部即在全域性作用域中;如果函式中還有函式,那麼在這個作用域中就又可以誕生一個作用域;根據在[內部函式可以訪問外部函式變數]的這種機制,用鏈式查詢決定哪些資料能被內部函式訪問,就稱作作用域鏈

預解析的相關概念

JavaScript 程式碼是由瀏覽器中的 JavaScript 解析器來執行的。
JavaScript 解析器在執行 JavaScript 程式碼的時候分為兩步:預解析和程式碼執行。
  • 預解析:在當前作用域下, JS 程式碼執行之前,瀏覽器會預設把帶有 var 和 function 宣告的變數在記憶體中進行提前宣告或者定義。

  • 程式碼執行: 從上到下執行JS語句。

    預解析會把變數和函式的宣告在程式碼執行之前執行完成。

變數預解析

預解析也叫做變數、函式提升。
變數提升(變數預解析): 變數的宣告會被提升到當前作用域的最上面,變數的賦值不會提升。
console.log(num);  // 結果是多少?
var num = 10;      // ?
結果:undefined

注意:變數提升只提升宣告,不提升賦值
  • 函式提升

    JavaScript解析器首先會把當前作用域的函式宣告提前到整個作用域的最前面

fn();
function fn() {
    console.log('列印');
}
結果:控制檯列印字串 --- ”列印“ 

注意:函式宣告代表函式整體,所以函式提升後,函式名代表整個函式,
但是函式並沒有被呼叫!	

函式表示式宣告函式問題

函式表示式建立函式,會執行變數提升,此時接收函式的變數名無法正確的呼叫:
fn();
var  fn = function() {
    console.log('想不到吧');
}
結果:報錯提示 ”fn is not a function"

解釋:該段程式碼執行之前,會做變數宣告提升,fn在提升之後的值是undefined;
而fn呼叫是在fn被賦值為函式體之前,此時fn的值是undefined
,所以無法正確呼叫

物件的相關概念

  • 什麼是物件?

    在 JavaScript 中,物件是一組無序的相關屬性和方法的集合,所有的事物都是物件,例如字串、數值、陣列、函式等。
    (現實生活中:萬物皆物件,物件是一個具體的事物,一個具體的事物就會有行為和特徵。)
    物件是由屬性和方法組成的。

    • 屬性:事物的特徵,在物件中用屬性來表示(常用名詞)

    • 方法:事物的行為,在物件中用方法來表示(常用動詞)

  • 為什麼需要物件?

    儲存一個值時,可以使用變數,儲存多個值(一組值)時,可以使用陣列。

      如果要儲存一個人的完整資訊呢?
    

因此為了讓更好地儲存一組資料,物件應運而生:物件中為每項資料設定了屬性名稱,可以訪問資料更語義化,資料結構清晰,表意明顯,方便開發者使用。

JavaScript中的物件

JavaScript中的物件其實就是生活中物件的一個抽象
JavaScript的物件是無序屬性的集合。
屬性和方法
	如果一個變數屬於一個物件所有,那麼該變數就可以稱之為該物件的一個屬性,
	屬性一般是名詞,用來描述事物的特徵
	如果一個函式屬於一個物件所有,那麼該函式就可以稱之為該物件的一個方法,
	方法是動詞,描述事物的行為和功能
	其屬性可以包含基本值、物件或函式。物件就是一組沒有順序的值。
	我們可以把JavaScript中的物件想象成鍵值對,其中值可以是資料和函式。
物件的行為和特徵
	特徵---屬性
	行為---方法
  • 事物的特徵在物件中用屬性來表示。
  • 事物的行為在物件中用方法來表示。
    建立物件的三種方式
  • 利用字面量建立物件

    使用物件字面量建立物件
      就是花括號 { } 裡面包含了表達這個具體事物(物件)的屬性和方法;{ } 裡面採取鍵值對的形式表示 
    
    • 鍵:相當於屬性名

    • 值:相當於屬性值,可以是任意型別的值(數字型別、字串型別、布林型別,函式型別等)

      程式碼如下:

      var star = {
          name : 'pink',
          age : 18,
          sex : '男',
          sayHi : function(){
              alert('大家好啊~');
          }
      };
      

      上述程式碼中 star即是建立的物件。

  • 物件的使用

    • 物件的屬性

      • 物件中儲存具體資料的 "鍵值對"中的 "鍵"稱為物件的屬性,即物件中儲存具體資料的項
    • 物件的方法

      • 物件中儲存函式的 "鍵值對"中的 "鍵"稱為物件的方法,即物件中儲存函式的項
    • 訪問物件的屬性

      • 物件裡面的屬性呼叫 : 物件.屬性名 ,這個小點 . 就理解為“ 的 ”

      • 物件裡面屬性的另一種呼叫方式 : 物件[‘屬性名’],注意方括號裡面的屬性必須加引號

        示例程式碼如下:

        console.log(star.name)     // 呼叫名字屬性
        console.log(star['name'])  // 呼叫名字屬性
        
    • 呼叫物件的方法

      • 物件裡面的方法呼叫:物件.方法名() ,注意這個方法名字後面一定加括號

        示例程式碼如下:

        star.sayHi();              // 呼叫 sayHi 方法,注意,一定不要忘記帶後面的括號
        
    • 變數、屬性、函式、方法總結

      屬性是物件的一部分,而變數不是物件的一部分,
      變數是單獨儲存資料的容器
      
      • 變數:單獨宣告賦值,單獨存在

      • 屬性:物件裡面的變數稱為屬性,不需要宣告,用來描述該物件的特徵

        方法是物件的一部分,函式不是物件的一部分,函式是單獨封裝操作的容器

      • 函式:單獨存在的,通過“函式名()”的方式就可以呼叫

      • 方法:物件裡面的函式稱為方法,方法不需要宣告,使用“物件.方法名()”的方式就可以呼叫,方法用來描述該物件的行為和功能。

  • 利用 new Object 建立物件

    • 建立空物件

      var andy = new Obect();
      

      通過內建建構函式Object建立物件,此時andy變數已經儲存了創建出來的空物件

    • 給空物件新增屬性和方法

      • 通過物件操作屬性和方法的方式,來為物件增加屬性和方法

        示例程式碼如下:

      andy.name = 'pink';
      andy.age = 18;
      andy.sex = '男';
      andy.sayHi = function(){
          alert('大家好啊~');
      }
      

      注意:

      • Object() :第一個字母大寫
      • new Object() :需要 new 關鍵字
      • 使用的格式:物件.屬性 = 值;
  • 利用建構函式建立物件

    • 建構函式

      • 建構函式:是一種特殊的函式,主要用來初始化物件,即為物件成員變數賦初始值,它總與 new 運算子一起使用。我們可以把物件中一些公共的屬性和方法抽取出來,然後封裝到這個函式裡面。

      • 建構函式的封裝格式:

        function 建構函式名(形參1,形參2,形參3) {
             this.屬性名1 = 引數1;
             this.屬性名2 = 引數2;
             this.屬性名3 = 引數3;
             this.方法名 = 函式體;
        }
        
      • 建構函式的呼叫格式

        var obj = new 建構函式名(實參1,實參2,實參3)
        

        以上程式碼中,obj即接收到建構函式創建出來的物件。

      • 注意事項

        1. 建構函式約定首字母大寫
        2. 函式內的屬性和方法前面需要新增 this ,表示當前物件的屬性和方法。
        3. 建構函式中不需要 return 返回結果
        4. 當我們建立物件的時候,必須用 new 來呼叫建構函式
      • 其他

        建構函式,如 Stars(),抽象了物件的公共部分,封裝到了函式裡面,它泛指某一大類(class)
        建立物件,如 new Stars(),特指某一個,通過 new 關鍵字建立物件的過程我們也稱為物件例項化

new關鍵字

建構函式 ,是一種特殊的函式。主要用來在建立物件時初始化物件, 即為物件成員變數賦初始值,總與new運算子一起使用在建立物件的語句中。

  1. 建構函式用於建立一類物件,首字母要大寫。
  2. 建構函式要和new一起使用才有意義。

new在執行時會做四件事情

new會在記憶體中建立一個新的空物件
new 會讓this指向這個新的物件
執行建構函式  目的:給這個新物件加屬性和方法
new會返回這個新物件

this詳解

JavaScript中的this指向問題,有時候會讓人難以捉摸,隨著學習的深入,
我們可以逐漸瞭解
現在我們需要掌握函式內部的this幾個特點
	1. 函式在定義的時候this是不確定的,只有在呼叫的時候才可以確定
	2. 一般函式直接執行,內部this指向全域性window
	3. 函式作為一個物件的方法,被該物件所呼叫,那麼this指向的是該物件
	4. 建構函式中的this其實是一個隱式物件,類似一個初始化的模型,
	5. 所有方法和屬性都掛載到了這個隱式物件身上,後續通過new關鍵字來呼叫,
	從而實現例項化

物件的使用

  • new關鍵字的作用

    1. 在建構函式程式碼開始執行之前,建立一個空物件;
    2. 修改this的指向,把this指向創建出來的空物件;
    3. 執行函式的程式碼
    4. 在函式完成之後,返回this---即創建出來的物件

5.3 遍歷物件

for...in 語句用於對陣列或者物件的屬性進行迴圈操作。

其語法如下:
for (變數 in 物件名字) {
    // 在此執行程式碼
}
語法中的變數是自定義的,它需要符合命名規範,
通常我們會將這個變數寫為 k 或者 key。
for (var k in obj) {
    console.log(k);      // 這裡的 k 是屬性名
    console.log(obj[k]); // 這裡的 obj[k] 是屬性值
}

簡單型別和複雜型別的區別

基本型別又叫做值型別,複雜型別又叫做引用型別

值型別:簡單資料型別,基本資料型別,在儲存時,變數中儲存的是值本身,因此叫做值型別。

引用型別:複雜資料型別,在儲存是,變數中儲存的僅僅是地址(引用),因此叫做引用資料型別。

  • 堆和棧

    堆疊空間分配區別:
      1、棧(作業系統):由作業系統自動分配釋放 ,存放函式的引數值,
      區域性變數的值等。其操作方式類似於資料結構中的棧;
      2、堆(作業系統): 儲存複雜型別(物件),一般由程式設計師分配釋放,
       若程式設計師不釋放,由垃圾回收機制回收,分配方式倒是類似於連結串列。
    

    注意:JavaScript中沒有堆和棧的概念,此處我們用堆和棧的目的方便理解

為什麼會有堆記憶體和棧記憶體之分

首先 JavaScript 中的變數分為基本型別和引用型別。

基本型別就是儲存在棧記憶體中的簡單資料段,而引用型別指的是那些儲存在堆記憶體中的物件。

1 、基本型別

基本型別有 Undefined、Null、Boolean、Number 和String。這些型別在記憶體中分別佔有固定大小的空間,他們的值儲存在棧空間,我們通過按值來訪問的。

2 、引用型別

引用型別,值大小不固定,棧記憶體中存放地址指向堆記憶體中的物件。是按引用訪問的。如下圖所示:棧記憶體中存放的只是該物件的訪問地址, 在堆記憶體中為這個值分配空間 。 由於這種值的大小不固定,因此不能把它們儲存到棧記憶體中。但記憶體地址大小的固定的,因此可以將記憶體地址儲存在棧記憶體中。 這樣,當查詢引用型別的變數時, 先從棧中讀取記憶體地址, 然後再通過地址找到堆中的值。對於這種,我們把它叫做按引用訪問。

PS:當我們看到一個變數型別是已知的,就分配在棧裡面,比如INT,Double等。其他未知的型別,比如自定義的型別,因為系統不知道需要多大,所以程式自己申請,這樣就分配在堆裡面。

為什麼會有棧記憶體和堆記憶體之分:

通常與垃圾回收機制有關。為了使程式執行時佔用的記憶體最小。

當一個方法執行時,每個方法都會建立自己的記憶體棧,在這個方法內定義的變數將會逐個放入這塊棧記憶體裡,隨著方法的執行結束,這個方法的記憶體棧也將自然銷燬了。因此,所有在方法中定義的變數都是放在棧記憶體中的;

當我們在程式中建立一個物件時,這個物件將被儲存到執行時資料區中,以便反覆利用(因為物件的建立成本通常較大),這個執行時資料區就是堆記憶體。堆記憶體中的物件不會隨方法的結束而銷燬,即使方法結束後,這個物件還可能被另一個引用變數所引用(方法的引數傳遞時很常見),則這個物件依然不會被銷燬,只有當一個物件沒有任何引用變數引用它時,系統的垃圾回收機制才會在核實的時候回收它。