• JavaScript基础知识


    前言

      其实我个人认为JavaScript是一种非常随便的语言,也是一门很神奇很强大的语言。

      因为之前使用过一段时间的JavaScript并做了些学习笔记都是放在word上的显得十分杂乱,所以这次也是打算认认真真的重新填一下坑并且认真整理一下JavaScript笔记到博客园。

      以前在群里聊JavaScript的时候会经常出现一张图,我认为这个很有意思,所以就放在这里做一个填坑目标吧。

      https://www.w3cschool.cn/javascript/javascript-skillmap.html  这里放上一个学习路线图,非常详细非常精彩。当然我的笔记不可能做的十分的全面,所以可以配合看这张学习路线图与笔记,这个路线图好像有很多新版特性都没介绍到,不过在我的笔记中会有相应的介绍。

    查看源图像

      我还是希望将整个的笔记好好整理一下,并且以一种文档格式进行书写,也方便后期查阅。

    理论知识

    语言介绍

      JavaScript官方名称是 ECMAScript 是一种属于网络的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。

      1995年2月Netscape的布兰登.艾奇开发了针对网景公司的 Netscape Navigator浏览器的脚本语言LiveScript。之后Netscape与Sun公司联盟后LiveScript更名为JavaScript

      微软在JavaScript发布后为了抢占市场推出了JavaScript。为了让脚本语言规范不在混乱,根据JavaScript 1.1版本推出了ECMA-262的脚本语言标准。

      ECMA是欧洲计算机制造商协会由Sum、微软、NetScape公司的程序员组成。

      文档中会经常使用 JS 简写来代替 JavaScript

      Ps:其实整个JavaScript最早的开发周期只用了两周,所以在未来很长一段时间里JavaScript的语法非常混乱,但是随着时间的更迭慢慢的越来越完善起来。

    适用场景

    • 浏览器网页端开发

    • 做为服务器后台语言使用Node.js

    • 移动端手机APP开发,如Facebook的 React NativeuniappPhoneGapIONIC

    • 跨平台的桌面应用程序,如使用 electronjs

      所以JS是一专多能的语言,非常适合学习使用。

    发展历史

    • 1994年Netscape(网景)公司发布了 Navigator 浏览器1.0版本,市场占用率超过90%

    • 1995年发布了JavaScript 语言

    • 1996年 JS在 Navigator浏览器中使用

    • 1996年微软发布JScript在IE3.0中使用

    • 1996年11月网景公司将JS提交给ECMA(国际标准化组织)成为国际标准,用于对抗微软。

      由ECMA的第39号技术专家委员会(Technical Committee 39,简称TC39)负责制订ECMAScript标准,成员包括Microsoft、Mozilla、Google等大公司。

    • 1997年 ECMA发布ECMA-262标准,推出浏览器标准语言 ECMAScript 1.0

      ECMAScript 是标准而Javascript是实现

    • ...

    • 2009年ECMAScript 5.0发布

    • 2011年ECMAScript5.1发布,成为ISO国际标准,从而推动所有浏览器都支持

    • ...

    • 2015年ECMAScript6发布,更名为ECMAScript 2015。

    • 2016年ECMAScript7发布,ECMAScript2016

    • 2017年ECMAScript8发布,ECMAScript2017

    • 2018年ECMAScript9发布,ECMAScript2018

    • 2019年ECMAScript10,ECMAScript2019

    • 2020年ECMAScript11,ECMAScript2020

    • ....

      从2015年开始 tc39委员会决定每年发布新的ECMAScript版本

    chrome使用

      在学习Js的过程中,推荐使用chrome浏览器作为你的开发工具。

    image-20200725004121425

    引入方式

    嵌入式

      HTML文档中使用<script>标签,在<script>标签中嵌入Js代码即可,关于type什么的文档类型声明可写可不写。

      使用这种在方式最好是将Js代码写在尾部。也就是写在HTMLCSS代码之后。

      这种做法是因为如果我们的Js代码需要去查找某一标签而将其放在头部的话HTML的代码可能还没有加载出来,会出现一些不稳定的特殊情况。

      我个人是非常喜欢夹在<body>标签后的...

    <!DOCTYPE html>
    <html lang="en"><head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Document</title>
    </head><body></body>
        <script>
            console.log("hello,world");  // hello,world
        </script>
    </html>

    引入式

      同样的,也是使用<script>标签,并为其src属性指定好Js文件路径即可,关于type什么的文档类型声明可写可不写。

      还是推荐将它放在尾部,但是也有很多是放在<head>标签中的。

    image-20200724212027898

    <script src="./first_js.js" type="application/x-javascript"></script>

    代码注释

      Js中的注释有两种,一种单行注释,一种多行注释。

    单行注释

      使用//放在语句前,即可完成单行注释。

    <script>
            // 下面是个自执行函数
           
            (function (){
                    console.log("hello,world");
            })()
    </script>

    多行注释

      使用/*开头,*/结束,可包含多行。

    <script>
            /* 下面是个自执行函数
            它没有参数 */
            
            (function (){
                    console.log("hello,world");
            })()
    </script>

    自动分号

    自动分号

      在一段语句结束后,应当加上;号,但是这并不是强制性的而是一种规范。

    <script>
    
            (function (){
                    console.log("hello,world");
                    alert("hello,world");
                    document.write("hello,world");
            })();
    
    </script>

    意义作用

      尽管你可以不加,但是请注意前端的代码一般来说在上线部署后都会进行压缩。

      在使用构建工具时,不使用分号结束可能会造成异常!

      我们可以看一下一个非常常见的JsjQuery的生产版源码。

    image-20200724214109570

    变量声明

      变量就是存储着一个允许变的值。

      如年龄,爱好,居住地等都可以定义为变量。

      变量的使用都是先声明后使用,这个应该是非常基础的,在每个语言中都是这样。

      那么在JavaScript中关于变量声明有很多有意思的点,可以慢慢往下看。

    命名规则

      Js中的变量是弱类型可以保存所有类型的数据,即变量没有类型而值有类型。变量名以字母$_开始,后跟字母数字_

      Js中的语言关键字不能用来做变量名,比如 true、if、while、class 等。

      请不要轻易使用用$来作为变量名的起始,因为它被jQuery给霸占了,目前请谨记这一点。

      正确的命名规范

    <script>
    
            var username = "Yunya";
            var _age = 18;
            var $select = "Please do not use $ to start variable names lightly, although it is not wrong";
            
    </script>

      错误的命名规范

    <script>
    
            var 9username = "ERROR";
            var (age = "ERROR";
            var --select = "ERROR";
            
    </script>

    image-20200724220024928

    声明赋值

      早期的Js使用者都同一用var来声明变量,但是es6后推出了let,具体的作用我们这里先不管。先看一下最基本的使用,由于Js是一门弱类型语言,所以不用强调变量声明的类型。

      先声明并赋值,后使用

    <script>
            
            // 先声明并且赋值
            var username = "YunYa";
            let age = 18;
            // 后使用
            console.log(username);  // YunYa
            console.log(age);  // 18
    
    </script>

      上面是最常用的方式,其实也可以先声明,再赋值,后使用。

    <script>
    
            // 先声明
            var username;
            let age;
            // 再赋值
            username = "YunYa";
            age = 18;
            // 后使用
            console.log(username);  // YunYa
            console.log(age);  // 18
    
    </script>

      我们还可以一次性声明赋值多个变量。

    <script>
    
            var username = "YunYa", age = 18, gender = "male";
            console.log(username);  // YunYa
            console.log(age);  // 18
            console.log(gender);  // male
    
    </script>

      也可以进行链式赋值

    <script>
    
            var a=b=c=1;
            console.log(a);  // 1
            console.log(b);  // 1
            console.log(c);  // 1
    
    </script>

    弱类型

      弱类型其实就是说存的是什么类型的值,就是什么类型的变量。

      不用提前声明变量变量再进行存储。

    <script>
    
            var username = "YunYa";
            var age = 18;
            var other = {"hobby":"basketball","marriage":false,"height":192,"weight":126,};
    
            // typeof 是查看变量的类型方法
            console.log(typeof username);  // string
            console.log(typeof age);  // number
            console.log(typeof other);  // object
    
    </script>

    常量声明

      常量存储一些不允许被改变的值。

      PI,性别,籍贯等等都可以定义为常量。

    命名规则

      常量的命名规则和变量基本一致,但是一定要注意!常量的命名规则是全部大写形式,这是一种规范。

      常量名建议全部大写

      只能声明一次变量

      声明时必须同时赋值

      不允许再次全新赋值

      可以修改引用类型变量的值

      拥有块、函数、全局作用域

    <script>
            // 常量声明全用大写
            const PI = 3.1415926535897;
            console.log(PI);  // 3.1415926535897
    
    </script>

    声明赋值

      常量我们一般都会使用const来进行声明并赋值,它有一个特点,即声明之后不允许改变。

    <script>
            
            // 常量声明全用大写
            const PI = 3.1415926535897;
            PI = 100;
            console.log(PI); 
            // Uncaught TypeError: Assignment to constant variable.
            // 类型错误: 将值分配给了一个不变的变量(常量)
    
    </script>

    var let const 区别

    意义作用

      不使用他们会全部乱套,因为有不同的作用域存在,如果不使用他们则代表将所有的变量全部放进全局作用域中。

      代码及易出现问题!

    <script>
    
            username = "YunYa";
     
            function test(params) {
    
                    console.log(username); // YunYa
                    username = "Jack";   
                    console.log(username); // Jack
            };
            test();
    
            // 可以看到,被污染了..
            console.log(username); // Jack
    
    </script>
    <script>
    
            var username = "YunYa";
     
            function test(params) {
    
                    console.log(username); // undefined 这是因为自身局部作用域有一个 username,但是此时还未定义。所以不去找全局的name了,只好显示undefined。
                    var username = "Jack";   
                    console.log(username); // Jack
            };
            test();
    
            // 可以看到,未污染了..
            console.log(username); // YunYa
    
    </script>

    变量提升

      变量提升其实你可以将它当做是预加载,它会预先来检查所有声明的变量名字是否合法。

    <script>
    
            console.log("执行我了...");  // 没执行
            let for = "YunYa";  //  Uncaught SyntaxError: Unexpected token 'for'
            console.log("执行我了...");  // 没执行
            
    </script>

      很明显的看到,代码都没执行,但是却抛出异常。这是预加载做的第一步事情,检查名称是否合法。

      当预加载第一步执行完毕后,开始做第二步事情,对var声明的变量进行开辟内存空间(注意:是开辟内存空间,并未赋值,并且letconst声明的变量都不会开辟内存空间)。

      也就是说,当Js代码开始运行时,检查完变量名是否合法后,它会预先拿到所有var声明的变量名的名字(函数名也会),但并不会进行赋值。

      只有当真正开始执行代码并且走到赋值代码时才会进行赋值操作,所以你可以看到下面的这种情况。

    <script>
    
            // 为什么没抛出异常?
            console.log(username)  // undefined
            var username = "YunYa";
            
    </script>

      如果使用一个未被定义的名字,那么才是真正的会抛出异常。

    <script>
    
            console.log(age)  // Uncaught ReferenceError: age is not defined
            var username = "YunYa";   
      
    </script>

    TDZ暂时性死区

      TDZ又称暂时性死区,指变量在作用域内已经存在,但必须在let/const声明后才可以使用。

      TDZ可以让程序保持先声明后使用的习惯,让程序更稳定。

      变量要先声明后使用

      建议使用let/const而少使用var

      使用let/const 声明的变量在声明前存在临时性死区(TDZ)使用会发生错误。

      其实说白了就是letconst来声明的变量必须遵守先声明后使用的原则。

    <script>
            
            // 意思就说,不能在完成之前访问name这个变量
            console.log(username)  // Uncaught ReferenceError: Cannot access 'name' before initialization
            let username = "YunYa";   
      
    </script>
    <script>
    
            // 意思就说,不能在完成之前访问name这个变量
            console.log(username)  // Uncaught ReferenceError: Cannot access 'username' before initialization
            const username = "YunYa";   
      
    </script>

    块作用域

      作用域你可以简单的理解为,只要有{}括起来的地方全是作用域,它的作用就是让相同名字的变量名之间互不冲突。

    作用域 
    全局作用域 变量名全局有效。
    局部作用域 变量名在函数,类中有效,可访问全局作用域中的变量。
    块作用域 对于var来说不存在,对于let来说则存在,常见for循环,通俗讲只要有不是局部作用域和全局作用域而被{}包裹的代码块全部称为块作用域。

      注意:letconst都具有块作用域,而var则不具有。

      下面例子使用var则会造成污染(会当成全局作用域来看待,不具有块作用域),而使用let则不会(const不可多次赋值应用)。

    <script>
    
            var i = 100;
            for(var i = 0;i < 5;i++){
                    console.log(i);  // 0 1 2 3 4 
            }
    
            // 此时我们在想用 100 的那个 i 抱歉,被替换了。
    
            console.log(i);  // 5
      
    </script>
    <script>
    
            let i = 100;
            for(let i = 0;i < 5;i++){
                    console.log(i);  // 0 1 2 3 4 
            }
    
            // 未替换。
    
            console.log(i);  // 100
      
    </script>

    重复定义

      在同一作用域下,使用var定义的变量名可重复定义,而letconst则不可重复定义。

      var

    <script>
    
            var num = 100;
            var num = 1000;
    
            // 明显不太好
    
            console.log(num);   // 1000
      
    </script>

      let

    <script>
            
            // Uncaught SyntaxError: Identifier 'num' has already been declared
            // 语法错误 num 已经被定义
            let num = 100;
            let num = 1000;
    
            console.log(num); 
      
    </script>

      const

    <script>
    
            // Uncaught SyntaxError: Identifier 'num' has already been declared
            // 语法错误 num 已经被定义
            const num = 100;
            const num = 1000;
    
            console.log(num);   // 1000
      
    </script>

    windows对象

      使用var定义的变量会被存入windows对象,而letconst却不会。

      var

    <script>
    
            var username = "YunYa";
            console.log(window["username"]);  // YunYa
      
    </script>

      let

    <script>
    
            let username = "YunYa";
            console.log(window["username"]);  // undefined
      
    </script>

      const

    <script>
    
            const username = "YunYa";
            console.log(window["username"]);  // undefined
      
    </script>

    差异总结

    var let const区别   
      var let const
    变量提升
    TDZ暂时性死区
    块作用域
    同一作用域下重复定义 允许 不允许 不允许
    windows对象 添加 不添加 不添加
    总结:尽量少使用var多使用let   

    严格模式

      严格模式可以让我们及早发现错误,使代码更安全规范,推荐在代码中一直保持严格模式运行。

      只需要在书写代码前加上"use strict";即可。

      主流框架都采用严格模式,严格模式也是未来JS标准,所以建议代码使用严格模式开发

    基本差异

      变量必须使用关键词声明,未声明的变量不允许赋值。

    <script>
    
            //  Uncaught ReferenceError: username is not defined
    
            "use strict";
            
            username = "YunYa";  
    
            console.log(username);
    
    </script>

      关键词不允许做变量使用

    <script>
    
            //  Uncaught SyntaxError: Unexpected token 'try'
    
            "use strict";
            
            var try = "YunYa";  
    
            console.log(username);
    
    </script>

      变量参数不允许重复定义

    <script>
    
            //  Uncaught SyntaxError: Duplicate parameter name not allowed in this context
    
            "use strict";
            
            function test(x,x){
                    console.log("执行了...");
            };
    
            test();
    
    </script>

      单独为函数设置严格模式

    <script>
            
            function test(){
                    "use strict";
                    console.log("执行了...");  // 执行了...
            };
    
            test();
    
    </script>

      为了在多文件合并时,防止全局设置严格模式对其他没使用严格模式文件的影响,将脚本放在一个执行函数中。

    <script>
            
            (function (param) {
    
                    "use strict";
                    let url = "www.google.com";
                    console.log(url);
                    
              })();
    
    </script>

    解构差异

      非严格模式可以不使用声明指令,严格模式下必须使用声明。所以建议使用 let等声明。

    <script>
    
            // "use strict"; 
            // 在严格模式下不允许这样使用
    
            ({ name, other } = { "name":"YunYa-cnblogs","other":"good" });
            console.log(name, other); // YunYa-cnblogs good
    
    
    </script>
  • 相关阅读:
    每天一个小算法(Heapsort)
    每天一个小算法(matlab armijo)
    每天一个小算法(Shell sort5)
    每天一个小算法(Shell Sort3)
    每天一个小算法(Shell Sort2)
    Java并发编程:阻塞队列
    Java并发编程:并发容器之CopyOnWriteArrayList
    Java并发编程:并发容器之ConcurrentHashMap
    Java并发编程:CountDownLatch、CyclicBarrier和Semaphore
    豆瓣的前世今生
  • 原文地址:https://www.cnblogs.com/Yunya-Cnblogs/p/13375290.html
Copyright © 2020-2023  润新知