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等。其他未知的類型,比如自定義的類型,因為系統不知道需要多大,所以程序自己申請,這樣就分配在堆里面。

為什么會有棧內存和堆內存之分:

通常與垃圾回收機制有關。為了使程序運行時占用的內存最小。

當一個方法執行時,每個方法都會建立自己的內存棧,在這個方法內定義的變量將會逐個放入這塊棧內存里,隨着方法的執行結束,這個方法的內存棧也將自然銷毀了。因此,所有在方法中定義的變量都是放在棧內存中的;

當我們在程序中創建一個對象時,這個對象將被保存到運行時數據區中,以便反復利用(因為對象的創建成本通常較大),這個運行時數據區就是堆內存。堆內存中的對象不會隨方法的結束而銷毀,即使方法結束后,這個對象還可能被另一個引用變量所引用(方法的參數傳遞時很常見),則這個對象依然不會被銷毀,只有當一個對象沒有任何引用變量引用它時,系統的垃圾回收機制才會在核實的時候回收它。


免責聲明!

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



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