前端學習筆記八-JavaScript基礎(3)

一、數組

1.1 數組的概念

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

1.2 創建數組

  • 利用數組字面量創建數組(常用方式)

    //1. 使用數組字面量方式創建空的數組
    var  數組名 = [];
    //2. 使用數組字面量方式創建帶初始值的數組
    var  數組名 = ['小白','小黑','大黃','瑞奇'];
    
    • 數組的字面量是方括號 [ ]
    • 聲明數組并賦值稱為數組的初始化
    • 這種字面量方式也是我們以后最多使用的方式

1.3 獲取數組中的元素

索引 (下標) :用來訪問數組元素的序號(數組下標從 0 開始)。


// 定義數組
var arrStus = [1,2,3];
// 獲取數組中的第2個元素
console.log(arrStus[1]);    // 數字2

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

1.4 遍歷數組

  • 數組遍歷

    ? 把數組中的每個元素從頭到尾都訪問一次(類似學生的點名),可以通過 for 循環索引遍歷數組中的每一項

var arr = ['red','green', 'blue'];
for(var i = 0; i < arr.length; i++){
    console.log(arrStus[i]);
}

注意

  • 數組的長度是數組元素的個數 ,不要和數組的索引號混淆。
  • length 屬性動態檢測數組元素的個數
  • 數組的length屬性可以被修改:
    (1)如果設置的length屬性值大于數組的元素個數,則會在數組末尾出現空白元素[undefined];
    (2)如果設置的length屬性值小于數組的元素個數,則會把超過該值的數組元素刪除

1.5 數組中新增元素

?數組中可以通過以下方式在數組的末尾插入新元素:

  數組[ 數組.length ] = 新數據;

翻轉數組

        // 將數組 ['red', 'green', 'blue', 'pink', 'purple'] 的內容反過來存放
        // 1、聲明一個新數組 newArr
        // 2、把舊數組索引號第4個取過來(arr.length - 1),給新數組索引號第0個元素 (newArr.length)
        // 3、我們采取 遞減的方式  i--
        var arr = ['red', 'green', 'blue', 'pink', 'purple', 'hotpink'];
        var newArr = [];
        for (var i = arr.length - 1; i >= 0; i--) {
            newArr[newArr.length] = arr[i]
        }
        console.log(newArr);

1.6 冒泡排序

        // var arr = [5, 4, 3, 2, 1];
        var arr = [4, 1, 2, 3, 5];
        for (var i = 0; i <= arr.length - 1; i++) { // 外層循環管趟數 
            for (var j = 0; j <= arr.length - i - 1; j++) { // 里面的循環管 每一趟的交換次數
                // 內部交換2個變量的值 前一個和后面一個數組元素相比較
                if (arr[j] < arr[j + 1]) {
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }

            }
        }
        console.log(arr);

二、函數

2.1 函數的概念

在 JS 里面,可能會定義非常多的相同代碼或者功能相似的代碼,這些代碼可能需要大量重復使用。雖然 for循環語句也能實現一些簡單的重復操作,但是比較具有局限性,此時我們就可以使用 JS 中的函數。

函數:就是封裝了一段可被重復調用執行的代碼塊。通過此代碼塊可以實現大量代碼的重復使用

2.2 函數的使用

聲明函數
// 聲明函數
function 函數名() {
    //函數體代碼
}
  • function 是聲明函數的關鍵字,必須小寫
  • 由于函數一般是為了實現某個功能才定義的, 所以通常我們將函數名命名為動詞,比如 getSum
調用函數
// 調用函數
函數名();  // 通過調用函數名來執行函數體代碼
  • 調用的時候千萬不要忘記添加小括號
  • 口訣:函數不調用,自己不執行
函數的封裝
  • 函數的封裝是把一個或者多個功能通過函數的方式封裝起來,對外只提供一個簡單的函數接口

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

2.3 函數的參數

函數參數語法
  • 形參:函數定義時設置接收調用時傳入

  • 實參:函數調用時傳入小括號內的真實數據

參數的作用 : 在函數內部某些值不能固定,我們可以通過參數在調用函數時傳遞不同的值進去。

函數參數的運用:

// 帶參數的函數聲明
function 函數名(形參1, 形參2 , 形參3...) { // 可以定義任意多的參數,用逗號分隔
  // 函數體
}
// 帶參數的函數調用
函數名(實參1, 實參2, 實參3...); 
  1. 調用的時候實參值是傳遞給形參的
  2. 形參簡單理解為:不用聲明的變量(沒有傳實參值就是undefined,即默認值是undefined)
  3. 實參和形參的多個參數之間用逗號(,)分隔
函數形參和實參數量不匹配時

小結:

  • 聲明函數的時候,函數名括號里面的是形參,形參的默認值為 undefined
  • 調用函數的時候,函數名括號里面的是實參
  • 形參的個數可以和實參個數不匹配,但是結果不可預計,我們盡量要匹配

2.4 函數的返回值

return 語句

返回值:函數調用整體代表的數據;函數執行完成后可以通過return語句將指定數據返回。

// 聲明函數
function 函數名(){
    ...
    return  需要返回的值;
}
// 調用函數
函數名();    // 此時調用函數就可以得到函數體內return后面的值
  • 在使用 return 語句時,函數會終止執行,并返回指定的值
  • 如果函數沒有 return ,返回的值是 undefined
  • return只能返回一個值,多個值用,隔開的話,只會返回最后一個
break ,continue ,return 的區別
  • break :結束當前的循環體(如 for、while)
  • continue :跳出本次循環,繼續執行下次循環(如 for、while)
  • return :不僅可以退出循環,還能夠返回 return 語句中的值,同時還可以結束當前的函數體內的代碼

2.5 arguments的使用

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

  • 只有函數有arguments對象
  • 具有 length 屬性
  • 按索引方式儲存數據
  • 不具有數組的 push , pop 等方法
// arguments 的使用  只有函數才有 arguments對象  而且是每個函數都內置好了這個arguments
        function fn() {
            // console.log(arguments); // 里面存儲了所有傳遞過來的實參  arguments = [1,2,3]
            // console.log(arguments.length);
            // console.log(arguments[2]);
            // 我們可以按照數組的方式遍歷arguments
            for (var i = 0; i < arguments.length; i++) {
                console.log(arguments[i]);

            }
        }
        fn(1, 2, 3);
        fn(1, 2, 3, 4, 5);

注意:在函數內部使用該對象,用此對象獲取函數調用時傳的實參。

2.6 函數的兩種聲明方式

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

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

    // 聲明定義方式
    function fn(aru) {...}
    // 調用  
    fn();  
    
    • 因為有名字,所以也被稱為命名函數
    • 調用函數的代碼既可以放到聲明函數的前面,也可以放在聲明函數的后面
  • 函數表達式方式(匿名函數

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

    // 這是函數表達式寫法,匿名函數后面跟分號結束
    var fn = function(aru){...};
    // 調用的方式,函數調用必須寫到函數體下面
    fn();
    
    • 因為函數沒有名字,所以也被稱為匿名函數
    • 這個fn是變量名,里面存儲的是一個函數
    • 函數表達式方式原理跟聲明變量方式是一致的
    • 函數調用的代碼必須寫到函數體后面

三、作用域

3.1 作用域概述

通常來說,一段程序代碼中所用到的名字并不總是有效和可用的,而限定這個名字的可用性的代碼范圍就是這個名字的作用域。作用域的使用提高了程序邏輯的局部性,增強了程序的可靠性,減少了名字沖突。

JavaScript(es6前)中的作用域有兩種:

  • 全局作用域
  • 局部作用域(函數作用域)

3.2 全局作用域

作用于所有代碼執行的環境(整個script標簽內部)或獨立的js文件。

3.3 局部作用域

作用于函數內的代碼環境,就是局部作用域。
因為跟函數有關系,所以也稱為函數作用域。

3.4 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(num); //123
}
console.log(num);   //123

四、變量的作用域

在JavaScript中,根據作用域的不同,變量可以分為兩種:

  • 全局變量
  • 局部變量

4.1 全局變量

在全局作用域下聲明的變量叫做全局變量(在函數外部定義的變量)。

  • 全局變量在代碼的任何位置都可以使用
  • 在全局作用域下 var 聲明的變量 是全局變量
  • 特殊情況下,在函數內不使用 var 聲明的變量也是全局變量(不建議使用)

4.2 局部變量

在局部作用域下聲明的變量叫做局部變量(在函數內部定義的變量)

  • 局部變量只能在該函數內部使用
  • 在函數內部 var 聲明的變量是局部變量
  • 函數的形參實際上就是局部變量

4.3 全局變量和局部變量的區別

  • 全局變量:在任何一個地方都可以使用,只有在瀏覽器關閉時才會被銷毀,因此比較占內存
  • 局部變量:只在函數內部使用,當其所在的代碼塊被執行時,會被初始化;當代碼塊運行結束后,就會被銷毀,因此更節省內存空間

五、作用域鏈

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

案例分析1:
function f1() {
    var num = 123;
    function f2() {
        console.log( num );
    }
    f2();
}
var num = 456;
f1();
作用域鏈:采取就近原則的方式來查找變量最終的值
var a = 1;
function fn1() {
    var a = 2;
    var b = '22';
    fn2();
    function fn2() {
        var a = 3;
        fn3();
        function fn3() {
            var a = 4;
            console.log(a); //a的值 ?
            console.log(b); //b的值 ?
        }
    }
}
fn1();

六、預解析

6.1 預解析的相關概念

JavaScript 代碼是由瀏覽器中的 JavaScript 解析器來執行的。
JavaScript 解析器在運行 JavaScript 代碼的時候分為兩步:

預解析代碼執行。

  • 預解析:在當前作用域下, JS 代碼執行之前,瀏覽器會默認把帶有 var 和 function 聲明的變量在內存中進行提前聲明或者定義,預解析也叫做變量、函數提升。

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

注意:預解析會把變量和函數的聲明在代碼執行之前執行完成。

6.2 變量預解析

? 變量的聲明會被提升到當前作用域的最上面,變量的賦值不會提升。

console.log(num);  // 結果是多少?
var num = 10;      // ?

結果:undefined
注意:變量提升只提升聲明,不提升賦值

6.3 函數預解析

? 函數的聲明會被提升到當前作用域的最上面,但是不會調用函數。

fn();
function fn() {
    console.log('打印');
}

結果:控制臺打印字符串 --- ”打印“

注意:函數聲明代表函數整體,所以函數提升后,函數名代表整個函數,但是函數并沒有被調用!

6.4 函數表達式聲明函數問題

函數表達式創建函數,會執行變量提升

fn();
var  fn = function() {
    console.log('想不到吧');
}

結果:報錯提示 ”fn is not a function"

解釋:該段代碼執行之前,會做變量聲明提升,fn在提升之后的值是undefined;而fn調用是在fn被賦值為函數體之前,此時fn的值是undefined,所以無法正確調用

七、對象

7.1 對象的相關概念

  • 什么是對象?

    ?在 JavaScript 中,對象是一組無序的相關屬性和方法的集合,所有的事物都是對象,例如字符串、數值、數組、函數等。
    對象是由屬性和方法組成的。

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

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

為了讓更好地存儲一組數據,對象應運而生:對象中為每項數據設置了屬性名稱,可以訪問數據更語義化,數據結構清晰,表意明顯,方便開發者使用。

JS中的對象表達結構更清晰,更強大。

7.2 創建對象的三種方式

利用字面量創建對象

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 Object();
    

    通過內置構造函數Object創建對象,此時andy變量已經保存了創建出來的空對象

  • 給空對象添加屬性和方法:通過對象操作屬性和方法的方式,來為對象增加屬性和方法

    示例代碼如下:

    andy.name = 'pink';
    andy.age = 18;
    andy.sex = '男';
    andy.sayHi = function(){
        alert('大家好啊~');
    }
    
利用構造函數創建對象
  • 構造函數:是一種特殊的函數,主要用來初始化對象,即為對象成員變量賦初始值,它總與 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關鍵字的作用

    1. 在構造函數代碼開始執行之前,在內存中創建一個空對象;
    2. 修改this的指向,把this指向創建出來的空對象;
    3. 執行函數的代碼
    4. 在函數完成之后,返回this---即創建出來的對象

7.3 遍歷對象

?for...in 語句用于對數組或者對象的屬性進行循環操作。

其語法如下:

for (變量 in 對象名字) {
    // 在此執行代碼
}

語法中的變量是自定義的,它需要符合命名規范,通常我們會將這個變量寫為 k 或者 key。

for (var k in obj) {
    console.log(k);      // 這里的 k 是屬性名
    console.log(obj[k]); // 這里的 obj[k] 是屬性值
}

八、內置對象

8.1 內置對象

? JavaScript 中的對象分為3種:自定義對象 、內置對象、 瀏覽器對象
? 前面兩種對象是JS 基礎 內容,屬于 ECMAScript; 第三個瀏覽器對象屬于 JS 獨有的, JS API 講解內置對象就是指 JS 語言自帶的一些對象,這些對象供開發者使用,并提供了一些常用的或是最基本而必要的功能(屬性和方法),內置對象最大的優點就是幫助我們快速開發

? JavaScript 提供了多個內置對象:Math、 Date 、Array、String等

8.2 查文檔

? 查找文檔:學習一個內置對象的使用,只要學會其常用成員的使用即可,我們可以通過查文檔學習,可以通過MDN/W3C來查詢。
? Mozilla 開發者網絡(MDN)提供了有關開放網絡技術(Open Web)的信息,包括 HTML、CSS 和萬維網及 HTML5 應用的 API。
? MDN:https://developer.mozilla.org/zh-CN/

8.3 Math對象

? Math對象不是構造函數,它具有數學常數和函數的屬性和方法。跟數學相關的運算(求絕對值,取整、最大值等)可以使用 Math 中的成員。

屬性、方法名 功能
Math.PI 圓周率
Math.floor() 向下取整
Math.ceil() 向上取整
Math.round() 四舍五入版 就近取整 注意 -3.5 結果是 -3
Math.abs() 絕對值
Math.max()/Math.min() 求最大和最小值
Math.random() 獲取范圍在[0,1)內的隨機值(隨機小數)

? 注意:Math.round(遇到.5,往大取,因此負值-x.5結果是-x)

? 獲取指定范圍內的隨機整數

function getRandomIntInclusive(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 
}
 // 要求用戶猜 1~50之間的一個數字 但是只有 10次猜的機會
        var random = getRandom(1, 50),
            i = 0;
        while (i <= 10) { // 死循環
            var num = prompt('你來猜? 輸入1~50之間的一個數字');
            i++;
            if (num > random) {
                alert('你猜大了');
            } else if (num < random) {
                alert('你猜小了');
            } else {
                alert('你好帥哦,猜對了');
                break; // 退出整個循環結束程序
            }

        }   

8.4 日期對象

Date 對象和 Math 對象不一樣,Date是一個構造函數,所以使用時需要實例化后才能使用其中具體方法和屬性。Date 實例用來處理日期和時間

  • 使用Date實例化日期對象

    • 獲取當前時間必須實例化:
    var now = new Date();
    
    • 獲取指定時間的日期對象
    var future = new Date('2019-5-1 8:8:8');
    var future1 = new Date('2019/5/1');
    

    注意:如果創建實例時并未傳入參數,則得到的日期對象是當前時間對應的日期對象

  • 使用Date實例的方法和屬性

  • 通過Date實例獲取總毫米數

    • 總毫秒數的含義

      ? 基于1970年1月1日(世界標準時間)起的毫秒數

    • 獲取總毫秒數

      // 實例化Date對象
      var now = new Date();
      // 1. 用于獲取對象的原始值
      console.log(date.valueOf()) 
      console.log(date.getTime()) 
      // 2. 簡單寫可以這么做
      var now = + new Date();         
      // 3. HTML5中提供的方法,有兼容性問題
      var now = Date.now();
      

8.5 數組對象

創建數組的兩種方式
  • 字面量方式

    • 示例代碼如下:

      var arr = [1,"test",true];
      
  • new Array()

    • 示例代碼如下:

      var arr = new Array();
      var arr1 =new Array(2) //等價于 arr1=[empty*2] 表示有個2個空數據組,length為2
      var arr2 =new Array(2,5) //等價于 arr2=[2,5]
      

      ? 注意:上面代碼中arr創建出的是一個空數組,如果需要使用構造函數Array創建非空數組,可以在創建數組時傳入參數

      ? 參數傳遞規則如下:

      • 如果只傳入一個參數,則參數規定了數組的長度

      • 如果傳入了多個參數,則參數稱為數組的元素

檢測是否為數組

  • instanceof 運算符

    • instanceof 可以判斷一個對象是否是某個構造函數的實例

      var arr = [1, 23];
      var obj = {};
      console.log(arr instanceof Array); // true
      console.log(obj instanceof Array); // false
      
  • Array.isArray()

    • Array.isArray()用于判斷一個對象是否為數組,isArray() 是 HTML5 中提供的方法

      var arr = [1, 23];
      var obj = {};
      console.log(Array.isArray(arr));   // true
      console.log(Array.isArray(obj));   // false
      
添加刪除數組元素的方法
  • 數組中有進行增加、刪除元素的方法,部分方法如下表

注意:push、unshift為增加元素方法;pop、shift為刪除元素的方法

var arr = [1,2,3];
arr.push(4,'pink');
console.log(arr.push(5)); //6 返回數組的長度

arr.unshift(6,'red')

console.log(arr.pop()); //pink 返回的是元素的最后一個元素

arr.shift();
console.log(arr)
數組排序
  • 數組中有對數組本身排序的方法,部分方法如下表

注意:sort方法需要傳入參數來設置升序、降序排序

  • 如果傳入“function(a,b){ return a-b;}”,則為升序
  • 如果傳入“function(a,b){ return b-a;}”,則為降序
var arr = [1,3,2,5];
var arr1 =[1,88,56,32,8]
arr.reverse();//翻轉數組
arr1.sort(function(a,b){ return a-b;})//升序冒泡排序
數組索引方法
  • 數組中有獲取數組指定元素索引值的方法,部分方法如下表
//查找兩組數組不同值案例【數組去重】
var Arr = ["寇曉麗", "馬曉晗", "王思聰", "張綠", "李德", "鄭萍", "張凱", "張嘉成", "葛云俠", "楊磊", "劉東", "王可可", "陳澤文", "李嘉琪", "段佳琦", "黃燕", "邱淑鴻", "宋翔宇", "王波", "樊琳", "王兆國", "許成", "李興"];
var currentArr = ["寇曉麗", "馬曉晗", "張綠", "李德", "鄭萍", "張凱", "張嘉成", "葛云俠", "楊磊", "劉東", "陳澤文", "李嘉琪", "段佳琦", "黃燕", "邱淑鴻", "宋翔宇", "王波", "樊琳", "王兆國", "許成", "李興"];
var unfinish = new Array();
for (var i = 0; i < Arr.length; i++) {
    if (currentArr.indexOf(Arr[i]) === -1) {
        unfinish.push(Arr[i])
    }
}
console.log(unfinish)
數組轉換為字符串
  • 數組中有把數組轉化為字符串的方法,部分方法如下表

注意:join方法如果不傳入參數,則按照 “ , ”拼接元素

var arr = [1,2,3]
console.log(arr.toString()) // 1,2,3
console.log(arr.join('')) // 1,2,3
console.log(arr.join('|')) // 1|2|3
其他方法
  • 數組中還有其他操作方法,同學們可以在課下自行查閱學習

8.6 字符串對象

基本包裝類型

為了方便操作基本數據類型,JavaScript 還提供了三個特殊的引用類型:String、Number和 Boolean。

基本包裝類型就是把簡單數據類型包裝成為復雜數據類型,這樣基本數據類型就有了屬性和方法。

// 下面代碼有什么問題?
var str = 'andy';
console.log(str.length);

按道理基本數據類型是沒有屬性和方法的,而對象才有屬性和方法,但上面代碼卻可以執行,這是因為 js 會把基本數據類型包裝為復雜數據類型,其執行過程如下 :

// 1. 生成臨時變量,把簡單類型包裝為復雜數據類型
var temp = new String('andy');
// 2. 賦值給我們聲明的字符變量
str = temp;
// 3. 銷毀臨時變量
temp = null;
字符串的不可變

指的是里面的值不可變,雖然看上去可以改變內容,但其實是地址變了,內存中新開辟了一個內存空間。

當重新給字符串變量賦值的時候,變量之前保存的字符串不會被修改,依然在內存中。重新給字符串變量賦值,會重新在內存中開辟空間,這個特點就是字符串的不可變。
?由于字符串的不可變,在大量拼接字符串的時候會有效率問題,因為非常占內存空間

根據字符返回位置

字符串通過基本包裝類型可以調用部分方法來操作字符串,以下是返回指定字符的位置的方法:

案例:查找字符串"abcoefoxyozzopp"中所有o出現的位置以及次數

  1. 先查找第一個o出現的位置
  2. 然后 只要indexOf 返回的結果不是 -1 就繼續往后查找
  3. 因為indexOf 只能查找到第一個,所以后面的查找,利用第二個參數,當前索引加1,從而繼續查找
    var str = 'abcoefoxyozzopp';
    var index = str.indexOf('o');
    var pos = [index];
    while (index !== -1) {
        console.log(index)
        index = str.indexOf('o', index + 1);
        pos.push(index)
    }
    pos.pop()
    console.log(pos)
    var time = pos.length
    console.log(time)
根據位置返回字符

字符串通過基本包裝類型可以調用部分方法來操作字符串,以下是根據位置返回指定位置上的字符:

在上述方法中,charCodeAt方法返回的是指定位置上字符對應的ASCII碼,ASCII碼對照表如下:

案例:判斷一個字符串 'abcoefoxyozzopp' 中出現次數最多的字符,并統計其次數

  1. 核心算法:利用 charAt() 遍歷這個字符串
  2. 把每個字符都存儲給對象, 如果對象沒有該屬性,就為1,如果存在了就 +1
  3. 遍歷對象,得到最大值和該字符

注意:在遍歷的過程中,把字符串中的每個字符作為對象的屬性存儲在對象總,對應的屬性值是該字符出現的次數

var str = 'abcoefoxyozzopp';
var obj = new Object();
for(var i=0; i < str.length; i++) {
    var charts = str.charAt(i);
    if(obj[charts]){
        obj[charts]++;
    }else{
        obj[charts] = 1;
    }
}
var max=0,chartKey='';
for(key in obj){
    if(obj[key] > max){
        max = obj[key]
        chartkey = key
    }
}
console.log(chartkey,max)
字符串操作方法

字符串通過基本包裝類型可以調用部分方法來操作字符串,以下是部分操作方法:

replace()方法

replace() 方法用于在字符串中用一些字符替換另一些字符,其使用格式如下:

字符串.replace(被替換的字符串, 要替換為的字符串);
split()方法

split()方法用于切分字符串,它可以將字符串切分為數組。在切分完畢之后,返回的是一個新數組。

其使用格式如下:

字符串.split("分割字符")

九、簡單數據類型和復雜數據類型

9.1 簡單數據類型

簡單類型基本數據類型、值類型):在存儲時變量中存儲的是值本身,包括string ,number,boolean,undefined,null

9.2 復雜數據類型

復雜數據類型(引用類型):在存儲時變量中存儲的僅僅是地址(引用),通過 new 關鍵字創建的對象(系統對象、自定義對象),如 Object、Array、Date等;

9.3 堆棧

  • 堆??臻g分配區別:

1、棧(操作系統):由操作系統自動分配釋放存放函數的參數值、局部變量的值等。其操作方式類 似于數據結構中的棧;

簡單數據類型存放到棧里面

2、堆(操作系統):存儲復雜類型(對象),一般由程序員分配釋放,若程序員不釋放,由垃圾回收機制回收。

  • 簡單數據類型的存儲方式

    ? 值類型變量的數據直接存放在變量(??臻g)中,直接開辟一個空間存放值

  • 復雜數據類型的存儲方式

    ? 引用類型變量(??臻g)里存放的是地址(十六進制表示,指向堆里的數據),真正的對象實例存放在堆空間中

9.4 簡單類型傳參

?函數的形參也可以看做是一個變量,當我們把一個值類型變量作為參數傳給函數的形參時,其實是把變量在??臻g里的值復制了一份給形參,那么在方法內部對形參做任何修改,都不會影響到的外部變量。

function fn(a) {
    a++;//形參在內存也開辟了一個新地址a,存上(復制了)x存的數據
    console.log(a); // 11
}
var x = 10;
fn(x);
console.log(x);//10

9.5 復雜數據類型傳參

函數的形參也可以看做是一個變量,當我們把引用類型變量傳給形參時,其實是把變量在??臻g里保存的堆地址復制給了形參,形參和實參其實保存的是同一個堆地址,所以操作的是同一個對象。

function Person(name) {
    this.name = name;
}
function f1(x) { // x = p //在棧中開辟一個地址x,存的是(復制得到)p中的地址
    console.log(x.name); // 2. 這個輸出什么 ?    劉德華
    x.name = "張學友";
    console.log(x.name); // 3. 這個輸出什么 ?    張學友
}
var p = new Person("劉德華");
console.log(p.name);    // 1. 這個輸出什么 ?   劉德華
f1(p);
console.log(p.name);    // 4. 這個輸出什么 ?  張學友
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375

推薦閱讀更多精彩內容