博客 / 詳情

返回

JavaScript入門乾貨:藍橋杯Web組分章學習筆記(基於藍橋雲課《JavaScript基礎入門》)

前言

最近整理代碼時,我翻看了前段時間備考藍橋杯Web組的練習代碼。當時,我是跟着藍橋雲課的《JavaScript 基礎入門》課程邊學邊敲的,因此本文涵蓋了該課程的大部分內容。我習慣將知識點、遇到的問題以及探究結果嵌入在代碼註釋中,註釋寫得非常細緻。

為了便於閲讀,我將代碼按1.1、1.2、2.1等章節分點整理,結構清晰、條理分明,讓大家能像讀文章一樣輕鬆理解代碼。現在,我將這些學習筆記分享給大家,希望能為JavaScript初學者提供幫助,順便心痛一下那300塊錢學費(

全文共800+行,乾貨滿滿!


正文

1.html

摘要

DOM事件:點擊,雙擊,移入,移出

DOM節點:為test.js裏的dom操作提供div目標

注意

請在瀏覽器或通過 Live Server 插件打開 1.html,確保 test.js 與 1.html 位於同一目錄並已引入,以運行JavaScript代碼。同時,1.html 中包含 test.js 的DOM操作所需的關鍵 div 元素。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 導航欄 -->
    <div class="navbar">
        <a    class="navbarButton" >首頁</a>
        <!-- 使用querySelectorAll返回的是一個靜態Nodelist,要設置color需要歷遍..nodelist是類數組型,有length屬性,但是沒有繼承所有的數組方法,以此來避免額外的性能開銷..也可以用靜態方法Array.from(變量名)轉換成數組
        nodelist的歷遍可以使用forEach方法,
        onmouseover="document.querySelectorAll('.navbarButton').forEach(e1 => e1.style.color = 'red')"-->
        
        <a   class="navbarButton">HTML</a>
        <a   class="navbarButton">CSS</a>
        <a   class="navbarButton">JavaScript</a>
        <a   class="navbarButton">關於</a>
        <a   class="navbarButton">幫助</a>
    </div>
    <!-- 主體 -->
    <div class="head1" id="head1">
        hahaha
    </div>
    <div class="forpro">
        <h1>輸出當前的時間:</h1>
        <div id="forpro_timer_divId" class="forpro_timer_divClass"></div>
        <div class="forpro_container_divClass" id="forpro_container_divId"></div>
    </div>
    <div class="dom_par" id="dom_parID" ></div>
    <div class="dom_onclick" style="background-color: #ee5844;margin: 0 0 0 0;">
        <p 
        style="margin: 0 0 0 0;" 
        onclick="this.innerHTML = '我愛學習,身體好好!'" 
        ondblclick="this.innerHTML = '我愛學習,身體好好好!'" 
        onmouseover="this.innerHTML = '你把鼠標移到了上面'"
        onmouseleave="
            this.innerHTML = '你把鼠標移開了';
            setTimeout(() => {
                this.innerHTML ='請點擊文本,雙擊該文本或把鼠標移動到上面';
            }, 1000);">
        請點擊文本,雙擊該文本或把鼠標移動到上面</p>
    </div>
    <!-- 這裏p是一個段落,內容會被margin撐大 -->
</body>
<style>
    /* 導航欄 */
    .navbar{
        background-color: #f5f5dc;
        display: flex;
        gap: 16px;
    }
    .navbarButton{
        text-decoration: none;
        color: #2424eb;
        display: flex;
        gap: 160px;
        font-size: 24px;
    }
 
    .navbarButton:active{
        background-color: red;
    }
    /* 主體 */
    .head1{
        /* width: 100%; */
        background-color: antiquewhite;
    }
    .forpro h1{
        margin: 0 0 0 0;
        background-color: #ffe793;
    }
    .forpro_timer_divClass{
        background-color: #ee5844;
        
    }
    .forpro_container_divClass{
        background-color: #a6e22e;
        height: 320px;
        overflow: auto;
    }
</style>
<script src="test.js" ></script> 
<!-- script最好放在最下面,防止dom找不到元素,或者用defer延遲執行腳本,知道文檔加載完畢才執行腳本
同時,放在下面時添加的標籤也是添加在下面 -->
</html>

test.js

摘要

變量:動態類型;命名規則
運算符:===;==;類型轉換
數組:創建;增刪;截取
字符串:查找;截取;替換
類型轉換:顯式;隱式
函數:聲明;自執行;嵌套
對象:字面量;原型鏈
JSON:鍵值對;無方法
內置對象:數組;日期;數學

DOM事件:點擊;雙擊;移入;移出
DOM節點:增刪改查
BOM:窗口控制;定時器
作用域:函數級;無塊級
閉包:保留變量
函數進階:this綁定;參數處理

注意

以下是 test.js 的代碼,依賴 1.html 中的 div 元素進行DOM操作,請通過 1.html 運行。

//1.1 變量
console.log("hello world");
var name = "實驗樓";
// 變量必須以字母,下劃線,美元符號$頭,不能以數字開頭
//大小寫區分
//動態類型語言,不需要指定變量將包含什麼類型
//給一個帶引號的值,就是字符串."1"也是字符串,可以用typeof查看類型
 
/*1.2 運算符
不等於!==
1
*/
 
/*1.3 數組
創建並賦值數組*/
//var myarray = new Array[1 ,2 ,3 ,4 ,5];
var myarray = [1 ,2 ,3 ,4 ,5];
// 多維數組
var student = [
    ["張三" ,"男" ,"18"],
    ["李四" ,"男" ,"220"]
    ];
student[0][2];
//獲取數組長度
var len_stu = student.length;
console.log(len_stu);
//將字符串轉化為數組--對字符串使用split()方法
"1:2:3:4".split(":");
"a|b|c".split("|");
//將數組轉化為字符串——對數組使用join()方法
myarray.join(":");
myarray.toString();     //也可以使用tostring方法來轉換,但是無法指定分隔符,只能是逗號
console.log(myarray);
//在數組尾部添加一個或多個元素,使用push()方法
var arr = ["1" ,"2" ,"3" ,"4"];
arr.push("5" ,"6");
console.log(arr);
// 刪除數組的最後一個元素,並把數組的長度減1,用pop()方法
arr.pop();
console.log(arr);
//如果數組為空則不改變數組,然後返回undefined值
var arr_b = [];
arr_b.pop();
console.log(arr_b ,typeof(arr_b));
//在開頭添加,用unshift。刪除開頭,用shift
 
//1.4 無
//==,相等操作符,比較值是否相等,不比較類型
/*===,全等操作符,比較值和類型是否相等。
比如説,null和undefined的值相等,但是他們的類型不相等
undefined表示所有未賦值變量的默認值
null表示一個變量不在指向任何對象的地址
*/
 
//1.5字符串
//連接字符串,直接用+
//數字轉字符串,使用tostring
var myNum = 9123;
var myString = myNum.toString();
var hello_str = "Hello World";
console.log(typeof(myNum));
//獲取長度,繼續用length
console.log(myString.length);
//獲取字符串第一個字符
console.log(myString[0]);
//查找字符串是否包含某個字詞,沒找到會返回-1
/*str.indexOf(searchValue, fromIndex);
fromIndex,開始查找的位置,默認為0,fromIndex >= str.length,則返回-1
特殊情況:被查找的字符串為空字符串時,當 fromIndex <= 0 時返回 0,0 < fromIndex <= str.length 時返回 fromIndex,fromIndex > str.length 時返回 str.length
*/
myString.indexOf("9");
//從字符串當中提取用slice(strat,end)
var res1_myString =myString.slice(0,2);
console.log(hello_str);
//轉換大小寫
/*toLowerCase() ,全部轉化為小寫
toUpperCase() ,全部轉化為大寫
*/
var lowercase_hello = hello_str.toLowerCase();
console.log(lowercase_hello);
//替換字符串的某一部分,用replace,注意這個只能替換第一次出現的字符串,要替換的話要用全局替換方式
var replace_hello = hello_str.replace("World" ,"shiyanlou");
console.log(replace_hello);
console.log(hello_str.replace(/o/g ,"hello"));
 
//1.6轉換成字符串
//使用tostring()可以帶參,括號內是進制方式
//有的值沒有 toString() 方法,所以需要用 String(),比如 null 和 undefined
 
//1.7 任意值轉換成數值類型
//number()可以把任意值轉化成數值,如果將轉化的字符串裏面有一個不是數字的字符,則返回NaN(not a number)
//parseInt()把字符串轉化成整數,可帶兩個參數,(字符串 ,進制)
var num1 = "12";
console.log(parseInt(num1 ,2) ,typeof(num1));
//字符串轉換成浮點數,但是隻支持十進制數,如果內容只有整數,則解析成整數
console.log(parseFloat(num1));
//隱式類型轉換,執行-0操作。如果該字符串不是純粹的數字字符串,儘管在-0之後,它的數據類型變為number,但是其值為NaN
console.log(typeof("1221" - 0));
NoPureNumTransform = "abc" - 0;
console.log(typeof(NoPureNumTransform) ,NoPureNumTransform);
 
//1.8 轉換成布爾類型
console.log(Boolean(123));
//在控制語句,比如if當中,會將括號裏面的條件隱式轉換成布爾值
var message;    //這句語句中定義了一個messaage變量,但是沒有賦值,默認為undefined,它的布爾值為false
console.log(message);
if (message) {
    
}
else{
    console.log("false");
}
 
//2.1 條件
// 三元表達式 條件表達式?結果1:結果2
 
//2.2 循環
//continue使得當親一次循環下的下面的語句都不執行
 
//2.3 函數
//方法需要依附於對象使用比如説console.log,這是面向對象編程的一個體現
//常規法創建函數
RegularFunction(1 ,2);  //這樣寫沒問題,js會把當前作用域的函數聲明放到最前面
function RegularFunction(a ,b) {
    console.log(a + b);
}
//函數表達式創建函數,比如説上面的可以改編為
var FunExpressFunction = function (a ,b) {  /*但是如果用表達式法創建函數,這樣就和定義其他基本類型的邊框
                                            一樣,沒什麼特殊的,只會按順序執行,所以就不能把調用放在聲明
                                            前面,同時後面的這個function也是一個匿名函數,函數名就是
                                            變量名。要是想不命名直接調用,可以用自調用*/
    console.log(a + b);
}
FunExpressFunction(2 ,3);
//js當中,後定義的函數會覆蓋之前定義的函數
//如果函數中沒有返回值或者return後面沒有跟任何值,則默認返回undefined
//匿名函數的自調用,可以避免全局變量污染,原理:()()
(function () {
    console.log("self-calling!");
})();
 
//練習1:打印直角三角形
console.log("\n");
var TimesInp;
//TimesInp = prompt("請輸入三角形的行數");
 
//最好進行顯示類型轉換,保證邏輯嚴密
var goal = 10;//prompt("請輸入要打印的三角形行數");
goal = Number(goal);    //因為prompt獲取到的是字符串
console.log(typeof(goal));
if (goal > 10) {
    console.log("輸入的數字太大了" ,typeof(goal));
}
 
//3.1 json簡介
//在javascript裏面所有事物都是對象,字符串,數組,日期等
//屬性就是和對象相關的值,也可以理解為特徵
//方法就是在對象上執行的動作,也可以理解為行為
//例如,一輛汽車就是現實生活裏面的對象,它的名字,它的顏色,它的價格等特徵就是汽車對象的屬性。它能啓動,駕駛,加速剎車就是汽車對象的方法
 
//3.2 json格式
//json是一種輕量級的數據交換語言
//json源於JavaScript,其數據格式與語言無發熱,但是有許多語言都支持json
//json的文件擴展名是.json,官方的MIME類型是application/json
//注意:
//json是一種純數據格式,它只有屬性,沒有方法。
//json的屬性必須用“ ”引起來
//json要求兩頭有{}來使其合法
//可以把JavaScript對象原原本本的寫入json數據,比如説:字符串,數字,數組,布爾值,還有其他字面值對象
//層級關係:
/*可以用{
    [],[]
}
的形式實現多層嵌套,也就是以數組作為頂層結構,實現存放多個對象
也可以用對象存放對象或者混合的方式
{
    "student": [],
    "age": {}
}
*/
 
//3.3 常用內置對象
/*1.Array對象,
常用屬性:length,獲取數組的長度
常用方法:
concat() 方法,用於鏈接兩個或多個數組,並返回結果,語法為
arrayObject.concat(arrayX ,arrayY ,...);
例子:
*/
var ToConcat_a = [1 ,2 ,3];
var ToConcat_b = [4 ,5 ,6];
var ToConcat_c = ["one" ,"two" ,"three"];
console.log(ToConcat_a.concat(ToConcat_b ,ToConcat_c));    
//意思就是對象ToConcat_a使用了concat()方法拼接了字符串對象ToConcat_b ,ToConcat_c
//test:2025年1月8日16:45:05
//pop()方法:彈出,刪除並返回數組的最後一個元素。
//push()方法:拉長,向數組的末尾添加一個或多個元素,並返回拉長之後數組的長度
//reverse()方法:倒序,顛倒數組的順序,返回修改後的數組本身
//shift()方法:移除,刪除並返回數組的第一個元素,先進先出,隊列,其他的元素向前移動.
    /*注:隊列:有順序,按時間處理的系統,確保了請求和任務處理的公平性,更符合人類直覺.
    在C語言中如果要這樣操作,那就需要更改每個位置的元素,所以我們給數組添加順序一般添加到 末尾,為什麼JavaScript能這樣?答:JavaScript的數組是動態分的,數組元素在內存中的位置不一定是連續的.數組是對象,對象的屬性時可以動態改變的.除外,JavaScript 提供了對數組的高級抽象,背後處理了很多底層細節。可以讓開發者不必考慮一些底層問題
    */
//unshift()方法:移除的反義詞,添加,向數組的開頭添加一個或多個元素,並返回新的長度
//slice()方法:切片,從數組中提取一部分並返回。其中start的值是必需的,規定從何處開始選取。可以為負數。end的值是可選的,規定從何處結束選取,如果沒有設置,默認為從start開始選取到數組後面的所有元素。該方法不會修改數組,只會返回值
var slice_a =[1 ,2 ,3 ,4 ,5 ,6];
console.log(slice_a.slice(2 ,5));
//splice()方法,拼接剪接,用於刪除或替換當前數組的某些項目.語法為arrayObject.splice(start ,deleteCount ,options);
                                            //其中start的值是必需的,規定刪除或替換項目的位置
                                            //deleteCount的值是必需的,規定要刪除的項目數量,如果設置為0,則不會刪除項目
                                            //option的值是可選的,規定替換它的新項目
                                            //和slice()方法不同的是,splice()方法會修改項目
var splice_s = [1 ,2 ,3 ,4 ,5, 6];
splice_s.splice(2 ,2 ,"abc");   //012從序號為2的元素開始刪,刪兩個,然後把刪掉的部分替換為"abc"
//sort()方法,排序,會改變原始數組!,語法為arrayObject.sort(sortby).其中sortby這個參數可選,參數必須為函數,在這個函數中,傳入a和b的值,若傳出的結果為大於零的數字,則説明前者比後者更靠前。沒參數的話,默認按字符編碼排序
var sort_arr1 = ["a" ,'z' ,'k' ,'w' ,'x'];
document.write( 
    `<div class ="sort_arr1_resultDiv" style="background-color : lightblue";>
    ${sort_arr1}
    </div>`  );   //注:write方法只能在加載過程中使用,如果使用了defer標籤,現代瀏覽器禁止在文檔加載完成後使用document.write
document.getElementById("head1").innerHTML += 
    `<div class ="sort_arr1_resultDiv" style="background-color : #007acc";>
    ${sort_arr1.sort()}
    </div>`
//數字排列-從小到大
function sortNum_ByOlder(a ,b){
    return a - b;   //從小到大排序
}
function sortNum_ByOlderRev(a ,b){
    return b - a;   //從大到小排序,(b - a)相對於(a - b)來説是絕對值
}
var sort_arr2 = [11 ,55 ,22 ,44 ,66 ,33];
let sort_arr2_div = document.createElement('div');
sort_arr2_div.className = "sort_arr2_divClass";
sort_arr2_div.style.backgroundColor = "#a47aee";
sort_arr2_div.innerHTML += (sort_arr2.sort(sortNum_ByOlder) + "<br \>"  );
document.body.appendChild(sort_arr2_div);
//數字排序-從大到小
var sort_arr4 = [1 ,22 ,44 ,6 ,55 ,5 ,2 ,4 ,66];
let sort_arr4_div = document.createElement('div');
sort_arr4_div.className = "sort_arr4_divClass";
sort_arr4_div.style.backgroundColor = "#8eaa85";
sort_arr4_div.innerHTML += (sort_arr4.sort(sortNum_ByOlderRev) + "<br \>");
document.body.appendChild(sort_arr4_div);   //  appendchild後面放DOM元素
//toString()方法,把數組轉化為字符串,並返回結果
 
/*2.String對象 
常用屬性:length,獲取字符串長度*/
//charAt()方法,獲取指定位置處的字符.StringObject.charAt(index);index是下標.字符串的第一個字符的下標是0.如果參數不在0與String.length之間,該方法則返回一個空字符串
var charAt_str = "Hello World!";
let charAt_str_div = document.createElement('div');
charAt_str_div.className = "charAt_str_divClass";
charAt_str_div.style.backgroundColor = "#7762c8";
charAt_str_div.innerHTML += (charAt_str.charAt(2) + "<br \>");
document.body.appendChild(charAt_str_div);
//conct()方法,連接字符串,等效於“+”,“+”,更常用,與數組中的concat()方法類似
var concatstr_a = "hello world!";
var concatstr_b = "shiyanlou";
console.log(concatstr_a.concat(concatstr_b));
//slice()方法,提取字符串的片段,並在新的字符串中返回被提取的部分
//indexof()方法,檢索字符串
//toString()方法,返回字符串
//toLowerCase()方法,把字符串轉換為小寫
//toUpperCase()方法,把字符串轉換為大寫
//replac()方法,替換字符串中的某些部分
//split()方法,把字符串分割為字符串數組
 
/*3.Data對象 */
//Date()方法,返回當前的日期和時間
//getDate()方法,從Date對象中返回一個月中的某一天(1-31)
//getDay()方法,從Date對象中返回一週中的某一天(1-6)
//getMonth()方法,從Date對象中返回月份(0-11)
//getFullYear()方法,從 Date對象中以四位數字返回年份
//getHours()方法,返回Date對象的小時(0-23)
//getMinutes()方法,返回Date對象中的分鐘(0-59)
//getSecond()方法,返回Date對象中的秒數
//getMilliseconds()方法,返回Date對象中的毫秒(0-999)
 
/*4.Math對象
常用屬性:*/
//E屬性,返回常數e(2.7118281828...)
console.log(Math.E.toPrecision(100) ,Math.PI.toFixed(100));
//LN2屬性,返回2的自然對數ln2
//LN10屬性,返回10的自然對數ln10
//LOG2E屬性,返回以2為底的e的對數(log2e)
//LOG10E屬性,返回以10為底的e的對數(log10e)
//PI屬性,返回π
//SQRT1_2屬性,返回1/2的平方根
//SQRT2屬性,返回2的平方根
/*常用方法: */
//abs(x)方法,返回x的絕對值
//round(x)方法,返回x四捨五入後的值
//sqrt(x)方法,返回x的平方根
//ceil(x)方法,返回大於等於x的最小整數.ceil天花板向上取整
//floor(x)方法,返回小於等於x的最大整數,floor地板向下取整
//sin(x)
//cos(x)
//tan(x)
//acos(x)
//asin(x)
//atan(x)
//exp(x),exponential指數,返回e的x次冪
//pow(n,m),返回n的m次冪
//log(x)
//max(a ,b),返回a,b中較大的的數
//min(a ,b),返回a,b中較小的數
//random(),返回大於0小於1的一個隨機數
console.log(Math.random().toPrecision(50));
 
//3.4 創建對象和訪問對象
//1.通過對象字面量來創建
var literal_student = {
    name:"zhangsan" ,
    age: 18 ,
    gender: "male",
    sayHi: function (params) {
        console.log("hi , my name is " + this.name);
    },
};
//在控制枱輸入student.gender可以調用對象的屬性,輸入student.sayHi()可以調查用對象的方法
//通過上面的例子你會發現對象的屬性和方法都通過"."來調用
//2.通過new Object()創建對象
var newObject_student = new Object();
(newObject_student.name = "zhangsan"),
(newObject_student.age = 10),
(newObject_student.gender = "male"),
(newObject_student.sayHi = function (params) {
    console.log("hi,my nane is" + this.name);
});
//3.通過工廠函數創建對象
function createStudent(name ,age ,gender){  //定義了一個名字叫createStudent的工廠函數。這個函數用來創建和返回一個新的對象
    var factory_student = new Object(); /*創建了一個空對象factory_Student..new Object()會返回一個空對象
                                        
                                        工廠函數是手動在函數體裏面使用new var了一個對象,然後再用return返回了回去(但是也可以在調用的時候在函數名前面加上new關鍵字來自動創建並綁定),而且由於是在函數體裏面創建並返回的,所以每個傳入並創建的對象都有獨立的內存空間,會比較佔內存,如果在工廠函數中定義方法,每個對象實例都會有一份獨立的副本,導致較高的內存佔用..因此,工廠函數適用於簡單的對象創建,但是在需要大量對象共享方法的情況下,使用構造函數+prototype會更加高效
                                    
                                        */
    
    factory_student.name = name;    //將傳入的值賦值給
    factory_student.age = age;
    factory_student.sayHi = function (params) {
        console.log("hi,my name is" + this.name);   //this.name會引用當前對象的name屬性
    };
    return factory_student;    //注意返回值..用於返回創建的學生對象
}
var factory_s1 = createStudent("zhangsan" ,18 ,"male");
//4.自定義構造函數來創建對象
function custom_student(name ,age ,gender){ //創建了一個函數,傳入name,age,gender
    this.name = name;   
    this.age = age;
    this.gender = gender;
    this.sayHi = function (params) {
        console.log("hi ,my name is " + this.name);
    }
}
var s1 = new custom_student("zhangsan" ,18 ,"male");   //當使用關鍵字new調用一個函數是,會自動創建一個新對象並綁定到this上
 
//3.5 prototype屬性
//什麼是prototype?  這是一個屬性,指向一個對象,這個對象可以用來存儲共享的屬性和方法,從而實現對象實例之間的複用..
//每個函數(包括構建函數在創建時,都會自動創建一個prototype屬性,該屬性指向一個空對象,這個對象的是用來存儲可以被共享的屬性和方法
 
//3.6一些關鍵字 
//1.new關鍵字
//構建函數是一種很特殊的函數.主要用來在創建對象時初始化對象,即為對象成員賦初值,總與new運算符一起用在創建對象的語句中.這裏有特別注意的幾點:
//*構建函數用於創建一類對象,首字母要大寫
//*內部使用this關鍵字給對象添加初值
//*使用new關鍵字調用對象構造函數
 
//2.this關鍵字
//誰調用this,它就是誰
//函數在執行this時2是不確定的,只有在調用的時候才可以確定
//普通函數被直接調用時(不是通過對象的方法,或者特定綁定),函數內部的this默認指向全局變量.在瀏覽器環境中,全局變量就是Window
function DefultThis_test(){
    console.log(this);
}
//當函數被作為一個對象的方法被該對象調用時,那麼this指向的就是該對象
//構造函數中的this,始終是new的當前對象
 
//3.7 歷遍對象的屬性
//通過for...in語句用於歷遍數組或者對象屬性,對數組或對象屬性進行循環操作
var cycle_student ={
    name :"zhangsan",
    age :18,      //之所以不使用"",是因為儘管有強制類型轉換,但是當使用+運算符的時候,仍然會視為拼接而不是加法,因此應該要明確類型
    gender :"male"
};
/*for循環用法:for..in是專門設計用於對象屬性遍歷的結構,結構為定義一個循環變量用於某個對象,歷遍對象中的可枚舉屬性,並將對象的每個屬性名依次賦值給循環變量,然後依次執行循環體
for (var key in object) {
    // 在每次迭代時,key 是對象中的一個屬性名
    // 通過 object[key] 可以訪問對應屬性值
}
相比於for循環,for..in會自動完成初始化,條件判斷,更新操作..
*/
console.log("before delete:");
 
for (var cycle_key in cycle_student){   /*
                                        注:cycle_key是一個變量,當中存儲的是該對象的所有屬性的名字*/
 
    console.log("cycle_student." +cycle_key +":" +cycle_student[cycle_key]);
}
 
//3.8 刪除對象的屬性
//使用delete操作符刪除對象的屬性
//delate返回true或flase,被delete的對象不存在時也會返回true,只有對象存在而且有DontDelete屬性時才返回flase
console.log("after delete:");
delete cycle_student["name"]; //naem(不加引號)會被認為是一個變量,找不到變量就會刪不了..而不加引號表示這是一個屬性的名字
delete cycle_student.age;   //也可以用點語法
for (var cycle_key in cycle_student){   /*
                                        注:cycle_key是一個變量,當中存儲的是該對象的所有屬性的名字*/
 
    console.log("cycle_student." +cycle_key +":" +cycle_student[cycle_key]);
}
 
//3.9 寫一個函數,格式化日期對象,最終輸入形式為:yyyy/MM/dd HH:mm:ss。
//這裏再詳細講解一下date對象。
//在賦值的時候可以new一個date對象,
// 當Date(),也就是沒有傳入值的時候,此時的return值類似"2025-01-17T13:48:42.491Z"..當有傳入值的時候,會把參數格式化為上面的形式
var format_date_Milliseconds = 0;
var format_date_date = new Date();
function format_date() {
    format_date_date = new Date();
    var format_date_year = format_date_date.getFullYear();
    var format_date_mouth = (format_date_date.getMonth() + 1).toString().padStart(2 ,'0');  //pad填充padding,start在開頭,padstart在開頭填充
    var format_date_day = format_date_date.getDate().toString().padStart(2 ,'0');
    var format_date_hour = format_date_date.getHours().toString().padStart(2 ,'0');
    var format_date_minute = (format_date_date.getMinutes()).toString().padStart(2  ,'0');  //toString()是方法,調用的時候必須加()*2
    var format_date_second = format_date_date.getSeconds().toString().padStart(2 , "0");
    format_date_Milliseconds = format_date_date.getMilliseconds().toString().padStart(3 ,"0")
    return (
      format_date_year +
      "/" +
      format_date_mouth +
      "/" +
      format_date_day +
      " " +
      format_date_hour +
      ":" +
      format_date_minute +
      ":" +
      format_date_second +
      "\t" +
      format_date_Milliseconds
    );
 }
console.log(format_date());
var forpro_i = 0;
var TextEncoder = document.createTextNode("過去了一毫秒");
var forpro_tiemout = setInterval(
    function(){
        
    if (format_date_date.getMilliseconds() != format_date_Milliseconds) {   //注意是!=
        document.getElementsByClassName("forpro")[0].appendChild(TextEncoder);
        }
        //因為多個元素可以共享同一個類名,所以通過元素名選擇的返回值就是一個數組,在使用是要指定數組的第幾個元素
        document.getElementById("forpro_container_divId").innerHTML += 
                                                                        `<pre> ${format_date()}</pre>  
                                                                        `;
        forpro_i++;
        document.getElementById("forpro_timer_divId").innerHTML = `<p style="font-size: 24px;margin:0 0 0 0;">你發呆了${forpro_i}秒</p>`;
        var forpro_container_div_scrollHeight = document.querySelector("#forpro_container_divId").scrollHeight;
        document.querySelector("#forpro_container_divId").scrollTop = forpro_container_div_scrollHeight;    //在css中,是通過.來選中class,表示該選擇器適用於所有擁有該類的元素..在css中,使用#來選中id
} ,1000
);
 
//3.10 總結
//這節課學習了常用的內置對象 Array對象,String對象,Date對象,Math對象
//還有創建和訪問對象
 
//4.1 web api
//瀏覽器是一個封裝較為完善的軟件,它給我們提供了操作瀏覽器功能和頁面元素的接口。在本節中,我們將對這些接口進行學習
//web api 是瀏覽器提供的一套操作瀏覽器功能和界面元素的api(bom和dom)。
 
//4.2 bom簡介
//browse Object model 瀏覽器對象模型,指的是由web瀏覽器暴露的所有對象組成的表示模型。bom和dom(document Object model文檔操作模型)不同,既沒有標準的實現,也沒有嚴格的定義,所以瀏覽器廠商可以自由地實現BOM
//作為顯示文檔的窗口,瀏覽器程序將其視為對象的分層集合。當瀏覽器分析文檔時,它將會創建一個對象的集合,以定義文檔,並詳細説明它應如何顯示。瀏覽器創建的對象稱為文檔對象,它是瀏覽器使用的更大對象集合的一部分。此瀏覽器集合對象統稱為瀏覽器對象模型或BOM
 
// BOM頂級對象window以及常用的操作方法
//window是瀏覽器的頂級對象,當調用Window下的屬性和方法時,可以忽略window
 
//對話框
//alert() 顯示帶有一段消息和一個確認按鈕的警告框
//prompt() 顯示可提示用户輸入的對話框
//confirm()顯示一段消息以及確認按鈕和取消按鈕的對話框
 
//頁面加載事件
//onload
window.onload = function () {
    //當頁面完成加載時執行
    //即當頁面完全加載所有內容時(包括圖像,腳本文件,css文件等),執行
};
//onunload
window.onunload = function (){
   
    //當用户完全退出頁面時執行
};
 
//獲取瀏覽器寬度
var window_width = window.innerWidth;   //窗口內部的寬度,包含瀏覽器窗口的內容寬度,包括滾動條的寬度,使用在需要獲取窗口的總可視寬度時
console.log(window_width + "\n" +
    document.documentElement.clientWidth + "\n" +   //獲取html文檔的寬度,即<html>的可見寬度,不包含滾動條的寬度,在當需要精確控制內容寬度而忽略滾動條時使用
    document.body.clientWidth);    //<body>元素的寬度,可能會被超寬元素撐大,不包含滾動條的信息
 
//獲取瀏覽器高度
var window_height =window.innerHeight;
console.log(window_height + '\n' +
            document.documentElement.clientHeight + '\n' +
            document.body.clientHeight);
 
//定時器
//setTimeout()方法,在指定的毫秒數到達之後執行指定的函數,只執行一次..
//clearTimeout()方法取消由setTImeout()方法設置的timeout
//創建一個定時器,2000毫秒後執行
var timerId = setTimeout(
    function(){
        console.log("Hello shiyanlou");
    } ,2000
);
//取消定時器的執行
clearTimeout(timerId);
 
// setInterval()方法,設定定時調用的函數,也就是可以按照給定的時間(單位毫秒)週期調用函數,
//clearInterval()方法,取消由setInterval()方法設定的timeout
//創建一個定時器,每隔兩秒調用一次
var timerId = setInterval(
    function(){
        var date = new Date();
        console.log(date.toLocaleDateString());
    } ,1
);
clearTimeout(timerId)
 
//4.3 DOM簡介
    //文檔對象模型(document Object Model,簡稱DOM),是W3C組織推薦的處理可拓展標誌性語言的標準編程接口。DOM定義了訪問HTML和XML文檔的標準。我們這裏主要學習HTML DOM。DOM可以吧HTML看成是文檔樹,通過DOM提供的API可以對樹上的節點進行操作
    //DOM能改變HTML輸出流:在JavaScript中,使用document.write("新設置的內容<p>標籤也可以生成</p>")可以直接像html輸出流寫內容
    document.write("<div style = 'background-color:#ce70d6'>新設置的內容<p style='margin:0 0 0 0;' id='p1'>標籤也可以生成</p></div>");
    //字符串中的雙引號會與hrml標籤的雙引號衝突..對此,可以是使用單引號'來包裹html標籤的屬性值,或者使用轉義,也就是用兩個\"p\包裹
//改變HTML內容,使用innerHTML屬性改變HTML內容.比如修改標籤p中的內容
document.querySelector("#p1").innerHTML = "hello 實驗樓";
//改變html屬性
document.querySelector("#p1").id = "p2";
try {
    document.querySelector("#p1").innerHTML = "hello ";
} catch (error) {
    console.log("發生錯誤,但已忽略:"  ,error); 
} //會報錯選不到,然後會影響後續代碼的執行
 
// DOM節點
    //根據W3C的html dom標準,html文檔中的所有內容都是節點:整個文檔就是一個文檔節點,而每個HTML標籤都是一個元素節點。html標籤中的文本則是文本節點,html標籤;則是屬性節點,一切都是節點
        //document-文檔節點-整個文檔 window.document
        //documenttype-文檔類型節點-文檔的類型
        //element-元素節點-html元素(比如<body><div>等)
        //attribute-屬性節點-html元素的屬性(比如class="right")
        //text-文本節點-html文檔中出現的的文本
        //documentfragment-文檔碎片節點-文檔的片段
 
//Dom節點的操作
//獲取節點
    //要操作節點,首先我們要找到節點.主要有以下三種方法:
        //1.通過id找到html元素
        //2.通過標籤名找到html元素:使用方法getELementByTagName()來選取元素..如果有多個同類型標籤那麼我們可以通過下標來確認,比如:
document.getElementsByTagName("div")[0];
//下標為[0]表示選取第一個div標籤,
document.getElementsByTagName("div")[1];
//下標為[1]表示選取第2個div標籤
        //3.通過類名來找到html標籤
            //使用方法getElementsByClassName()通過元素的類名來選取元素
console.log( document.getElementsByClassName("forpro_container_divClass"));
//返回包含class="name"的所有元素的一個列表
//DOM節點之間的關係
        //DOM的節點並不是孤立的,我們從DOM樹中可以看出,節點和節點之間存在相對關係,就如同一個家族一樣,有父輩,有兄弟,有兒子等.下面我們來看一下有哪些節點:
        //父節點 parentNode
        //兄弟節點 nextSibiling nextELementSibiling previousSibiling previousELementSibiling
        //子節點 firstChild firstELementChild lastChild lastELementChild
        //所有子節點 childNodes children
    //例如,在下面這個文檔中
    /*<html>
        <head>
            <title>DOM 節點演示</title>
        </head>
        <body>
            <h1>我是h1標籤</h1>
            <p>我是p標籤</p>
        </body>
    </html> */
        //<html>節點沒有父節點,它是根節點
        //<head>和<body>的父節點是<html>節點
        //文本節點 我是p標籤 的父節點是<p>節點
        //<html>節點有兩個子節點<head>和<body>
        //<h1>節點和<p>節點是兄弟節點,同時也是<body>的子節點
    //需要注意以下幾點:
        //childNodes 它是標準屬性,它返回指定元素的子元素集合,包括html節點,所有屬性,文本節點
        //children 非標準屬性,它返回指定元素的子元素集合.但讓只返回html節點,甚至不返回文本節點
        //nextSibiling和preViousSibiling獲取的是節點,獲取元素對應的屬性是nextELementSibiling和previousELementSibiling
        //nextELementSibiling和previousELementSibiling有兼容性問題,Ie9以後才支持
//DOM節點的操作
    //1.創建節點
        //創建元素節點,使用createELement()方法.比如
var dom_par = document.createElement("p");
        // 創建屬性節點,使用createAttribut()方法
var dom_par_attr = document.createAttribute("background-color:red");
dom_par.setAttribute("style" ,"margin:0 0 0 0");  //屬性是附加到元素節點上的,不屬於子節點,不能用append..append是用來插入子節點的..要用setAttribute()..而margin不是屬性名,是css的一個字符串,提到style的時候,後面要直接跟一個字符串作為樣式的參數。或者用點語法對創建出來的或選中的div的style進行修改
 
        //創建建文本節點,使用createTextNode()方法
var dom_par_node = document.createTextNode("hhh");
    //2.插入子節點
        // appendChild()方法向節點添加最後一個子節點
document.querySelector("#dom_parID").append(dom_par);   //appendChild是較早的api,兼容性強。但是一次只能添單一節點,而append可以添加多個節點,而且可以添加字符串文本
 
        //insertBefore(goal_node ,point_node)方法在指定的子節點前面插入新的子節點..如果第二個參數沒寫或者為null,則默認插入到後面
    //3.刪除節點
        //使用removeChild()方法.寫法為
        //父節點.removeChild(子節點);
        //node.parentNode.removeChild(node);    如果不知道父節點是什麼,可以用點語法獲取,也就是可以這樣寫
    //4.替換子節點
        //使用replaceChild()方法.語法為:
        //node.replaceChild(newnode ,oldnode)   //後面是被替換的目標
    //5.操作節點的屬性
        //獲取getAttribut(屬性名);
        //設置setAttribut(name ,value);
// dom_par.setAttribute(dom_par_attr)
        //刪除removeAttribut(name);
console.log(document.querySelector("#dom_parID").getAttribute("id"));
//DOM事件
    //事件的定義
        //在什麼時候執行什麼事
    //事件三要素
        //事件由事件源 +事件類型 +事件處理程序 組成
            //事件源:觸發事件的元素
            //事件類型:觸發事件的方法(比如鼠標點擊或鍵盤點擊)
            //事件處理程序:事件觸發以後要執行的代碼
    //常用的事件
        //onclick onclick鼠標單擊
        //ondbclick ondbclick鼠標雙擊
        //onkeyup onkeyup按下並釋放鍵盤上面的一個按鍵時觸發
        //onchange onchange文本內容或下拉菜單中的選項發生改變
        //onfocus onfocus獲得焦點,表示文本框等獲得焦點..配合失去焦點使用,可以做到僅在獲得焦點的時候顯示提示信息
        //onblur onblur失去焦點,表示文本框等失去焦點
        //onmouseover onmouseover鼠標懸停,即鼠標停留在圖片等的上方
        //onmouseout onmouseout鼠標移出,即離開圖片等所在的區域
        //onload onload網頁文檔加載事件
        //onunload 關閉網頁時
        //onsubmit 表單提交時
        //onreset 重置表單時
 
//5 值類型和引用類型及其異常
//5.1值類型和引用類型
    //值類型
        //以下變量中存儲的是對應的值,值和變量名都存儲在棧中
        //值類型又叫基本數據類型,原始類型,在JavaScript中值類型有以下五種
            //數據類型
            //布爾類型
            //undefined
            //null
            //字符串
var Primitive_num = 18;
var Primitive_flag = true;
var Primitive_un = undefined;
var Primitive_nu = null;
var Primitive_str = "zhangsan";
    //引用類型
        //引用類型又稱複合數據類型,在JavaScript中引用類型有以下三種
            //對象
            //數組
            //函數
        //引用類型存儲在堆中
        //變量名存儲在棧中,裏面的值是地址,指向存儲對象的內存處
var Reference_arr = [1 ,2 ,3];
var Reference_p = {
    name :"張三",
    age :18
};
 
//5.2 值類型和引用類型的特徵
    //值類型的特徵
        //值類型的值是不可變的,不可變指的是值類型指向的空間不可變,例如
var Primitive_a = 2;
/*JavaScript 在棧內存中為變量 a 分配空間,並將值 2 存儲在棧上的一個地址位置(假設是地址 A)。
然後a 變量現在指向這個地址 A,也就是存儲 2 的位置*/
Primitive_a += 2;
console.log(Primitive_a);
            //也就是a變量指向的地址值變了,但是內存中2的地址值沒有變
        //按值傳遞的變量之間互不影響,比如
var Primitive_b = Primitive_a;
/*JavaScript複製了一份a的值到其他地方,然後讓b指向這個地方 */
Primitive_a = Primitive_a + 2;
console.log(Primitive_a ,Primitive_b);
        //再看下面一段代碼
console.log(Reference_p.name ,Reference_p.age);
var Reference_p1 = Reference_p;
Reference_p1.name = "李四";
console.log(Reference_p.name ,Reference_p.age)
/*因為Reference型變量存儲的是地址,複製的時候也僅僅是把地址複製了一份,所以改變p1指向的對象的內容也改變了p指向的對象的內容。*/
function foo(o){
    o.age += 1; //注意,當數據類型為字符串時,哪怕用+=1,也是在字符串後面加上“1”這個字符
}
foo(Reference_p);
console.log(Reference_p.age);
/*同樣地當參數為引用類型時,函數內和函數外的兩個變量不同,但是共同指向同一個對象,在函數修改對象數據時會影響外部
注:其實我們可以這樣理解。引用數據類型中的地址是一把鑰匙,鑰匙指向的是寶藏,複製一把鑰匙後,兩把鑰匙打開的是同一個寶藏 */
 
//5.3 調試工具的使用
//在調試的時候,可以加一句console.log()語句來打印出來
    //設置斷點,逐步運行
        //設置斷點的方案很簡單,直接左鍵點擊代碼旁邊的數字行數
        //選中右鍵選擇將變量加入watch窗口,實時查看它的值的變化
        //然後刷新,點擊運行,可以逐段運行代碼
 
//5.4 異常處理
    //當出現錯誤時,JavaScript引擎通常會停止,並生成一個錯誤信息
    //異常捕獲
        //可以使用try-catch語句捕獲異常
try {
    //這裏寫可能出現異常的代碼
} catch (error) {   //給錯誤信息賦個形參
    //執行的代碼
}
        //注意:
            //語句try和catch是成對出現的
            //如果在try中遇到了錯誤,try裏面出現錯誤的語句後面的代碼都不執行,直接跳轉到catch中,catch處理錯誤的信息
            //如果try中沒有出現錯誤,則不會執行catch中的代碼,執行完try中的代碼直接執行後面的代碼、
            //在try或catch執行完以後,代碼會繼續執行,不會中斷
    //throw語句
        //通過throw語句,我們可以創建自定義錯誤。throw語句通常和try catch語句一起使用
 
        
 
 
//7 函數進階
//在前面的課程中,我們已經學習了一下這些函數的相關內容:函數聲明,函數表達式和function()構造函數,以及函數的參數,返回值,調用..現在我們將繼續學習函數進階的內容..
//7.1 call apply bind
    //在學習call(),apply(),bind()方法之前,我們先來複習一下this的指向性問題,我們前面説過一個口訣:誰調用this,它就指向誰..讓我們先來看一個例子
function this_foods() { }
this_foods.prototype = {
    price: "¥15",
    say: function () {
        console.log("My price is" + this.price);
    }
};
 
var this_apply = new this_foods();
this_apply.say();
var this_orange = new this_foods();
this_orange.say();
 
    //也就是説上述例子調用say()方法,最後打印的結果都是一樣的,但是如果我們想打印橘子的價格是10元呢?又不想重新定義say()方法..JavaScript為我們專門提供了一些函數方法來幫我們更優雅第處理函數this指向問題..這就是我們接下來要學習的call() ,apply() ,bind()三個函數方法
    //call
        //call()方法調用一個函數,其具有一個指定的this值和分別地提供的參數(參數的列表)..語法為
            //fun.call(thisArg ,arg1 arg2)
        //注: thisArg指的是在fun函數中指定的this的值..如果指定了null或者undefined,則內部的this指向window,同時,值為原始值(數字 ,字符串 ,布爾值)時,this會自動指向原始值,是一個可選項
            //arg1 ,arg2 ,...指定的參數列表,也是可選項
            //
            //call()允許為不同的對象分配和調用屬於一個對象的函數/方法..你可以使用call()來實現繼承:寫一個方法,然後讓另外一個新的對象來繼承它(而不是在新的對象中在寫一次這個方法)
        //1.使用call()方法調用函數並指定上下文的this..前面的例子可以寫成
        var this_apple = new this_foods();
        this_orange = {
            price: "¥10",
        }
        this_apple.say.call(this_orange);   //使用call讓console.log("My price is" + this.price);裏面的this指向this_orange
        //2.在一個子構造函數中,你可以通過調用父構造函數的call()方法來實現繼承
        //
    //apply
        //apply()方法和call()方案類似,唯一的區別是call()方法接受的是參數,apply()方法接受的是數組,語法為
        //fun.apply(thisArg ,[argsArray]);
        //例子:
var apply_array = ["a" ,"b" ,"c"];
var apply_nums = [1 ,2 ,3];
apply_array.push.apply(apply_array ,apply_nums);
//注:使用concat()方法鏈接數組,不會改變數組,而是創建一個新數組..而使用push()是接受可變數量的參數的方式來添加元素..使用apply則可以鏈接兩個數組..使用apply是為了將指定的數組變更為這兩個數組
console.log(apply_array);
    //bind
        //bind()方法創建一個新的函數(稱為綁定函數),在調用時設置this關鍵字作為提供的值
        //bind()方法用於綁定到一個函數,當綁定函數被調用時,參數thisArg會作為原函數運行時的this指向
//遞歸
//在函數中,遞歸就是自己直接或間接的調用自己
//例子:計算1到10之間 的整數相加的和
function recurrence_foo(n){
    if(n==0){
            return 0;
    }else{
        return n+recurrence_foo(n-1);
    }
}
var recurrence_a = recurrence_foo(10);
console.log(recurrence_foo(10));
console.log(recurrence_a);
 
//7.2 作用域
//作用域就是變量和函數的課訪問範圍
//在JavaScript中是沒有塊級作用域 的,即不會把{}擴在一起的代碼視為一個作用域,例如
{
    var block_num = 123;
    {
        console.log(block_num);
    }
}
console.log(block_num);
 
//7.3 閉包
//7.4 arguments對象
    //在函數代碼中,使用特殊對象argument,無需明確指出變量名,我們就能訪問它們..第一個參數是argument[0] ,第二個參數是argument[1] ,以此類推..比如:
function arguments_foo(params) {
    console.log(arguments[0]);  //取傳入參數的第一個
    console.log(arguments[1]);
}
arguments_foo(2 ,3);    //打印2 3
    //還可以用arguments對象檢測函數參數個數,引用argument.length即可..來看一個歷遍參數求和的例子
function arguments_add(){
    var arguments_sum = 0;
    for(var i = 0;i < arguments.length;i++){
        arguments_sum += arguments[i]; 
    }
    console.log("參數的個數為:" + arguments_sum);
}
arguments_add();    //0
arguments_add(1);   //1
arguments_add(1 ,2);    //3
arguments_add(1 ,2 ,3); //6
 
//7.5 function對象
    //function()對象創建函數的語法如下
    //var function_name = new Function(arg1 ,arg2 ,... ,argN ,Function_body)
    //注意:每個參數都必須是字符串,Function_body是函數主體..
    //直接new一個Function出來,直接把參數和函數體都塞進去

希望這些筆記對你有所幫助,感覺不錯的話,動手點個贊吧,祝學習順利。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.