前端基礎(chǔ) 03狭姨、JavaScript 入門

一宰啦、什么是 JavaScript

1. 概述
  • JavaScript 是世界上最流行的腳本語言;
  • JavaScript 是運行在瀏覽器中的饼拍,解釋型的編程語言赡模;
  • JavaScript Java;
  • 只用了 10 天設(shè)計完成师抄;
  • 后端人員漓柑,必須要精通 JavaScript
  • 在 Web 世界里叨吮,只有 JavaScript 能跨平臺辆布、跨瀏覽器,驅(qū)動網(wǎng)頁茶鉴,與用戶交互锋玲;
2. JavaScript 歷史
  • 1995年,網(wǎng)景公司憑借 Navigator 瀏覽器涵叮,成為 Web 時代最著名的第一代互聯(lián)網(wǎng)公司惭蹂。
  • 該公司希望能在靜態(tài) HTML 頁面上,添加一些動態(tài)效果割粮,于是找 Brendan Eich 在兩周之內(nèi)(10天)設(shè)計出了 JavaScript 語言盾碗。
  • 為什么起名叫 JavaScript ?原因是舀瓢,當(dāng)時 Java 語言非常紅火廷雅,所以網(wǎng)景公司希望借 Java 的名氣來推廣,但事 實上 JavaScript 除了語法上有點像Java京髓,其他部分基本上沒啥關(guān)系航缀。
3. ECMAScript
  • ECMAScirpt:可以理解為是 JavaScript 的一個標(biāo)準(zhǔn);
  • 版本已經(jīng)到 ES6 及更高版本朵锣,但是大部分瀏覽器谬盐,還只停留在支持 ES5 代碼上;
  • 開發(fā)環(huán)境與線上環(huán)境诚些,版本不一致飞傀。

二、快速入門

1. 引入 JavaScript
  1. 內(nèi)部標(biāo)簽:JS 代碼可以直接嵌在網(wǎng)頁的任何地方诬烹,通常放到 head 中砸烦;

    <script>
        // JS注釋
     alert("Hello,World!")
    </script>
    
  2. 外部引入:把 JS 代碼放到一個單獨的 .js 文件,然后引入绞吁;

    <script src="js/hello.js"></script>
    
  3. 測試代碼:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>第一個JavaScript</title>
        <!--1. 內(nèi)部引用-->
        <!--    <script>-->
        <!--        alert("Hello,World!")-->
        <!--    </script>-->
        <!--script標(biāo)簽內(nèi)寫JS代碼幢痘,script標(biāo)簽必須成對出現(xiàn)-->
        <!--2. 外部引用-->
        <script src="js/hello.js"></script>
        <!--不用顯式定義type,默認(rèn)就是JavaScript-->
        <script type="text/javascript"></script>
    </head>
    <body>
    
    <!--JS代碼也可以放這里-->
    </body>
    </html>
    
  4. 調(diào)試

    • 安裝 Google Chrome 瀏覽器家破;
    • 打開開發(fā)者工具:快捷鍵 F12颜说、Ctrl + Shift + I购岗,或鼠標(biāo)右鍵 檢查
    • 先點擊控制臺(Console),在這里可以直接輸入 JS 代碼门粪,按回車后執(zhí)行喊积;

    • 要查看一個變量的內(nèi)容,在 Console 中輸入 console.log(a);玄妈,回車后顯示的值乾吻,就是變量的內(nèi)容。

    • 關(guān)閉 Console 請點擊右上角的 × 按鈕拟蜻。

2. 基本語法入門
  • JavaScript 的語法和 Java 語言類似绎签,每個語句以 ;結(jié)束,語句塊用 {...}酝锅;

  • JavaScript 不強(qiáng)制要求在每個語句的結(jié)尾加 ;诡必,瀏覽器中負(fù)責(zé)執(zhí)行JavaScript 代碼的引擎,會自動在每個語句的結(jié)尾補(bǔ)上 ;屈张。

  • 完整的賦值語句:

    // 常規(guī)
    var x = 1;
    // 仍然可以視為一個完整的語句
    'Hello, world';
    // 不建議一行寫多個語句
    var x = 1; var y = 2; 
    
  • 實例:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>基本語法</title>
        <script>
            // JavaScript嚴(yán)格區(qū)分大小寫
            // 1. 定義變量 變量類型 變量名 = 變量值;
            var score = 95;
            // 2. 條件控制(可嵌套)
            if (score >= 0 && score <= 100) {
                if (score > 70 && score < 80) {
                    alert("70-80");
                } else if (score < 70) {
                    alert("0-70");
                } else {
                    // 彈窗
                    alert("other");
                }
            }
            /*
              在瀏覽器的控制臺中打印變量:
              相當(dāng)于Java System.out.println();
              */
            console.log(score);
        </script>
    </head>
    <body>
    </body>
    </html>
    
3. 數(shù)據(jù)類型簡介

數(shù)值擒权、文本、圖形阁谆、音頻碳抄、視頻、網(wǎng)頁等各種各樣的數(shù)據(jù)场绿,在 JavaScript 中定義了以下幾種數(shù)據(jù)類型:

  • 變量

    • 大小寫英文剖效、數(shù)字、 $ 和 _ 的組合焰盗,且 不能用數(shù)字開頭璧尸;
    • 變量名也不能是 JavaScript 的關(guān)鍵字,如 if 熬拒、 while 等爷光;
    • 申明一個變量用 var 語句,比如:
      var a; // 申明變量a澎粟,值為undefined
      var $b = 1; // 申明變量$b蛀序,同時給$b賦值涡匀,此時$b的值為1
      var s_007 = '007'; // s_007是一個字符串
      var Answer = true; // Answer是一個布爾值true
      var t = null; // t的值是null
      
    • 變量名也可以用中文蒋譬,一般不這樣用。
  • Number:JavaScript 不區(qū)分整數(shù)和浮點數(shù)刻撒,統(tǒng)一用 Number 表示啸盏,以下都是合法的 Number 類型:

    123; // 整數(shù)
    0.456; // 浮點數(shù)
    1.2345e3; // 科學(xué)計數(shù)法 1.2345x1000
    -99; // 負(fù)數(shù)
    NaN; // NaN表示Not a Number重贺,當(dāng)無法計算結(jié)果時用NaN表示
    Infinity; // Infinity表示無限大,當(dāng)數(shù)值超過了JavaScript的Number所能表示的最大值時,就表示為Infinity
    
  • 字符串:‘a(chǎn)bc’ “abc”

  • 布爾值:true false

  • 邏輯運算符

    &&    // 兩個都為真气笙,結(jié)果為真
    ||    // 一個為真次企,結(jié)果為真
    ! // 真即假,假即真(取反)
    
  • 比較運算符:用 === 進(jìn)行比較健民;

    = // 賦值預(yù)算法
    ==    // 等于(類型不一致抒巢,值一樣贫贝,也會判斷為true秉犹,即判斷1=='1')
    ===   // 絕對等于(類型一樣,值一樣稚晚,結(jié)果為true崇堵,JS 的缺陷)
    

    須知:

    • NaN:與所有的數(shù)值都不相等,包括自己客燕;
    • 只能通過 isNaN() 來判斷這個數(shù)是不是 NaN鸳劳。
  • 浮點數(shù):

    console.log(1/3)===(1-2/3); // 結(jié)果為false
    
    // 盡量避免使用浮點數(shù)進(jìn)行運算,存在精度問題
    Math.abs(1/3-(1-2/3))<0.00000001; // 結(jié)果為true
    
  • null 和 undefined

    • null:空也搓;
    • undefined:不存在赏廓。
  • 數(shù)組:Java 的數(shù)組必須是相同類型的對象,JS 中不需要這樣傍妒。

    //保證代碼的可讀性幔摸,盡量使用[]
    var arr = [1,2,3,'hello',null,true];
    //取數(shù)組下標(biāo):如果越界了,就會報undefined
    
  • 對象:對象是一組由 鍵-值 組成的無序集合

    • 對象是大括號颤练,數(shù)組是中括號既忆;
    • 每一個屬性之間使用逗號隔開,最后一個不需要加逗號嗦玖。
    // java對象 Person person = new Pperson();
    var person = {
    name: 'Bob',
    age: 20,
    tags: ['js', 'web', 'mobile'],
    city: 'Beijing',
    hasCar: true,
    zipcode: null
    };
    
    • 獲取對象的屬性患雇,用 對象變量.屬性名 的方式
      person.name
      < 'Bob'
      person.zipcode
      < null
      
4. 嚴(yán)格檢查模式:'use strict'
  • 預(yù)防 JavaScript 隨意性導(dǎo)致產(chǎn)生的一些問題;

  • 必須寫在 script 標(biāo)簽內(nèi)的第一行宇挫。

    <script>
        // 嚴(yán)格檢查模式:必須寫在 script 標(biāo)簽內(nèi)的第一行
        // 前提:IDEA苛吱,設(shè)置支持ES6語法
        'use strict';
        // 如果瀏覽器支持strict模式,下面的代碼將報ReferenceError錯誤
        abc = 'Hello, world';
        // ES6 局部變量建議let去定義
        let a = "abc";
        console.log(abc);
    </script>
    
  • IDEA 設(shè)置支持 ES6 語法

三器瘪、數(shù)據(jù)類型

1. 字符串
  • 正常字符串:使用單引號翠储、雙引號包裹

    console.log('a');
    console.log("a");
    
  • 轉(zhuǎn)義字符:\ 其它轉(zhuǎn)義符

    \';   // '
    \\; // \
    \n;   // 換行
    \t;   // 制表位
    \u4e2d;   // \u#### Unicode 字符
    \x41; // Ascll字符
    
  • 多行字符串:ES6 新增,反引號 ``表示

    // tab 和 ESC 鍵中間的字符 `` 包裹
    let msg = `這是
              一個多行
              字符串`;
    
  • 模板字符串

    • ES6 新增
    let name = '小明';
    let age = 20;
    // let message = '你好, ' + name + ', 你今年' + age + '歲了!';
    // ES6 新增
    let message = `你好, ${name}, 你今年${age}歲了!`;
    console.log(message);
    
  • 字符串長度

    let s = 'Hello, world!';
    s.length; // 13
    
  • 獲取字符串指定位置字符:

    • 使用類似 Array 的下標(biāo)操作娱局,索引號從0開始:
    let s = 'Hello, world!';
    s[0]; // 'H'
    s[6]; // ' '
    s[7]; // 'w'
    s[12]; // '!'
    s[13]; // undefined 超出范圍的索引不會報錯彰亥,但一律返回undefined
    
  • 字符串 不可變

    • 對字符串的某個索引賦值,不會有任何錯誤衰齐,但是任斋,也沒有任何效果:
    let s = 'Test';
    s[0] = 'X';
    console.log(s); // s仍然為'Test'
    
  • 大小寫轉(zhuǎn)換

    // 注意:這里是方法,不是屬性
    s.toUpperCase();  // 轉(zhuǎn)大寫
    s.toLowerCase();  // 轉(zhuǎn)小寫
    
  • 查找指定字符串出現(xiàn)的位置:indexOf()

    let s = 'hello, world';
    s.indexOf('world'); // 返回7
    s.indexOf('Worldd'); // 沒有找到指定的子串,返回-1
    
  • 返回指定索引區(qū)間的字符串:substring()

    let s = 'hello, world'
    s.substring(0, 5); // [0,5)從索引0開始到5废酷,返回'hello'
    s.substring(7); // 從索引7開始到結(jié)束瘟檩,返回'world'
    
2. 數(shù)組
  • Array 可以包含任意的數(shù)據(jù)類型:(下標(biāo)索引從0開始)

    var arr = [1, 2, 3.14, 'Hello', null, true];
    arr.length; // 6
    
  • 注意:直接給 Array 的 length 賦一個新的值會導(dǎo)致 Array 大小的變化

    let arr = [1, 2, 3];
    arr.length; // 3
    arr.length = 6;
    arr; // arr變?yōu)閇1, 2, 3, undefined, undefined, undefined]
    arr.length = 2;
    arr; // arr變?yōu)閇1, 2]
    
  • 如果數(shù)組索引賦值變小,元素就會丟失澈蟆;

  • 通過索引修改為新的值:

    let arr = ['A', 'B', 'C'];
    arr[1] = 99;
    arr; // arr現(xiàn)在變?yōu)閇'A', 99, 'C']
    
  • 通過索引賦值時墨辛,索引超過了范圍,同樣會引起 Array 大小的變化:

    let arr = [1, 2, 3];
    arr[5] = 'x';
    arr; // arr變?yōu)閇1, 2, 3, undefined, undefined, 'x']
    
  • 不建議直接修改 Array 的大小趴俘,訪問索引時要確保索引不會越界睹簇。

數(shù)組常用方法

  1. indexOf():通過元素獲得下標(biāo)索引
    var arr = [10, 20, '30', 'xyz'];
    arr.indexOf(10); // 元素10的索引為0
    arr.indexOf(20); // 元素20的索引為1
    arr.indexOf(30); // 元素30沒有找到,返回-1
    arr.indexOf('30'); // 元素'30'的索引為2
    
  • 注意:數(shù)字 30 和字符串 '30' 是不同的元素寥闪。
  1. slice() :類似于 String 中的substring()

    • 截取 Array 的一部分太惠,返回一個新的數(shù)組。
    let arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
    arr.slice(0, 3); // 從索引0開始疲憋,到索引3結(jié)束凿渊,但不包括索引3: ['A', 'B', 'C']
    arr.slice(3); // 從索引3開始到結(jié)束: ['D', 'E', 'F', 'G']
    // 不傳遞任何參數(shù),它就會從頭到尾截取所有元素(相當(dāng)于復(fù)制一個新數(shù)組)
    let aCopy = arr.slice();
    aCopy; // ['A', 'B', 'C', 'D', 'E', 'F', 'G']
    aCopy === arr; // false
    
  2. push()和pop()

    • push():向 Array 的末尾添加若干元素缚柳;
    • pop():把 Array 的最后一個元素刪除掉埃脏。
    var arr = [1, 2];
    arr.push('A', 'B'); // 返回Array新的長度: 4
    arr; // [1, 2, 'A', 'B']
    arr.pop(); // pop()返回'B'
    arr; // [1, 2, 'A']
    arr.pop(); arr.pop(); arr.pop(); // 連續(xù)pop 3次
    arr; // []
    arr.pop(); // 空數(shù)組繼續(xù)pop不會報錯,而是返回undefined
    arr; // []
    
  3. unshift()和shift()

    • unshift():往 Array 的頭部添加若干元素秋忙;
    • shift():把 Array 的第一個元素刪掉彩掐。
    let arr = [1, 2];
    arr.unshift('A', 'B'); // 返回Array新的長度: 4
    arr; // ['A', 'B', 1, 2]
    arr.shift(); // 'A'
    arr; // ['B', 1, 2]
    arr.shift(); arr.shift(); arr.shift(); // 連續(xù)shift 3次
    arr; // []
    arr.shift(); // 空數(shù)組繼續(xù)shift不會報錯,而是返回undefined
    arr; // []
    
  4. sort() 排序

    • 直接修改當(dāng)前 Array 的元素位置翰绊,直接調(diào)用時佩谷,按照默認(rèn)順序排序。
    let arr = ['B', 'C', 'A'];
    arr.sort();
    arr; // ['A', 'B', 'C']
    
  5. reverse() 元素反轉(zhuǎn)

    let arr = ['one', 'two', 'three'];
    arr.reverse();
    arr; // ['three', 'two', 'one']
    
  6. splice()

    • 是修改 Array 的 萬能方法监嗜;
    • 可以從指定的索引開始刪除若干元素谐檀,然后再從該位置添加若干元素。
    let arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
    // 從索引2開始刪除3個元素,然后再添加兩個元素:
    arr.splice(2, 3, 'Google', 'Facebook'); // 返回刪除的元素 ['Yahoo', 'AOL','Excite']
    arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
    // 只刪除,不添加:
    arr.splice(2, 2); // ['Google', 'Facebook']
    arr; // ['Microsoft', 'Apple', 'Oracle']
    // 只添加,不刪除:
    arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因為沒有刪除任何元素
    arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
    
  7. concat()

    • 當(dāng)前的 Array 和另一個 Array 連接起來裁奇,并返回一個 新的 Array桐猬。
    let arr = ['A', 'B', 'C'];
    let added = arr.concat([1, 2, 3]);
    added; // ['A', 'B', 'C', 1, 2, 3]
    arr; // ['A', 'B', 'C']
    
  8. join()

    • 把當(dāng)前 Array 的每個元素,用指定的字符串連接起來刽肠,返回連接后的字符串溃肪。
    // 如果 Array 的元素不是字符串,將自動轉(zhuǎn)換為字符串后再連接
    let arr = ['A', 'B', 'C', 1, 2, 3];
    arr.join('-'); // 'A-B-C-1-2-3'
    
  9. 多維數(shù)組

    let arr = [[1, 2, 3], [400, 500, 600], '-'];
    let x = arr[1][1];
    console.log(x); // 500
    
3. 對象
  • 無序的集合數(shù)據(jù)類型音五,由若干鍵值對組成惫撰。

    var 對象名 = {
      key: 'value',
      key: 'value',
      key: 'value'
    };
    // 多個屬性之間使用逗號隔開,最后一個屬性不加逗號躺涝!
    
  • JavaScript 中的所有鍵都是字符串厨钻,值是任意對象!

  1. 定義一個對象

    var person = {
     name: '小明',
     birth: 1990,
     school: 'No.1 Middle School',
     height: 1.70,
     weight: 65,
     score: null
    };
    
  2. 獲取對象的屬性:對象.屬性對象["屬性"]

    • 使用一個不存在的對象屬性,不會報錯夯膀!undefined
    var person = {
     name: '小明'
    };
    
    person["name"];  // '小明'
    person.age; // undefined
    
  3. 動態(tài)的給對象刪除屬性(delete)

    var person = {
     name: '小明'
    };
    delete person['name']; // 刪除name屬性
    person.name; // undefined
    delete person.id; // 刪除一個不存在的id屬性也不會報錯
    
  4. 動態(tài)給新的屬性添加值

    var person = {
     name: '小明'
    };
    person.age = 18; // 新增一個age屬性
    person.age; // 18
    
  5. 判斷對象是否擁有某一屬性:in 操作符

    var person = {
     name: '小明',
     birth: 1990,
     school: 'No.1 Middle School',
     height: 1.70,
     weight: 65,
     score: null
    };
    'name' in person;    // true
    'id' in person;  // false
    
    // 繼承的屬性也為true
    'toString' in person;    // true
    
  6. hasOwnProperty():判斷是否是對象自身擁有的屬性

    var person = {
     name: '小明'
    };
    person.hasOwnProperty("toString");   // false 繼承屬性非自身
    person.hasOwnProperty("name");   // true
    
4. 流程控制
  • if 判斷

    let age = 8;
    if (age >= 18) {
        alert('adult');
    } else if (age >= 13) {
        alert('teenager');
    } else {
        alert('kid');
    }
    
  • while 循環(huán):避免程序死循環(huán) while(true)

    let x = 0;
    let n = 99;
    while (n > 0) {
        x += n; // x = x + n;
        n -= 2; // n = n - 2;
    }
    console.log(x); // 2500 計算奇數(shù)和
    
  • do...while:無論條件是否為真诗充,都先執(zhí)行一遍

    let n = 0;
    do {
        n += 1; // n = n + 1;
    } while (n < 100);
    console.log(n); // 100
    
  • for 循環(huán)

    // 基礎(chǔ)for
    let x = 0;
    let i;
    for (i = 1; i <= 100; i++) {
        x += i; // x = x + i;
    }
    console.log(x); // 5050
    
    // 遍歷數(shù)組
    let arr = ['Apple', 'Google', 'Microsoft'];
    let i, x;
    for (i = 0; i < arr.length; i++) {
        x = arr[i];
        console.log(x);
    }
    
  • 編寫循環(huán)代碼時,務(wù)必小心編寫 初始條件判斷條件诱建,尤其是 邊界值蝴蜓。

  • 特別注意 i < 100i <= 100 是不同的判斷邏輯。

  • 無限循環(huán)

    let x = 0;
    for (; ;) { // 未設(shè)置判斷條件俺猿,將無限循環(huán)
        if (x > 100) {
            break; // 通過if判斷來退出循環(huán)
        }
        x++;
    }
    
  • for ... in:遍歷屬性 (數(shù)組為索引)

    let person = {
        name: 'Jack',
        age: 20,
        city: 'Beijing'
    };
    // 遍歷屬性
    for (let key in person) {
        // 判斷屬性是否為自身屬性
        if (person.hasOwnProperty(key))
            console.log(`${key}:${person[key]}`);
    }
    
    // Array也是對象茎匠,元素的索引視為對象的屬性,遍歷出來是下標(biāo)
    let a = ['A', 'B', 'C'];
    for (let i in a) {
        console.log(i); // '0', '1', '2'
        console.log(a[i]);  // 'A', 'B', 'C'
    }
    
  • 注意:for ... in 對 Array 的循環(huán)得到的是 String 而不是 Number

  • for ... of(ES6):遍歷屬性值 (數(shù)組為元素)

    const cars = ["BMW", "Volvo", "Mini"];
    for (let x of cars) {
        console.log(x);   // "BMW", "Volvo", "Mini"
    }
    
    // 遍歷字符串
    let language = "JavaScript";
    for (let x of language) {
        console.log(x);   // 'J','a'...'t'
    }
    
    // 遍歷數(shù)組(獲取為元素辜荠,非下標(biāo))
    let a = ['A', 'B', 'C'];
    for (let i of a) {
        console.log(i); // 'A', 'B', 'C'
    }
    
  • forEach 循環(huán)(ES5.1):遍歷數(shù)組元素及索引汽抚,不能遍歷對象

    • 對象轉(zhuǎn)數(shù)組:Object.keys(person);
     // 遍歷元素及索引
    let age = [12, 3, 4, 22, 23, 55];
    // 傳遞函數(shù)(lambda簡化)
    age.forEach((value, index) => {
        console.log(`${index}:${value}`);
    });
    // age.forEach(function (value, index) {
    //     console.log(`${index}:${value}`);
    // });
    
5. Map 和 Set
  • 默認(rèn)對象表示方式 { } ,類似其他語言中的 Map 或 Dictionary 的數(shù)據(jù)結(jié)構(gòu)伯病,即一組鍵值對;
  • JavaScript 的對象否过,鍵必須是字符串午笛,無法用 Number 或者其他數(shù)據(jù)類型作為鍵;
  • ES6 引入了新的數(shù)據(jù)類型 Map苗桂。

Map:K-VK不能重復(fù)

// 學(xué)生姓名药磺,學(xué)生成績
// let names = ['Michael', 'Bob', 'Tracy'];
// let scores = [95, 75, 85];

// Map 實現(xiàn)
let map = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
let name = map.get('Michael'); // 95 通過key獲取value
map.set('admin', 100);  // 添加元素
map.delete('Bob');  // 刪除元素

Set:無序不重復(fù)的集合

  • Set 和 Map 類似,也是一組 key 的集合煤伟,但不存儲 value癌佩;
  • 由于 key 不能重復(fù),所以便锨,在 Set 中围辙,沒有重復(fù)的 key。
let set = new Set([3, 2, 1]);
set.add(5); // 增加元素
set.delete(3);  // 刪除元素
set.has(1); // 判斷是否包含元素
set.size;   // 長度
6. iterator
  • 遍歷 Array 可以采用下標(biāo)循環(huán)放案,遍歷 Map 和 Set 就無法使用下標(biāo)姚建;

  • 為了統(tǒng)一集合類型,ES6 標(biāo)準(zhǔn)引入了新的 iterable 類型(Array吱殉、Map掸冤、Set);

  • 具有 iterable 類型的集合可以通過新的 for ... of 循環(huán)來遍歷友雳。

  • 遍歷數(shù)組

    // 通過for...of遍歷值 / for...in 遍歷下標(biāo)
    let array = [1, 2, 3];
    for (let x of array) {
        console.log(x);
    }
    
  • 遍歷 Map

    let map = new Map([['tom', 100], ['jack', 90], ['tim', 80]]);
    for (let x of map) {
        console.log(x);
    }
    
  • 遍歷 Set

    let set = new Set([3, 2, 1]);
    for (let x of set) {
        console.log(x);
    }
    
  • forEach 方法:

    • ES5.1 同時獲得 K-V稿湿;
    • 它接收一個函數(shù),每次迭代就自動回調(diào)該函數(shù)押赊。
    // Array
    let a = ['A', 'B', 'C'];
    // element: 當(dāng)前元素值  index: 當(dāng)前索引  array: Array對象本身
    a.forEach((element, index, array) => {
        console.log(`index = ${index}:${element}`);
    });
    
    // Set
    let s = new Set(['set1', 'set2', 'set3']);
    // 沒有索引饺藤,前兩個參數(shù)都是元素本身
    s.forEach((element, sameElement, set) => {
        console.log(element);
    });
    
    // Map
    let m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
    m.forEach((value, key, map) => {
        console.log(`${key}:${value}`);
    });
    

四、函數(shù)

1. 定義函數(shù)

定義方式一 :推薦

  • function 函數(shù)名(參數(shù)){...}
// 求一個數(shù)的絕對值
function abs(x) {
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
}
  • 一旦執(zhí)行到 return 時,函數(shù)就執(zhí)行完畢策精,并將結(jié)果返回舰始;
  • 如果沒有 return 語句,函數(shù)執(zhí)行完畢后也會返回結(jié)果咽袜,只是結(jié)果為 undefined 丸卷。

定義方式二:

  • var 函數(shù)名 = function (參數(shù)){...};
let abs = function (x) {
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
};
  • function(x){….} 這是一個匿名函數(shù),把結(jié)果賦值給 abs询刹,通過 abs 調(diào)用函數(shù)谜嫉;
  • 兩種定義完全等價;
  • 注意:第二種方式凹联,按照完整語法需要在函數(shù)體末尾加一個 ;沐兰,表示賦值語句結(jié)束。
2. 調(diào)用函數(shù)
  • 調(diào)用函數(shù)時蔽挠,按順序傳入?yún)?shù)即可:

    abs(10); // 返回10
    abs(-9); // 返回9
    
  • 參數(shù)問題:JavaScript 可以傳任意多個參數(shù)住闯;

    abs(10, 'blablabla'); // 返回10
    abs(-9, 'haha', 'hehe', null); // 返回9
    
  • 傳入的參數(shù)比定義的少也沒有問題,也可以不傳:

    abs(); // 返回NaN
    
  • 此時 abs(x) 函數(shù)的參數(shù) x 將收到 undefined 澳淑,計算結(jié)果為 NaN比原。

  • 要避免收到 undefined ,可以對參數(shù)進(jìn)行檢查:

function abs(x) {
    // 判斷參數(shù)是否為 number 類型
    if (typeof x !== 'number') {
        throw 'Not a number';
    }
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
}

arguments

  • arguments 是關(guān)鍵字杠巡,只在函數(shù)內(nèi)部起作用量窘;

  • 永遠(yuǎn)指向當(dāng)前函數(shù)的調(diào)用者傳入的所有參數(shù);

  • 是一個數(shù)組氢拥。

    function foo(x) {
        console.log(`x = ${x}`); // 10
        for (let i = 0; i < arguments.length; i++) {
            console.log(`arg[${i}]=${arguments[i]}`);
        }
    }
    
    foo(10, 20, 30);
    
  • 利用 arguments 蚌铜,即使函數(shù)不定義任何參數(shù),還是可以拿到參數(shù)的值:

    function abs() {
        if (arguments.length === 0) {
            return 0;
        }
        let x = arguments[0];
        return x >= 0 ? x : -x;
    }
    
    abs(); // 0
    abs(10); // 10
    abs(-9); // 9
    
  • arguments 最常用于判斷傳入?yún)?shù)的個數(shù):

    // foo(a[, b], c)
    // 接收2~3個參數(shù)嫩海,b是可選參數(shù)冬殃,如果只傳2個參數(shù),b默認(rèn)為null:
    function foo(a, b, c) {
        if (arguments.length === 2) {
            // 實際拿到的參數(shù)是a和b出革,c為undefined
            c = b; // 把b賦給c
            b = null; // b變?yōu)槟J(rèn)值
        }
        // ...
    }
    
  • arguments 包含所有的參數(shù)造壮,想使用多余的參數(shù)操作,需要排除已有參數(shù)骂束。

rest 參數(shù)

  • ES6 以前耳璧,獲取參數(shù):

    function foo(a, b) {
        let i, rest = [];
        if (arguments.length > 2) {
            // 將多出來的參數(shù),放入數(shù)組
            for (i = 2; i < arguments.length; i++) {
                rest.push(arguments[i]);
            }
        }
        console.log('a = ' + a);
        console.log('b = ' + b);
        console.log(rest);
    }
    
  • ES6 標(biāo)準(zhǔn)引入了rest 參數(shù)展箱,獲取除了已定義的參數(shù)之外所有的參數(shù)

    function foo(a, b, ...rest) {
        console.log('a = ' + a);
        console.log('b = ' + b);
        console.log(rest);
    }
    
    foo(1, 2, 3, 4, 5);
    // 結(jié)果:
    // a = 1
    // b = 2
    // Array [ 3, 4, 5 ]
    foo(1);
    // 結(jié)果:
    // a = 1
    // b = undefined
    // Array []
    
  • 注意:rest 參數(shù)只能寫在最后旨枯,前面必須用 ... 標(biāo)識

  • 從運行結(jié)果可知,傳入的參數(shù)先綁定 a 混驰、 b 攀隔,多余的參數(shù)以數(shù)組形式交給變量 rest 皂贩,不再需要 arguments 就獲取全部參數(shù)。

3. 變量的作用域
  1. 變量作用域
  • 在 JavaScript 中昆汹, var 定義的變量明刷,是有作用域的;

  • 如果在 函數(shù)體內(nèi) 聲明满粗,則在 函數(shù)體外 不可以使用辈末。

    function foo() {
        var x = 1;    
    }
    
    x = x + 2;  // Uncaught ReferenceError: x is not defined
    
  • 不同函數(shù)內(nèi)部的同名變量,互不影響:

    function foo() {
        var x = 1;
        x = x + 1;
    }
    
    function bar() {
        var x = 'A';
        x = x + 'B';
    }
    
  • 內(nèi)部函數(shù)可以訪問外部函數(shù)的成員映皆,反之則不行:

    function foo() {
        var x = 1;
    
        function bar() {
            var y = x + 1; // bar可以訪問foo的變量x!
        }
    
        var z = y + 1; // ReferenceError! foo不可以訪問bar的變量y!
    }
    
  • 內(nèi)部函數(shù)和外部函數(shù)的變量名重名

    function foo() {
        var x = 1;
    
        function bar() {
            var x = 'A';
            console.log('x in bar() = ' + x); // 'A'
        }
    
        console.log('x in foo() = ' + x); // 1
        bar();
    }
    
    foo();
    

    總結(jié):

    • JavaScript 的函數(shù)挤聘,查找變量從自身函數(shù)開始,從 內(nèi) 查找捅彻。
    • 如果內(nèi)部函數(shù)组去、外部函數(shù)有 重名的變量,則內(nèi)部函數(shù)的變量將 屏蔽 外部函數(shù)的變量步淹。
  1. 提升變量作用域
  • JavaScript 的函數(shù)定義特點从隆,先掃描整個函數(shù)體的語句,把所有聲明的變量 自動提升到函數(shù)頂部

    function foo() {
        var x = 'Hello, ' + y;
        console.log(x);
        var y = 'Bob';
    }
    
    foo();
    
  • 結(jié)果:Hello, undefined 贤旷, 說明 y 的值為 undefined广料;

  • 自動提升了變量 y 的聲明,但不提升變量 y 的賦值幼驶;

  • JavaScript 引擎看到的代碼相當(dāng)于:

    function foo() {
        var y; // 提升變量y的聲明,此時y為undefined
        var x = 'Hello, ' + y;
        console.log(x);
        y = 'Bob';
    }
    
  • 在函數(shù)內(nèi)部定義變量時韧衣,要嚴(yán)格遵守 在函數(shù)內(nèi)部盅藻,首先申明所有變量

  • 常見做法:在函數(shù)頭部畅铭,先聲明氏淑,再使用:

    function foo() {
        var x = 1,  // x初始化為1
            y = x + 1,  // y初始化為2
            z, i;   // z和i為undefined
        // 其他語句:
    }
    
  1. 全局函數(shù)
  • 不在任何函數(shù)內(nèi)定義的變量,就具有全局作用域硕噩。
    // 全局變量
    var a = 1;
    function f() {
        console.log(a);
    }
    f();
    console.log(a);
    

全局對象 window

  • JavaScript 默認(rèn)有一個全局對象 window 假残,全局作用域的變量,實際上是被綁定到 window 的一個屬性:

    `use strict`
    var course = 'JavaScript';
    alert(course);  // 'JavaScript'
    alert(window.course);   // 'JavaScript
    
  • 直接訪問全局變量 course 和訪問 window.course 是完全一樣炉擅;

  • 頂層函數(shù)的定義辉懒,也被視為一個全局變量,并綁定到 window 對象:

    function foo() {
        alert('foo');
    }
    
    foo();  // 直接調(diào)用foo()
    window.foo();   // 通過window.foo()調(diào)用
    
  • alert() 函數(shù)其實也是 window 的一個變量:

window.alert('調(diào)用window.alert()');
// 把a(bǔ)lert保存到另一個變量:
var old_alert = window.alert;
// 給alert賦一個新函數(shù):
window.alert = function () {
}
alert('無法用alert()顯示了!');
// 恢復(fù)alert:
window.alert = old_alert;
alert('又可以用alert()了!');

說明:

  • JavaScript 實際上只有一個全局作用域谍失。
  • 任何變量(函數(shù)也視為變量)眶俩,如果沒有在當(dāng)前函數(shù)作用域中找到,就會繼續(xù)往上查找快鱼,最后如果在全局作用域中也沒有找到颠印,則報 ReferenceError 錯誤纲岭。

規(guī)范:

  • 不同的 JavaScript 文件如果使用了相同的全局變量,或者定義了相同名字的頂層函數(shù)线罕,都會造成命名沖突止潮,并且很難被發(fā)現(xiàn);
  • 減少沖突:把所有變量和函數(shù)钞楼,全部綁定到一個自定義全局變量中喇闸。
// 唯一的全局變量MYAPP:
var MYAPP = {};
// 其他變量:
MYAPP.name = 'myapp';
MYAPP.version = 1.0;
// 其他函數(shù):
MYAPP.foo = function () {
    return 'foo';
};
  • 把自己的代碼全部放入唯一的名字空間 MYAPP 中,會大大減少全局變量沖突的可能窿凤。
  • 很多 JavaScript 庫都也是這樣的:jQuery仅偎,YUI,underscore等等雳殊。
  1. 局部作用域:let
  • 在 for 循環(huán)等語句塊中橘沥,是無法定義具有局部作用域的變量的:

    function foo() {
        for (var i = 0; i < 100; i++) {
            // ...
        }
        i += 100;   // 問題:出了作用域,仍然可以引用變量i
        console.log(i);   // 200
    }
    
  • ES6 用 let 替代 var 夯秃,解決局部作用域沖突問題

    function foo() {
        for (let i = 0; i < 100; i++) {
            // ...
        }
        i += 100;   // Uncaught ReferenceError: i is not defined
        console.log(i);
    }
    
  • 建議:用 let 定義局部作用域變量座咆。

  1. 常量 const
  • ES6 之前:用全部大寫的變量來表示 常量,建議不要修改它的值:

    var PI = 3.14
    console.log(PI);
    PI = 123;   // 值可以修改
    console.log(PI);
    
  • ES6 引入了關(guān)鍵字 const 定義常量仓洼, constlet 都具有塊級作用域:

    const PI = 3.14;    // 只讀變量
    console.log(PI);
    // TypeError: Assignment to constant variable
    PI = 123;   // 某些瀏覽器不報錯介陶,但是無效果
    console.log(PI);    // 3.14
    
4. 方法

定義方法

  • 方法:對象中的函數(shù),稱為這個對象的方法色建;

  • 對象只包含:屬性哺呜、方法;

  • 方法調(diào)用:對象.方法名();箕戳,方法名后某残,一定要帶()

  • 實例:

    var person = {
        name: '小明',
        birth: 1990,
        age: function () {
            // 獲取當(dāng)前年份
            let y = new Date().getFullYear();
            // 返回年齡
            // this 當(dāng)前調(diào)用它的對象
            return y - this.birth;
        }
    };
    person.age; // 返回值:方法 person.age()
    person.age();   // 返回具體數(shù)值
    
  • 在方法內(nèi)部陵吸,this 始終指向當(dāng)前調(diào)用它對象玻墅,如:person 調(diào)用,this.birth 則指向 person 的 birth 屬性壮虫。

  • 把上述代碼拆分:

    // 把年齡方法拆分出來(函數(shù))
    function getAge() {
        let y = new Date().getFullYear();
        return y - this.birth;
    }
    
    var person = {
        name: '小明',
        birth: 1990,
        age: getAge
    };
    person.age();   // 正常結(jié)果
    getAge();   // NaN
    

    分析:

    • person.age();:以對象的方法形式調(diào)用澳厢,this 指向?qū)ο?person,所以返回 person 的屬性囚似;
    • getAge();:單獨調(diào)用函數(shù)剩拢,this 指向全局對象(window),沒有對應(yīng)的屬性谆构,所以返回 NaN裸扶。

apply:控制 this 的指向

  • 函數(shù)名.apply(對象,[]);
  • JavaScript 的所有函數(shù)都可以調(diào)用搬素;
  • 接收兩個參數(shù):
    1. this 指向的變量呵晨;
    2. Array :數(shù)組對象魏保,表示函數(shù)本身。
    function getAge() {
        let y = new Date().getFullYear();
        return y - this.birth;
    }
    
    var person = {
        name: '小明',
        birth: 1990,
        age: getAge
    };
    
    // person:this指向的對象摸屠; []:空參谓罗,數(shù)組對象
    getAge.apply(person,[]);
    

五、內(nèi)部對象

1. 標(biāo)準(zhǔn)對象
  • JavaScript 里季二,一切都是對象檩咱;
  • typeof:獲取對象的類型,返回字符串:
typeof 123; // 'number'
typeof NaN; // 'number'
typeof 'str'; // 'string'
typeof true; // 'boolean'
typeof undefined; // 'undefined'
typeof Math.abs; // 'function'
typeof null; // 'object'
typeof []; // 'object'
typeof {}; // 'object'
2. Date
  • Date:表示日期和時間
var now = new Date();
now;   // Mon Feb 07 2022 10:44:36 GMT+0800 (中國標(biāo)準(zhǔn)時間)
now.getFullYear();  // 年份
now.getMonth(); // 月份:范圍是0~11胯舷,值需要 +1
now.getDate();  // 日
now.getDay();   // 星期
now.getHours(); // 小時, 24小時制
now.getMinutes();   // 分鐘
now.getSeconds();   // 秒
now.getMilliseconds();  // 毫秒數(shù)
now.getTime();  // 時間戳 全世界統(tǒng)一 1970 1.1 00:00:00 毫秒數(shù)
console.log(new Date(1644204579172));   // 時間戳轉(zhuǎn)為時間
  • 注意:當(dāng)前時間是瀏覽器從本機(jī)操作系統(tǒng)獲取的時間刻蚯,不一定準(zhǔn)確,當(dāng)前時間設(shè)定為任何值桑嘶。

  • 轉(zhuǎn)換

    var d = new Date(1644204579172);
    d.toLocaleString;   // 注意:調(diào)用的是一個方法炊汹,不是一個屬性
    d.toLocaleString(); // 顯示的字符串與操作系統(tǒng)設(shè)定的格式有關(guān)
    d.toUTCString();    // UTC時間,與本地時間相差8小時
    
  • 時區(qū)轉(zhuǎn)換:只需要傳遞時間戳逃顶,或者從數(shù)據(jù)庫里讀時間戳讨便,再讓 JavaScript 自動轉(zhuǎn)換為當(dāng)?shù)貢r間。

  • 獲取當(dāng)前時間戳:

    if (Date.now) {
      // 老版本IE沒有now()方法
        console.log(Date.now()); 
    } else {
        console.log(new Date().getTime());
    }
    
3. JSON
  • 早期以政,所有的數(shù)據(jù)傳輸習(xí)慣都使用 XML 文件
  • JSON(JavaScript Object Notation霸褒,JS 對象標(biāo)記)輕量級數(shù)據(jù)交換格式;
  • 簡潔盈蛮、結(jié)構(gòu)清晰废菱,使 JSON 成為理想的數(shù)據(jù)交換語言;
  • 易于人閱讀和編寫抖誉,同時也易于機(jī)器解析和生成昙啄,并有效地提升網(wǎng)絡(luò)傳輸效率;
  • 在 JavaScript 中寸五,一切皆為對象,任何 JS 支持的類型耿币,都可以用 JSON 來表示梳杏。

    格式:

    • 對象:{}
    • 數(shù)組:[]
    • 鍵值對:key:value
  • JSON 鍵值對:

    {"name":"Tom"}
    {"age":"20"}
    {"sex":"男"}
    
  • JSON 是 JavaScript 對象的字符串表示法厢蒜,使用文本表示一個 JS 對象的信息墩虹,本質(zhì)是一個字符串闲擦。

    // 對象:鍵名也可以使用引號包裹
    var obj = {a: 'Hello', b: 'World'};
    // JSON:本質(zhì)是一個字符串
    var json = '{"a": "Hello", "b": "World"}';
    
  • JSON 和 JavaScript 對象互轉(zhuǎn):

    • JSON.parse()叫编;:JSON 轉(zhuǎn) JavaScript 對象
    // JSON 轉(zhuǎn) JavaScript 對象
    var obj = JSON.parse('{"a": "Hello", "b": "World"}');
    // 結(jié)果是 {a: 'Hello', b: 'World'}
    
    • JSON.stringify();:JavaScript 對象轉(zhuǎn) JSON
    // JavaScript  對象轉(zhuǎn) JSON
    var json = JSON.stringify({a: 'Hello', b: 'World'});
    // 結(jié)果是 '{"a": "Hello", "b": "World"}'
    
  • 實例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JSON</title>
    <script>
        `use strict`
        // 編寫一個js的對象
        var user = {
            name: "Tom",
            age: 20,
            sex: "男"
        };
        // 將js對象轉(zhuǎn)換成json字符串
        let str = JSON.stringify(user);
        console.log(str);
        // 將json字符串轉(zhuǎn)換為js對象
        let user2 = JSON.parse(str);
        console.log(user2.age, user2.name, user2.sex);
    </script>
</head>
<body>

</body>
</html>
4. Ajax
  • 原生的 JS 寫法余掖,xhr 異步請求务嫡;
  • jQuery 封裝好的方法 $(“#name”).ajax(“”)心铃;
  • axios 請求。

六挫剑、面向?qū)ο缶幊?/h4>

1. 原型對象
  • 面向?qū)ο蟮膬蓚€基本概念:

    • 類:對象的類型模板去扣,原型對象;
    • 對象:根據(jù)類創(chuàng)建的具體實例樊破。
  • JavaScript 的面向?qū)ο笥淅猓推渌Z言,如:Java哲戚、C# 的面向?qū)ο螅?strong>有區(qū)別:

    • JavaScript 不區(qū)分 實例 的概念奔滑;
    • 通過 原型 (prototype)來實現(xiàn)面向?qū)ο缶幊獭?/li>
  • 原型:可以理解為父類(但不同),B 對象顺少,通過指向朋其,使用 A 對象的屬性和方法,A 就是 B 的原型對象脆炎;

    // user 的原型對象
    var student = {
        name: 'Robot',
        age: 20,
        run: function () {
            console.log(this.name + ' is running...');
        }
    };
    var user = {
        name: '小明'
    };
    // user的原型對象是student
    user.__proto__ = student;
    
2. class
  • JavaScript 的對象模型是基于原型實現(xiàn)的梅猿;

  • 優(yōu)點:簡單;

  • 缺點:

    • 比傳統(tǒng)的 類-實例 模型困難秒裕;
    • 繼承的實現(xiàn)需要編寫大量代碼袱蚓;
    • 需要正確實現(xiàn)原型鏈。
    // 了解:函數(shù)實現(xiàn) Student 的方法
    function Student(name) {
        this.name = name;
    }
    
    // 通過原型几蜻,給Student新增一個方法
    Student.prototype.hello = function () {
        alert('Hello, ' + this.name + '!');
    };
    var user = new Student("user").hello();
    
  • ES6 引入 class

    // ES6 定義一個學(xué)生類
    class Student {
        // constructor 構(gòu)造函數(shù)
        constructor(name) {
            this.name = name;
        }
    
        hello() {
            alert(`Hello,${this.name}`);
        }
    }
    
    // 創(chuàng)建實例
    let user1 = new Student("user1");
    let user2 = new Student("user2");
    // 調(diào)用
    user1.hello();
    user2.hello();
    
3. 繼承 extends
// 學(xué)生類
class Student {
    constructor(name) {
        this.name = name;
    }

    hello() {
        alert('hello')
    }
}

// 繼承學(xué)生類
class PrimaryStudent extends Student {
    // 本類的構(gòu)造函數(shù)
    constructor(name, grade) {
        // 用super調(diào)用父類的構(gòu)造方法!
        super(name);
        this.grade = grade;
    }

    // 本類的方法
    myGrade() {
        alert(`I am at grade ${this.grade}`);
    }
}

// 調(diào)用父類的方法
let student1 = new PrimaryStudent("小明", 5).hello();
// 調(diào)用本類的方法
let student2 = new PrimaryStudent("小明", 5).myGrade();
  • 本質(zhì):對象原型
4. 原型鏈

七癞松、操作 BOM 對象(重點)

1. 瀏覽器介紹
  • JavaScript 和瀏覽器的關(guān)系:為了能在瀏覽器中運行;
  • BOM:瀏覽器對象模型入蛆;
  • IE 6~11;
  • Chrome硕勿;
  • Safari哨毁;
  • FireFox;
  • Opera源武;

第三方

  • QQ 瀏覽器扼褪;
  • 360想幻;
2. window(重要)
  • window 對象不但充當(dāng)全局作用域,而且表示瀏覽器窗口话浇;
  • innerWidth脏毯、innerHeight:瀏覽器窗口的 內(nèi)部 寬度和高度沪蓬;
    • 內(nèi)部寬高:除去菜單欄水评、工具欄实檀、邊框等占位元素后逃呼,用于顯示網(wǎng)頁的凈寬高帖世;
  • outerWidth饼灿、outerHeight:瀏覽器窗口的整個寬高其掂;
  • 兼容性:IE<= 8 不支持缤底。
    window.alert(1);
    window.innerHeight;   // 內(nèi)部高度
    window.innerwidth;    // 內(nèi)部寬度
    window.outerHeight;   // 外部高度
    window.outerWidth;    // 外部寬度
    //調(diào)整游覽器窗口嗅定,值會改變
    
3. navigator 瀏覽器信息(不建議使用)
  • navigator 對象表示瀏覽器的信息自娩,最常用的屬性包括:

    • navigator.appName:瀏覽器名稱;
    • navigator.appVersion:瀏覽器版本渠退;
    • navigator.language:瀏覽器設(shè)置的語言忙迁;
    • navigator.platform:操作系統(tǒng)類型;
    • navigator.userAgent:瀏覽器設(shè)定的 User-Agent 字符串碎乃。
  • 注意:navigator 的信息可以被用戶修改姊扔,所以 JavaScript 讀取的值不一定是正確的。不建議直接使用荠锭,例如:

    let width;
    if (getIEVersion(navigator.userAgent) < 9) {
        width = document.body.clientWidth;
    } else {
        width = window.innerWidth;
    }
    
  • 建議:利用 JavaScript 對不存在屬性返回 undefined 的特性旱眯,直接用短路運算符 || 計算:

    let width = window.innerWidth || document.body.clientWidth;
    
4. screen 屏幕信息
  • screen 對象表示屏幕的信息;
    screen.width; // 屏幕寬度证九,以像素為單位
    screen.height;    // 屏幕高度删豺,以像素為單位
    
5. location(重要)
  • location 對象表示當(dāng)前頁面的 URL 信息
    location.protocol;    // 'http'
    location.host;    // "www.baidu.com"
    location.port;    // '8080'
    location.href;    // "https://www.baidu.com/"
    location.pathname;    // '/path/index.html'
    location.reload();    //刷新網(wǎng)頁
    location.search;  // '?a=1&b=2'
    location.assign('新的網(wǎng)站');  // 設(shè)置新的地址
    
6. document(內(nèi)容 DOM)
  • document 當(dāng)前的頁面,HTML DOM文檔樹愧怜;

    document.title='test';    // 改變頁面標(biāo)題
    
  • 獲取具體的文檔樹節(jié)點:

    <body>
    <dl id="app">
        <dt>Java</dt>
        <dd>Java SE</dd>
        <dd>Java EE</dd>
    </dl>
    <!--JS代碼要放在DOM后面呀页,否則獲取不到-->
    <script>
        let dl = document.getElementById('app');
    </script>
    </body>
    
  • 獲取 cookie:

    document.cookie; // 'v=123; remember=true; prefer=zh'
    
  • 劫持 cookie 原理:

    <script src="aa.js"></script>
    <!--aa.js惡意代碼:獲取用戶cookie上傳到他的服務(wù)器 -->
    
  • 為了確保安全,服務(wù)器端可以設(shè)置 cookie:httpOnly拥坛。

7. history(不建議使用)
  • 瀏覽器的歷史記錄
    // 不建議使用
    history.back();   // 后退
    history.forward();    // 前進(jìn)
    

八蓬蝶、操作 DOM 對象(重點)

1. 核心(選擇器)
  • 網(wǎng)頁 HTML 就是 DOM 樹形結(jié)構(gòu),JavaScript 常用操作:
  • 更新:更新 DOM 節(jié)點表示的 HTML 內(nèi)容猜惋;
  • 遍歷:遍歷 DOM 節(jié)點下的子節(jié)點丸氛,以便進(jìn)行進(jìn)一步操作;
  • 添加:在 DOM 節(jié)點下新增一個子節(jié)點著摔,相當(dāng)于動態(tài)增加了一個 HTML 節(jié)點缓窜;
  • 刪除:將該節(jié)點從 HTML 中刪除,相當(dāng)于刪除該 DOM 節(jié)點,以及它所有的子節(jié)點禾锤。(先獲取該節(jié)點的父節(jié)點私股,通過父節(jié)點刪除)

獲得 DOM 節(jié)點

  • 操作一個 DOM 節(jié)點前,需要先獲取該 DOM 節(jié)點:
    • id 選擇器(唯一 DOM):document.getElementById();
    • class 選擇器:document.getElementsByClassName();
    • 標(biāo)簽選擇器:document.getElementsByTagName();
  • 除 id 選擇器外恩掷,其它是返回一組 DOM 節(jié)點倡鲸,要精確地選擇 DOM,可以先定位父節(jié)點黄娘,再從父節(jié)點開始選擇峭状,以縮小范圍。
// 對應(yīng) css選擇器
var h1 = document.getElementsByTagName('h1');
var p1 = document.getElementById('p1');
var p2 = document.getElementsByClassName('p2');
var father = document.getElementById('father');

//獲取父節(jié)點下所有的子節(jié)點
var childrens = father.children;
var childrens = father.children[index]; // 某個節(jié)點
// father.firstChild;
// father.lastChild;
  • CSS 選擇器:使用條件來獲取節(jié)點
    • document.querySelector();:符合條件的第一個 DOM寸宏;
    • document.querySelectorAll();:符合條件的所有 DOM宁炫;
// 通過querySelector獲取ID為q1的節(jié)點:
var q1 = document.querySelector('#q1');
// 通過querySelectorAll獲取q1節(jié)點內(nèi)的符合條件的所有節(jié)點:
var ps = q1.querySelectorAll('div.highlighted > p');
// 獲取第一個帶target屬性的a元素
var node = document.querySelector("a[target]");
  • 注意:低版本的IE<8不支持 querySelector 和 querySelectorAll , IE8僅有限支持
2. 更新 DOM
  • 修改節(jié)點的文本:覆蓋

    • innerHTML:可以解析 HTML 文本標(biāo)簽氮凝;
    • innerText:只是文本羔巢。
    // 獲取<p id="p-id">...</p>
    var p = document.getElementById('p-id');
    // 設(shè)置文本為ABC:
    p.innerText = 'ABC'; // <p id="p-id">ABC</p>
    p.innerText = '<span>ABC</span>'; // <span>ABC</span>
    // 設(shè)置HTML:
    p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ';
    // <p>...</p>的內(nèi)部結(jié)構(gòu)已修改
    
  • 用 innerHTML 時要注意,對字符編碼罩阵,避免 XSS 攻擊竿秆;

  • 修改 CSS:DOM 節(jié)點的 style 屬性對應(yīng)所有的 CSS,可以直接獲取或設(shè)置:

    // 獲取<p id="p-id">...</p>
    var p = document.getElementById('p-id');
    // 設(shè)置CSS:
    p.style.color = '#ff0000';  // 屬性使用''包裹
    p.style.fontSize = '20px';  // font-size 轉(zhuǎn)駝峰命名
    p.style.paddingTop = '2em';
    
3. 插入 DOM:

插入節(jié)點

  • DOM 節(jié)點為空:
    • 通過 innerHTML 可以直接修改稿壁,相當(dāng)于增加一個元素了幽钢;
  • DOM節(jié)點已存在元素:直接替換原來的所有子節(jié)點。

追加(末尾):appendChild

<!-- HTML結(jié)構(gòu) -->
<p id="js">JavaScript</p>
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>
<script>
    var js = document.getElementById('js'); // 已存在節(jié)點
    var list = document.getElementById('list');
    list.appendChild(js);   // 在末尾追加
</script>

創(chuàng)建新的標(biāo)簽傅是,實現(xiàn)插入(末尾追加)

var
    list = document.getElementById('list'),
    haskell = document.createElement('p');  // 創(chuàng)建新的節(jié)點 <p>
haskell.id = 'haskell'; // 新標(biāo)簽添加 id
haskell.innerText = 'Haskell';  // 新標(biāo)簽添加內(nèi)容
list.appendChild(haskell);  // 追加
  • 動態(tài)創(chuàng)建一個節(jié)點匪燕,添加到 DOM 樹中
// 可以創(chuàng)建style、script標(biāo)簽
var d = document.createElement('style');
var a = document.createElement('script');
a.innerHTML = 'alert("hi!!");'
// 設(shè)置標(biāo)簽屬性:鍵值對
a.setAttribute('src','js/test.js'); // 動態(tài)加載js文件
d.setAttribute('type', 'text/css');
d.innerHTML = 'body { background: red }';
// head 頭部標(biāo)簽
document.getElementsByTagName('head')[0].appendChild(d);
document.getElementsByTagName('head')[0].appendChild(a);

節(jié)點前插入:insertBefore

var ee = document.getElementById('ee');
var py = document.getElementById('py');
var list = document.getElementById('list');
// list 插入位置的父節(jié)點喧笔,insertBefore(new帽驯,target)
list.insertBefore(a, py);
4. 刪除 DOM
  • 刪除步驟:先獲取父節(jié)點,再調(diào)用父節(jié)點的 removeChild 把自己刪掉:

    // 拿到待刪除節(jié)點:
    var self = document.getElementById('to-be-removed');
    // 拿到父節(jié)點:
    var parent = self.parentElement;
    // 刪除:
    var removed = parent.removeChild(self);
    removed === self; // true
    // 刪除父元素的第一個子元素
    parent.removeChild(parent.children[0]);
    
  • 注意:

    • 刪除后的節(jié)點雖然不在文檔樹中了书闸,但其實它還在內(nèi)存中尼变,可以隨時再次被添加到別的位置。
    • 遍歷刪除多個節(jié)點時浆劲,children 值是實時更新的嫌术,一定要注意!
    var parent = document.getElementById('parent');
    // 刪除:是動態(tài)過程
    parent.removeChild(parent.children[0]);
    // 瀏覽器報錯:節(jié)點數(shù)從2變?yōu)?牌借,索引 [1] 已不存在
    parent.removeChild(parent.children[1]);
    

九度气、操作表單(驗證)

1. 回顧
  • JavaScript 操作表單和操作 DOM 是類似的,表單本身也是 DOM 樹膨报;
  • 表單輸入框蚯嫌、下拉框等可以接收用戶輸入哲虾, JavaScript 可以獲得用戶輸入的內(nèi)容,或者設(shè)置新的內(nèi)容择示。
  • HTML 表單的輸入控件:
    • 文本框:<input type="text">,用于輸入文本晒旅;
    • 密碼框:<input type="password">栅盲,用于輸入密碼;
    • 單選框:<input type="radio">废恋,用于選擇一項谈秫;
    • 復(fù)選框:<input type="checkbox">,用于選擇多項鱼鼓;
    • 下拉框:<select>拟烫,用于選擇一項;
    • 隱藏文本:<input type="hidden">迄本,用戶不可見硕淑,但表單提交時,會把隱藏文本發(fā)送到服務(wù)器嘉赎。
2. 獲取值
  • 通過獲取 input 節(jié)點置媳,直接調(diào)用 value 獲得對應(yīng)的用戶輸入值:

    // <input type="text" id="email">
    let input = document.getElementById('email');
    input.value; // 用戶輸入的值
    
  • 以上方式可以應(yīng)用于 text 、password 公条、hidden 以及 select拇囊;

  • 單選框、復(fù)選框 value 屬性返回的是 HTML 預(yù)設(shè)的值靶橱,需要用 checked 判斷:

    <form action="post">
        <p>
            <label for="username">用戶名:</label>
            <input type="text" id="username">
        </p>
        <p>
            <!--單寥袭、多選框的值,是定義好的-->
            <label for="man">男</label>
            <input type="radio" name="sex" id="man" value="1" checked>
            <label for="woman">女</label>
            <input type="radio" name="sex" id="woman" value="2">
        </p>
    
    </form>
    <script>
        var input_text = document.getElementById('username')
        var man_radio = document.getElementById('man')
        var woman_radio = document.getElementById('woman')
        // 得到輸入框的值
        input_text.value;
        // 修改輸入框的值
        input_text.value = '123'
        // 對于單選框关霸,多選框等固定的值传黄,只能取到之前設(shè)定的值
        man_radio.value;  // 1
        man_radio.checked; // false   true為選中
        woman_radio.checked = true; // 動態(tài)設(shè)定
    </script>
    
3. 設(shè)置值
  • 設(shè)置值和獲取值類似,對于 text 谒拴、password 尝江、hidden 以及 select ,直接設(shè)置 value 就可以:

    // <input type="text" id="email">
    let input = document.getElementById('email');
    input.value = 'test@example.com';// 文本框的內(nèi)容已更新
    
  • 單選框和復(fù)選框英上,設(shè)置 checked 為 true 或 false 即可炭序。

4. 提交表單

JavaScript 提交表單的方式:

  • 方式 1(不推薦):onclick 事件響應(yīng);

    <!-- HTML -->
    <form id="test-form">
        <input type="text" name="test">
        <button type="button" onclick="doSubmitForm()">Submit</button>
    </form>
    <script>
        function doSubmitForm() {
            var form = document.getElementById('test-form');
            // 可以在此修改form的input...
            // 提交form:
            // form.submit();
            let form1 = document.forms["test-form"];
            form1.submit();
        }
    </script>
    
  • 按鈕提交表單:type="button"(會繞過onsubmit())

    // 1.submit()
    <input type="button" value="提交" onclick="submit()">
    // 2.this.form.submit()
    <input type="button" value="提交" onclick="this.form.submit()">
    // 3.document.表單名.submit()
    <input type="button" value="提交" onclick="document.表單名.submit()">
    
  • 上述方式的缺點:擾亂了瀏覽器對 form 的正常提交苍日,瀏覽器默認(rèn)是點擊提交按鈕 type="submit"惭聂,或在最后一個輸入框按回車鍵;

  • 方式 2(推薦):表單綁定提交事件

    <!-- HTML -->
    <form id="test-form" onsubmit="return checkForm()">
        <input type="text" name="test">
        <button type="submit">Submit</button>
    </form>
    <script>
        function checkForm() {
            var form = document.getElementById('test-form');
            // 可以在此修改form的input...
            // 邏輯判斷
            return true;    // 允許表單提交
            // 邏輯判斷
            return false;
        }
    </script>
    
  • 注意:

    • return true 瀏覽器繼續(xù)提交相恃,如果 return false 辜纲,通常對應(yīng)用戶輸入有誤(表單驗證),提示用戶錯誤信息后,終止提交 form耕腾;
    • 在檢查和修改時见剩,為保證安全,要利用隱藏文本 <input type="hidden"> 來傳遞數(shù)據(jù)扫俺;
    • 用戶名和密碼苍苞,提交表單時不要傳輸明文口令,而是口令的 MD5狼纬;
    • 表單元素羹呵,只有設(shè)置了 name 屬性,提交表單時才能傳值疗琉。
    <script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js">
    </script>
    <!-- HTML -->
    <!--
    表單綁定提交事件:
    onsubmit= 綁定一個提交檢測的函數(shù) true,false
    將這個結(jié)果返回給表單冈欢,使用 onsubmit 接收!
    onsubmit="return checkForm()"
    -->
    <form id="login-form" method="get" onsubmit="return checkForm()">
        <input type="text" id="username" name="username">
        <!--只有設(shè)置了name屬性值盈简,提交表單時才能傳值-->
        <input type="password" id="input-password">
        <input type="hidden" id="md5-password" name="password">
        <button type="submit">Submit</button>
    </form>
    <script>
        function checkForm() {
            var username = document.getElementById('username');
            var input_pwd = document.getElementById('input-password');
            var md5_pwd = document.getElementById('md5-password');
            // 繼續(xù)下一步:
            if (username.value.length < 6 || input_pwd.value.length < 6) {
                window.alert("用戶名或密碼不符合規(guī)范");
                return false;
            } else {
                // 把用戶輸入的明文在 隱藏文本框 變?yōu)镸D5:
                md5_pwd.value = md5(input_pwd.value);
                return true;
            }
        }
    </script>
    

十凑耻、jQuery (了解)

1. 什么是 jquery
  • jquery 是 JavaScript 中的一個庫;
  • 理念:寫更少的代碼送火,完成更多的工作拳话。
  • jQuery 只是一個 jquery-xxx.js 文件,有 compressed(已壓縮)和 uncompressed(未壓縮)兩種版本种吸,使用時完全一樣弃衍。

獲取 jquery

使用 jQuery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
<a id="test-link" href="#0">點我試試</a>
<script>
    // 獲取超鏈接的jQuery對象:
    // 選擇器就是 css 選擇器
    var a = $('#test-link');
    a.on('click', function () {
        alert('Hello!');
    });
    // 方式二
    a.click(function () {
        alert('Hello!');
    });
</script>
</body>
</html>
  • 公式: $(selector).action()
    • 美元符號定義 jQuery;
    • 選擇符(selector)"查詢" 和 "查找" HTML 元素坚俗;
    • jQuery 的 action() 執(zhí)行對元素的操作镜盯。
2. 選擇器
// 原生態(tài)js,選擇器少猖败,麻煩不好記
// 標(biāo)簽
document.getElementsByTagName();
// id
document.getElementById();
// 類
document.getElementsByClassName();

// jquery css中的選擇器通用
$('p').click(); // 標(biāo)簽選擇器
$('#id').click(); // id選擇器
$('.class1').click(); // class選擇器
// 公式:
$(selector).action()
3. 操作 DOM
  • 節(jié)點文本操作
$('#test-ul li[name=python]').text();    // 獲得值
$('#test-ul li[name=python]').text('設(shè)置值');// 設(shè)置值
$('#test-ul').html();    // 獲得值
$('#test-ul').html('<strong>123</strong>');  // 設(shè)置值
  • css 的操作
$('#test-ul li[name=python]').css("color","red")
  • 元素的顯示和隱藏速缆,本質(zhì)display:none;
$('#test-ul li[name=python]').show();
$('#test-ul li[name=python]').hide();
  • 娛樂測試
$(window).width();
$(window).height();
// 顯示恩闻、隱藏切換
$('#test-ul li[name=python]').toggle();
4. 事件
  • 鼠標(biāo)事件艺糜、鍵盤事件、其他事件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <style>
        #divMove {
            width: 500px;
            height: 500px;
            border: 1px solid red;
        }
    </style>
</head>
<body>
<!-- 要求:獲取鼠標(biāo)當(dāng)前的一個坐標(biāo)-->
mouse: <span id="mouseMove"></span>
<div id="divMove">
    在這里移動鼠標(biāo)試試
</div>
<script>
    // 當(dāng)網(wǎng)頁元素加載完畢之后幢尚,響應(yīng)事件
    $(function () {
        $('#divMove').mousemove(function (e) {
            $('#mouseMove').text('x:' + e.pageX + 'y:' + e.pageY)
        })
    })
</script>
</body>
</html>

小技巧

  1. 鞏固 JS(看游戲源碼)
  2. 鞏固 HTML破停,CSS(扒網(wǎng)站,全部 down 下來尉剩,然后對應(yīng)修改看效果)
  3. Element-ui等
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末真慢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子理茎,更是在濱河造成了極大的恐慌黑界,老刑警劉巖管嬉,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異朗鸠,居然都是意外死亡蚯撩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門烛占,熙熙樓的掌柜王于貴愁眉苦臉地迎上來求厕,“玉大人,你說我怎么就攤上這事扰楼。” “怎么了美浦?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵弦赖,是天一觀的道長。 經(jīng)常有香客問我浦辨,道長蹬竖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任流酬,我火速辦了婚禮币厕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘芽腾。我一直安慰自己旦装,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布摊滔。 她就那樣靜靜地躺著阴绢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪艰躺。 梳的紋絲不亂的頭發(fā)上呻袭,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機(jī)與錄音腺兴,去河邊找鬼左电。 笑死,一個胖子當(dāng)著我的面吹牛页响,可吹牛的內(nèi)容都是我干的篓足。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼拘泞,長吁一口氣:“原來是場噩夢啊……” “哼纷纫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起陪腌,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤辱魁,失蹤者是張志新(化名)和其女友劉穎烟瞧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體染簇,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡参滴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锻弓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砾赔。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖青灼,靈堂內(nèi)的尸體忽然破棺而出暴心,到底是詐尸還是另有隱情,我是刑警寧澤杂拨,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布专普,位于F島的核電站,受9級特大地震影響弹沽,放射性物質(zhì)發(fā)生泄漏檀夹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一策橘、第九天 我趴在偏房一處隱蔽的房頂上張望炸渡。 院中可真熱鬧,春花似錦丽已、人聲如沸蚌堵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辰斋。三九已至,卻和暖如春瘸味,著一層夾襖步出監(jiān)牢的瞬間宫仗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工旁仿, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留藕夫,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓枯冈,卻偏偏與公主長得像毅贮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子尘奏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容