zoukankan      html  css  js  c++  java
  • 那些我不知道的基础知识

    1. function函数传参

    1)传参类型为原始类型(字符,数值,布尔)时,为传值传递(passed by value);修改参数的值不会修改原始值。

            var a = 1;
            function name(a) { // 参数相当于name(var a; a=4), 这个a的作用域在函数内,和外部的a是两个变量
                a = 3
                console.log('--inner--',a); // 3
            }
            name(4);
            console.log('---outer--',a); // 1

    2)传参类型为符合类型(对象,数组,函数等),为传址传递(passed by reference), 传入函数的是原始值的地址。

    • 在函数内部修改传入的值的参数会修改原始值。
    var obj = {a:1};
    function fn(obj) {
      obj.a = 2;
    }
    fn(obj);
    console.log(obj); // { a: 2 }
    • 在函数内部整个替换传入的参数,不会修改原始值。原因是:传入的代表地址的形参,被赋值后,指向另一个地址。原来地址的值不变。
    var obj = {a:1};
    function fn(obj) {
      obj = { a: 2 }
    }
    fn(obj);
    console.log(obj); // { a: 1 }

     2. 语句和表达式

    函数式编程涉及到对表达式的理解。

    区别:

    • 语句为了完成一段操作,一般不需要返回值;表达式是为了得到一个值,一定会返回一个值。
    // 语句为了完成一段操作,如循环语句,赋值语句等
            for(let i=0; i<5;i++){
                console.log(i);
            };
           var a = 1 + 3;
    // 表达式是为了返回一个值
        if (true && 1) // 括号中是表达式,返回1
    • 语句以分号结尾。表达式不能以分号结尾,加上分号,会变成语句。
    • js引擎规定,function出现在行首时,时函数声明语句。非行首时,是函数表达式。
    // 此为函数表达式     
      var foo = function() {};

    3. 变量(var/function/let/const/class)

    1.区分大小写

    a和A是两个不同的变量,对于上面四种变量声明方式来说都是。

    var a = 1; 
    var A = 1;

    2.变量提升(var和function)

    对于var和function声明的变量存在变量提升,提升到当前函数作用域顶部或者全局作用域顶部

    js代码编译运行过程分为: 词法分析->语法解析(AST)->代码生成->代码执行;

    编译器在进行代码生成时,遇到变量声明,编译器询问当前作用域是否已经存在该变量。

    如果是,忽略;如果否,则要求作用域在当前作用域声明一个变量。

    所以:

    在js执行时,所有的声明类语句已经声明过了,他们在代码生成阶段阶段已经声明过了。

    而且作用域声明的时候在当前作用域的顶部进行声明。

    所以变量提升其实指的是变量声明提升,函数声明也会提升。

    ❌不要在块级作用域中声明函数,因为在ES5中function整个声明提升;ES6中只提升函数名。

    console.log(a); // undefined
    var a = 100;
    // 相当于
    var a; 
    console.log(a);
    a=100;

    对于let/const/class声明的变量(或常量)不存在变量提升,并且存在暂时性死区。

    <script>
        // 暂时性死区是说作用域内只要声明了let变量,声明之前就不能使用
        var a = 100;
        function add() {
            // 调用add()后报错;编译时不报错。
            a = 1000;// Uncaught ReferenceError: Cannot access 'a' before initialization
            let a;
            console.log(a);
        }
        add();
    </script>
    <script>
        // 下面是函数赋初值造成的“暂时性死区”现象
        var a = 100;
        // Uncaught ReferenceError: Cannot access 'a' before initialization
        function sum(a=a) { // 参数赋值形成单独的作用域 相当于在函数内let a=a;
        }
        sum(); // 声明时不会报错,调用时报错
    </script>
        <script>
            // class变量也不存在变量提升;
            const b = new a();//Uncaught ReferenceError: Cannot access 'a' before initialization
            class a{ }
        </script>

    3. 变量作用域

    对于var和function变量来说只有函数作用域和全局作用域。

    对于let/const/class存在块级作用。

    对于for循环来说,如果循环变量使用var,其实循环变量是全局变量或者函数内变量;

    如果循环变量使用let声明,实际生成了两层块级作用域;变量声明是一层,循环体是一层;

        <script>
            var a= []; // i是全局变量,跳出循环时i=3;
            for (var i=0; i<3; i++) {
                a[i] = function() {
                    console.log(i);
                }
            };
            // 数组a包含三个函数元素
            console.log(a.toString()); 
            /*  
                function(){console.log(i)},
                function(){console.log(i)},
                function(){console.log(i)},
            */
            a[2](); // 3  
        </script>
        <script>
            var a= []; // let块级作用域变量,每次循环都相当于重新声明一个新的i变量,新的块级作用域
            for (let i=0; i<3; i++) {
                a[i] = function() {
                    console.log(i);
                }
            };
            // 数组a包含三个函数元素
            console.log(a.toString()); 
            /*  
                function(){console.log(i)},
                function(){console.log(i)},
                function(){console.log(i)},
            */
            a[2](); // 2 
        </script>
        <script>
            // for循环生成两层块级作用域
            for (let i=0; i<3; i++) {// 声明循环变量的部分是外层块级作用域;会循环3次
                let i = 'hello'; // 循环体是内层块级作用域;内部作用域使用内部的块级变量
                console.log(i); 
            };
            // hello
            // hello
            // hello
        </script>

    4.变量重复声明

    var 和function允许重复声明,后面的会覆盖前面的;let和const不允许重复声明,会报错。

            var a = 1;
            var a = 2;
            console.log(a); // 2
    // 只要出现了let声明,前后再次声明同一个变量就会报错      
     let a = 1;
     var a = 2; // Uncaught SyntaxError: Identifier 'a' has already been declared
     console.log(a); 

    函数参数其实是一个隐藏的变量声明位置

            function add1(a) { //var a
                var a = 4; // 重复声明
                console.log(a); // 4
            }
            function add2(a) {// var a
                let a = 4;// Uncaught SyntaxError: Identifier 'a' has already been declared
                console.log(a); 
            }
            add1(); // 不会执行,因为在代码生成阶段就报错了
            add2(); // 不会执行

     5.顶层对象的属性

    var和function在全局环境声明的变量,会成为全局对象的属性,即window对象的属性;

    但是let,const, class的不会。

            var a = 100;
            console.log(window.a);//100
            let b = 10;
            console.log(window.b);//undefined
            class c{};
            console.log(window.c);//undefined
            const D = 1;
            console.log(window.D);//undefined

     6.变量命名规则

    • 汉字可以作为变量名
    • 保留字不能作为变量名
    // 保留字有:
    arguments、breakcasecatch、class、const、continuedebuggerdefaultdeletedoelse、enum、eval、export、
    extends、falsefinallyforfunctionif、implements、import、ininstanceof、interface、let、newnull、package、private、
    protected、public、return、static、super、switchthisthrowtruetrytypeofvarvoidwhilewith、yield

    4.条件语句,循环语句

    1)switch条件和case变量,比较是严格相等===;case后面要加break,否则会执行所有case语句;

    2)break跳出所有的循环;continue语句跳出本次循环;

         如果存在多层嵌套循环,则两者都是针对最内层循环。

    3)使用标签,可以配合break和continue跳出最外层循环。

    ❌一定注意不要把赋值表达式当成条件表达式,否则会出现死循环,因为赋值表达式永远是true;===

  • 相关阅读:
    我的第一个Django项目
    MVC和MTV设计模式
    Linux下安装MySQL
    UEditor演变的迷你版编辑器
    PHP+Mysql+jQuery实现文件下载次数统计
    PHP+JQUEY+AJAX实现分页
    PHP高手之路(一)
    nginx别名alias支持PHP fastcgi解析
    免费的FRP--windows 内网使用Argo Tunnel打洞到 Cloudflare
    拾得他人闲话 DNS 的牙慧
  • 原文地址:https://www.cnblogs.com/lyraLee/p/11252632.html
Copyright © 2011-2022 走看看