js進階(一)

第十一天

04-基礎進階-第01天{創建結構、函數進階}

微博發布(案例)

許愿墻(案例)

通過類名獲取元素對象的兼容方法

// 通過類名獲取元素對象的兼容方法
function getElementByClassName(element,className){
    if(element.getElementByClassName){// 可以使用這個屬性
        return element.getElementByClassName("className");
    }else{
        // 先找到element里面所有的標簽 然后判斷是否有需要的類名
        // 如果有 就把這些標簽放到一個集合中 最后返回這個集合
        var elements = element.getElementByTagName("*"); // 通配符找到所有標簽
        var filterArr = [];
        for(var i = 0;i<elements.length;i++){
            if(elements[i].className.indexOf(className)!== -1){
                filter.push(elements[i]);
            } 
        }
        return filterArr;
    }
}

函數進階

預解析

函數的兩種申明

  • 函數申明式

    function fn(a,b){
        return a+b;
    }
    
    
  • 函數表達式

    var fn = function(a,b){
        return a+b;
    }
    
    

預解析概念

  • 預解析:js代碼在執行之前有一個過程會對代碼進行預先處理,以便代碼高效準確的執行,這個過程叫做預解析
  • 特點:預解析會將變量和函數的申明提升到當前作用域的頂部 然后再開始執行代碼

申明提升

  • 變量提升:預解析會將變量的申明提升到作用域的最前面(只提升申明不提升賦值)

  • 函數提升:預解析會將函數的申明提升到作用域的最前面(函數申明是整個函數體)

  • 申明提升時先找var 再找function

    console.log(a);// 打印的是函數體
    function a(){
        console.log(a);
    }
    var a = 10;
    console.log(a);
    
    // 分析
    1.預解析
    解析器會先找var 
    var a;// 此時a為undefined
    然后再找function
    a{};// 此時a變為函數體
    2.執行console.log(a);// 此時a的賦值a = 10還沒有執行 所以打印的是函數體
    3.執行var a = 10;// 此時給a賦值為10;
    4.執行console.log(a);// 此時打印的是10
    
    

作用域

變量的兩種類型

var a = 1; // 全局變量
function fn(){
    var b = 2; // 局部變量
    c = 3;
    console.log(a);// 1
    console.log(b);// 2
    console.log(c);// 3
}
console.log(a);// 1
console.log(b);// undefined
console.log(c);// 3

  • 全局變量:在最外層申明的變量

  • 局部變量:在函數內部申明的變量

  • 隱式全局變量:在函數內部不用關鍵字var申明的變量

塊級作用域&函數作用域

  • 塊級作用域:一對花括號{}包裹的區間叫代碼塊,不過JavaScript沒有塊級作用域

    console.log(sum);// 因為沒有塊級作用域 所以這里可以訪問到sum,但是變量申明時只提升申明,所以結果是undefined
    if(false){
        var sum = 100; 
    }
    
    
  • 函數作用域:一個函數代碼塊所包含的區間,叫函數作用域,JavaScript只存在函數作用域

    function fn(){
        var a = 1;
    }
    fn();
    console.log(a);// a is not defined 因為存在函數作用域 函數內部申明的變量 函數外包無法訪問
    
    ||
    ||
    \/
    
    

作用域鏈

### 1.全局變量 解析器先在函數內部作用域尋找name1的申明,如果找不到,就向上級作用域尋找name1

    var name1 = "zs";
    function f1(){
        name1 = "ls";
    }
    f1();
    console.log(name1);

    ##分析(偽代碼)
        ||
        ||
        \/
    01.預解析(全局作用域)
    var name1;// 變量申明提升
    f1{};// 函數申明提升

    02.執行
    name1 = “zs”;// 變量賦值

    03.執行f1(函數作用域)
        001.預解析 沒有關鍵字var 也沒有函數申明 所以直接開始執行
        002.執行name1 = "ls";// 優先在當前作用域找name1的申明 然后賦值
        //但是當前作用域沒有name1的申明 就向上一級尋找到了name1的申明 然后賦值為"ls"

    04.執行打印 打印的是全局變量name1 ==> ls

### 2.局部變量 解析器先在函數內部的作用域尋找name2的申明 找了了就使用局部變量

    var name2 = "zs";
    function f2(){
        var name2 = "ls";
    }
    console.log(name2);

    ##分析(偽代碼)
        ||
        ||
        \/
    01.預解析(全局作用域)
    var name2; //變量申明提升
    f2{};// 函數申明提升

    02.執行
    name2 = "zs";

    03.執行f2(函數作用域)
        001.預解析
        var name2; 變量申明提升
        002.執行 現在當前作用域尋找name2 找到了name2的申明 所以給這個局部變量name2賦值"ls"
        name2 = "ls";

    04.執行打印 打印的是全局變量name2 ==> zs

### 3.作用域鏈 作用域鏈只和在哪里定義有關 和在哪里調用無關

    var color = "red";
    function outer(){
        var anotherColor = "blue";
        function inner(){
            var tmpColor = color;
            color = anotherColor;
            anotherColor = tmpColor;
            console.log(anotherColor);
        }
        inner();
    }
    outer();
    console.log(color);

    ##分析(偽代碼)
        ||
        ||
        \/
    01.預解析(全局作用域)
    var color; //變量申明提升
    outer{};// 函數申明提升

    02.執行
    color = "red";

    03.執行outer(outer的函數作用域)
        001.預解析
        var anotherColor;//變量申明提升
        inner{};//函數申明提升

        002.執行
        anotherColor = "blue";

        003.執行inner(inner的函數作用域)
            0001.預解析
            var tmpColor;//變量申明提升

            0002.執行
            tmpColor = color;// 一直向上找到全局變量color==>"red"
            color = anotherColor;// 找到outer中的anotherColor==>"blue"
            anotherColor = tmpColor;// 找到outer中的anotherColor 賦值tmpColo的值==>"red"
            0003.執行打印
            console.log(anotherColor);//找到上級作用域的anotherColor ==> "red"

    04.執行打印
    console.log(color);// 全局作用域的color ==> "blue"

### 4.作用域鏈 所謂不加var就是全局變量不準確

    var name3 = "zs";
    function f3(){
        var name3 = "ls";
        function f4(){
            name3 = "ww";
        }
        f4();
        console.log(name3);
    }
    f3();
    console.log(name3);

    ##分析(偽代碼)
        ||
        ||
        \/
    01.預解析(全局作用域)
    var name3; //變量申明提升
    f3{};// 函數申明提升

    02.執行
    name3 = "zs";

    03.執行f3(f3的函數作用域)
        001.預解析
        var name3;//變量申明提升
        f4{};// 函數申明提升

        002.執行
        name3 = "ls";

        003.執行f4(f4的函數作用域)
            0001.預解析
            0002.執行
            name3 = "ww";// 先在f4作用域尋找name3 沒找到 然后向上一級到f3作用域尋找name3 找到之后賦值"ww" 也就是f3作用域name3的值被改"ww"

        004.執行打印
        console.log(name3);// 當前是在f3的作用域 尋找name3 找到了 而且其值為"ww"

    04.執行打印(全局作用域)
    console.log(name3);// 當前作用域的name3是"zs"

遞歸

階乘

// 求階乘  
function getJC(n){
    if(n===1){
        return;
    }
    var jc = n*getJC(n-1);
    return jc;
}

斐波那契數列

// 斐波那契數列
function getFb(n){
    if(n===1||n===2){
        return 1;
    }
    var fb = getFb(n-1) + getFb(n-2);
    return fb;
}

構造函數的參數

  • 函數也是一種數據類型function

    function fn(){
        console.log("fn");
    }
    console.log(typeof fn);// function
    
    

構造函數Function()

  • 構造函數傳一個參數代表的就是函數體function_body

    var fn = new Function("alert('a')");
    ||
    ||等價
    \/
    function fn(){
        alert("a");
    }
    
    
  • 構造函數如果有多個參數,最后一個代表函數體,其他是形參

    var fn = new Function("a","b","c","alert(a+b+c)");
    ||
    ||等價
    \/
    function fn(a,b,c){
        alert(a+b+c);
    }
    
    

回調函數

  • 被當做參數傳遞的函數叫做回調函數

sort排序

var arr = [8,4,2,1,3,5,6,9,7];
arr.sort(function(a,b){
    return a-b;// 升序
    //return b-a;// 降序

});

sort內部原理

function sort(arr, fn) {
    for (var i = 0; i < arr.length - 1; i++) {
        var flag = true;
        for (var j = 0; j < arr.length - 1 - i; j++) {
            if (fn(arr[j], arr[j + 1]) > 0) {
                var temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = false;
            }
        }
        if (flag) {
            break;
        }
    }
    return arr;
}

function fn(a,b){
    return a-b;
}

sort([9,8,7,6,5,4,3,2,1],fn);// fn即回調函數

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 工廠模式類似于現實生活中的工廠可以產生大量相似的商品,去做同樣的事情,實現同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,842評論 2 17
  • 繼承 一、混入式繼承 二、原型繼承 利用原型中的成員可以被和其相關的對象共享這一特性,可以實現繼承,這種實現繼承的...
    magic_pill閱讀 1,080評論 0 3
  • 函數聲明和函數表達式有什么區別 (*)解析器會率先讀取函數聲明,并使其在執行任何代碼之前可以訪問;函數表達式則必須...
    coolheadedY閱讀 400評論 0 1
  • 一、JavaScript基礎知識回顧 1.1 JavaScript 1.1.1 javascript是什么? Ja...
    福爾摩雞閱讀 1,339評論 0 7
  • 單例模式 適用場景:可能會在場景中使用到對象,但只有一個實例,加載時并不主動創建,需要時才創建 最常見的單例模式,...
    Obeing閱讀 2,103評論 1 10