js进阶(一)

第十一天

04-基础进阶-第01天{创建结构、函数进阶}

  • 第十一天
    • 微博发布(案例)
    • 许愿墙(案例)
    • 通过类名获取元素对象的兼容方法
    • 函数进阶
      • 预解析
        • 函数的两种申明
        • 预解析概念
        • 申明提升
      • 作用域
        • 变量的两种类型
        • 块级作用域&函数作用域
      • 作用域链
    • 递归
      • 阶乘
      • 斐波那契数列
    • 构造函数的参数
      • 构造函数Function()
    • 回调函数
      • sort排序
      • sort内部原理

微博发布(案例)

许愿墙(案例)

通过类名获取元素对象的兼容方法

// 通过类名获取元素对象的兼容方法
function getElementByClassName(element,className){
    if(element.getElementByClassName){// 可以使用这个属性
        return element.getElementByClassName("className");
    }else{
        // 先找到element里面所有的标签 然后判断是否有需要的类名
        // 如果有 就把这些标签放到一个集合中 最后返回这个集合
        var elements = element.getElementByTagName("*"); // 通配符找到所有标签
        var filterArr = [];
        for(var i = 0;i

函数进阶

预解析

函数的两种申明

  • 函数申明式

    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即回调函数

你可能感兴趣的:(js进阶(一))