精华内容
下载资源
问答
  • javascript下载_免费JavaScript下载
    万次阅读
    2020-09-11 14:06:30

    javascript下载

    Unlike other languages that can be used in a web browser, JavaScript doesn't need to be downloaded and installed. Browsers that support JavaScript have it built into the browser, where it is turned on by default (meaning that typically, you'll need to change your browser settings only if you don't want the browser to run JavaScript). The only exception is that Internet Explorer also supports vbScript the same way, and the two languages are controlled via settings called "active scripting" rather than a setting that reference JavaScript specifically.

    与可在网络浏览器中使用的其他语言不同,不需要下载和安装JavaScript。 支持JavaScript的浏览器已将其内置到浏览器中,默认情况下处于打开状态(这意味着通常,仅当您希望浏览器运行JavaScript时,才需要更改浏览器设置)。 唯一的例外是Internet Explorer也以相同的方式支持vbScript ,并且这两种语言是通过称为“活动脚本”的设置来控制的,而不是通过专门引用JavaScript的设置来控制的。

    What you will need to download with JavaScript, then, is not the scripting language itself, but rather those scripts that you want to run in your web page (assuming that you have decided not to learn JavaScript so you can write it all yourself).

    因此,您需要使用JavaScript下载的不是脚本语言本身,而是要在网页中运行的脚本(假设您决定不学习JavaScript,因此可以自己编写)。

    JavaScript下载是免费的 ( JavaScript Downloads Are Free )

    There is no need to pay for scripts written in JavaScript, because just about any script imaginable is available somewhere as a free JavaScript download. What you need to be careful of, though, is to obtain them from a site that is actually offering the scripts as a free download, rather than just copying the scripts from any site. JavaScript code that performs any significant task will be subject to copyright, so you will permission from the author to use his or her script.

    无需为用JavaScript编写的脚本付费,因为几乎可以想象得到的任何脚本都可以通过免费JavaScript下载获得。 但是,您需要注意的是从实际上免费提供脚本的网站上获取它们,而不是仅仅从任何站点复制脚本。 执行任何重要任务的JavaScript代码均受版权保护,因此您将获得作者的允许使用其脚本。

    The task the JavaScript is doing is not able to be copyrighted, however, so if you are writing a script yourself, you can't get into trouble for looking at an existing script to see how the programmer did it and then writing your own version. But if you are just looking for free JavaScript downloads, then you should go to a site where the author specifically states that his or her script is available as a free download and can be used on your site. There are many sites that offer free JavaScript downloads, including several huge sites that only offer JavaScript downloads, as well as other sites (such as this one) that offer free JavaScript downloads and also have tutorials on how to write the scripts for yourself.

    但是,JavaScript所执行的任务无法获得版权,因此,如果您自己编写脚本,则不必担心查看现有脚本以了解程序员的工作方式,然后编写自己的版本。 但是,如果您只是在寻找免费JavaScript下载,那么您应该去一个网站,在该网站上作者特别声明,他或她的脚本可以免费下载,并且可以在您的网站上使用。 有许多网站提供免费JavaScript下载,包括几个仅提供JavaScript下载的大型网站,以及其他提供免费JavaScript下载并且还提供有关如何为自己编写脚本的教程的网站(例如该网站)。

    免费下载JavaScript的优点 ( Advantages of Getting Free JavaScript Downloads )

    Apart from avoiding copyright issues, there are other advantages to getting your free JavaScript downloads from a site that is actively offering the scripts. The main one is that such sites usually provide step-by-step instructions on how to actually install and use the script. Where you just grab a script from anywhere, not only are you stealing a script but also you won't get instructions on how to install it or support if you can't get it to work.

    除了避免版权问题外,从正在积极提供脚本的网站上免费下载JavaScript还有其他好处。 主要的一点是,此类站点通常提供有关如何实际安装和使用脚本的分步说明。 在任何地方都可以抓取脚本的地方,不仅会窃取脚本,而且如果无法使脚本正常运行,您将不会获得有关如何安装或获得支持的说明。

    Another thing to watch for when you are getting your free JavaScript downloads from an appropriate site is that many of these sites have been in existence for many years, and the way that JavaScript should be used has changed over time. In many cases, you'll find scripts that were written many years ago to work on the most popular browsers available at that time -- browsers that are now long gone. Ideally, you should have at least some familiarity with what is currently considered the best way of writing JavaScript, so that you can choose the version that will work best with current browsers.

    当您从适当的站点获得免费JavaScript下载时,还要注意的另一件事是,这些站点中的许多已经存在了很多年,并且使用JavaScript的方式已经随着时间而改变。 在许多情况下,您会找到许多年前编写的脚本,这些脚本可以在当时可用的最受欢迎的浏览器上运行,而这些浏览器早已不复存在。 理想情况下,您应该至少对当前被认为是编写JavaScript的最佳方式的知识有所了解,以便可以选择最适合当前浏览器的版本。

    You can't really blame the sites offering scripts that are not up to date. It does take time to code and test JavaScripts to make sure that they work correctly with the wide range of browsers in common use today. Having a somewhat dated script that still works available as a free download is certainly better than not having the script available at all. The biggest sites specializing in free JavaScript downloads usually offer scripts written by a lot of different people, and they rely on someone actually writing a new version of a script before they can offer it for download. Other sites that have their own staff to write and test scripts may have limited resources for being able to create updated versions of scripts, and so they may be offering older scripts until they can make updates.

    您不能真正怪罪那些提供最新脚本的网站。 确实需要花费一些时间来编写代码和测试JavaScript,以确保它们能够与当今广泛使用的各种浏览器正常工作。 具有过时日期的脚本仍然可以免费下载仍然比完全不提供脚本要好。 专门提供免费JavaScript下载的最大型网站通常会提供由许多不同人编写的脚本,并且它们依赖于实际编写脚本的新版本的人才能提供下载。 其他拥有自己的人员来编写和测试脚本的站点可能具有有限的资源来能够创建脚本的更新版本,因此它们可能会提供较旧的脚本,直到可以进行更新为止。

    更新免费JavaScript ( Updating Free JavaScripts )

    One thing to remember when you obtain free JavaScripts for your site is that there's no reason to continue running the same version of the script forever. When a more modern version of the script is made available as a free download, you can always update your page and replace the old script with the new one. This is particularly easy where the new version of the script is offered as a direct replacement for the script you are currently using, but it shouldn't be all that hard even if you get it from a completely different source.

    在为您的站点获得免费JavaScript时要记住的一件事是,没有理由永远继续运行相同版本的脚本。 免费提供更现代版本的脚本后,您可以随时更新页面,并用新脚本替换旧脚本。 在提供新版本的脚本以直接替换当前使用的脚本的情况下,这特别容易,但是即使从完全不同的来源获得脚本,也不应该那么困难。

    The number and variety of scripts offered for free download mean that no matter what sort of JavaScript you want to add to your page, you should be able to find several sites offering one or more variations on such scripts. Only when you get to the stage where you require a script that directly interacts with custom code within your web page (such as for form field validation) will you be unable to find a free JavaScript download that does everything for you without your having to code any of it yourself. Even in such situations, you should be able to find free downloads that provide you with pieces of code that will do at least a part of what you need, along with instructions on how to attach such code fragments together to do what you require.

    可免费下载的脚本数量众多,种类繁多,这意味着无论您要添加到页面的哪种JavaScript,您都应该能够找到多个站点,这些站点提供了一个或多个此类脚本的变体。 仅当您到达一个需要脚本与网页内的自定义代码直接交互的阶段(例如用于表单字段验证)时,您才能找到免费JavaScript下载,而无需编写代码即可为您完成所有工作任何你自己。 即使在这种情况下,您也应该能够找到免费下载的文件,这些文件可以为您提供至少可以满足您所需功能的一部分代码,以及有关如何将此类代码片段附加在一起以执行所需功能的说明。

    Even those who move on to writing their own JavaScript rather than relying on pre-written free downloads can make use of free downloads. Along with complete scripts for performing a variety of simple tasks, there are also code libraries available as free downloads that will provide common functionality that will make writing your own JavaScript much easier.

    即使是那些继续编写自己JavaScript而不是依靠预先编写的免费下载内容的人,也可以使用免费下载内容。 除了用于执行各种简单任务的完整脚本之外,还有免费下载的代码库,这些代码库将提供通用功能,这些功能将使编写自己JavaScript更加容易。

    For those want to learn to program, one of the biggest advantages of JavaScript is that it is all free. You don't need to pay for anything to get started. The JavaScript language itself is built into all the browsers you need for testing the scripts, and there are plenty of free JavaScript downloads of complete scripts and libraries that you can either use as is or examine to see how things work in order to write your own code.

    对于那些想学习编程的人来说,JavaScript的最大优点之一就是它完全免费。 您无需支付任何费用即可开始使用。 JavaScript语言本身已内置在测试脚本所需的所有浏览器中,并且有大量免费的完整脚本和库JavaScript下载,您可以按原样使用或检查它们的工作方式以编写自己的脚本码。

    翻译自: https://www.thoughtco.com/free-javascript-download-2037527

    javascript下载

    更多相关内容
  • vs2015.iso包安装,不然会卡在安装包丢失或损坏
  • 廖雪峰-JavaScript教程-PDF版

    热门讨论 2017-02-18 01:23:43
    廖雪峰老师官方的JavaScript教程的PDF版本
  • JavaScript帮助文档中文版

    千次下载 热门讨论 2016-05-31 22:07:32
    JScript的帮助文档,因为和JavaScript的内容差不多,可以作为JavaScript的帮助文档来使用。
  • javascript实现商品购物车功能

    热门讨论 2016-09-27 21:03:37
    javascript实现购物车,完成从商品页向购物车中添加商品,购物车中删除商品,更改商品数量,删除商品,全选单选等购物车操作,涉及到javascript中BOM,DOM,json,cookie等知识点的应用操作,综合性较强,对于...
  • JavaScript 是脚本语言,是一种解释性脚本语言(代码不进行预编译)

    Web前端基础:

    Web前端工具:

    基本概念

    概念

    JavaScript 是脚本语言,是一种解释性脚本语言(代码不进行预编译)
    JavaScript 是一种轻量级的编程语言。
    JavaScript 是可插入 HTML 页面的编程代码
    JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行
    JavaScript 很容易入门

    作用

    1. 为网页添加各式各样的动态功能,
    2. 为用户提供更流畅美观的浏览效果。 通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的

    用法

    HTML页面中的JavaScript

    在html页面中的脚本必须位于script围堵标签之间,script标签放在head中可以,body中也可以, 放在最后也可以,对位置要求不严格

    我们可以在 HTML 文档中放入不限数量的script标签,通常的做法是把内容统一放入head或者页 面底部。这样就可以把它们安置到同一处位置,不会干扰页面的内容

    PS:有些案例中可能会在 script 标签中出现type=“text/javascript”。现在完全可以省略了,JavaScript已经 是所有现代浏览器以及 HTML5 中的默认脚本语言

    <!DOCTYPE html>
    <html>
        <head>
    		<meta charset="utf-8" />
    		<title>JavaScript的用法</title> 
    		<script>
    	            alert("hello JavaScript1-1");
    	   	</script>
    		<script>
    	            alert("hello JavaScript1-2");
    	    </script>
     	</head>
        <body>
    		<script>
                alert("hello JavaScript2-1");
            </script>
    		<script>
                alert("hello JavaScript2-2");
            </script>
        </body>
    </html>
    <script>
        alert("hello JavaScript3-1");
    </script>
    <script>
        alert("hello JavaScript3-2");
    </script>
    

    外部的JavaScript

    可以把脚本保存到外部文件中。外部文件通常包含被多个网页使用的代码。外部 JavaScript 文件的文件扩展名是 .js。

    当我们使用外部文件时,在HTML页面的script 标签的 “src” 属性中设置该 .js 文件:

    myScript.js文件 //外部js文件中不能有script标签,直接编写JavaScript脚本代码即可 function fun1(){
        alert("hello JavaScript");
    }
    

    .html文件

    <!DOCTYPE html>
        <html>
            <head>
                <script src="js/myScript.js"/>
            </head>
            <body>
                <script>
    				fun1();//调用脚本中的内容s 
    			</script>
            </body>
    </html>
    外部文件引入一次即可,在head或者body中都可以。
    

    PS:外部脚本不能包含 script 标签。

    标签属性中的JavaScript

    直接编写在HTML标签的一些属性中,用于简单的JavaScript代码的编写,用的偏少。

    <a href="javascript:alert('ok')">登录</a>
    

    JavaScript显示数据

    使用window.alert()弹出框
    PS:这里的window可以省略,等价于alert(“hello world”);

    使用document.write()将内容写入到html文档

    使用innerHTML写入到html元素

    在这里插入图片描述

    JavaScript的注释

    JavaScript注释与java的单行和多行注释相同。
    单行注释以 // 开头。
    多行注释以 /* 开始,以 */ 结尾。

    JavaScript基本语法

    JavaScript 是一个脚本语言。它是一个轻量级,但功能强大的编程语言。

    JavaScript语法跟Java很相似,但是也有区别。JavaScript是弱语言类型,即有些时候有些错误不影响运行,但是依然推荐大家按照规范去编写代码,语言弱,程序员不能弱。

    变量

    声明变量的关键字:var
    语法:var 变量名称;
    
    var myCompany; //声明变量 
    myCompany='开课吧';//赋值 
    var x=5;//声明的同时赋值
    var y=6;
    var z=x+y;//变量也可以存储表达式
    

    变量的命名规则

    • 变量必须以字母开头
    • 变量也能以 $ 和 _ 符号开头
    • 变量名称对大小写敏感(y 和 Y 是不同的变量) 不能使用关键字保留字

    变量的命名规范:

    • 见名知意 。例如:breadPirce,userService等,避免无意义的a,b,c等
    • 推荐驼峰命名法,即第一个单词的首字母小写,以后每个单词的首字母大写。例如lastName

    JavaScript的语句

    JavaScript 语句向浏览器发出的命令。语句的作用是告诉浏览器该做什么。

    JavaScript 是脚本语言,浏览器会在读取代码时,逐行地执行脚本代码。而对于传统编程来说,会在执 行前对所有代码进行编译。

    JavaScript中也有分支结构和循环结构,语法与java类似,此处就不再深入讲解。细节上的内容等我们 后面使用过的时候再给大家单独指出。

    PS:一般一行只写一条语句,每句结尾编写分号结束。

    JavaScript的数据类型

    值类型(基本类型)

    字符串String

    字符串是存储字符的变量。字符串可以是引号中的任意文本。必须使用单引号或双引号;

    var myCompany; //声明变量 myCompany='开课吧'; //赋值 var x=5;//声明的同时赋值
    var y=6;
    var z=x+y;//变量也可以存储表达式
    var gameName="英雄联盟";
    var hairstylist='tony'; //PS:注意引号嵌套
    var message1='我的发型师是"tony"老师'; 
    var message2="我的发型师是'tony'老师";
    

    布尔Boolean

    只能有两个值:true 或 false。

    var isUnderstand = true;
    var isSingle = false;
    

    空Null

    var email = null;
    

    未定义Undefined
    表示变量不含有值。可以通过将变量的值设置为 null 来清空变量。
    共有4中情况会出现undefined的值

    1. 变量声明且没有赋值
    var obj; 
    alert(obj);//obj值为undefined
    
    1. 获取对象中不存在的属性时
    var obj;
    alert(obj.name);//报错信息: "Uncaught TypeError: Cannot read property 'name' of undefined"
    
    1. 函数需要实参,但是调用时没有传值,形参是undefined;

    2. 函数调用没有返回值或者return后没有数据,接收函数返回的变量是undefined

    function printNum(num){
        alert(num);
    }
    var result=printNum();//调用函数未传递参数,执行函数的时候num的值是undefined alert(result);
    //result的值也是undefined,因为printNum()没有返回值
    

    引用数据类型

    对象(Object)、数组(Array)、函数(Function),后续章节详细介绍。

    JavaScript拥有动态类型

    JavaScript 拥有动态类型。这意味着相同的变量可用作不同的类

    var param; // param类型为 undefined 
    param = 5; // 现在 param 为数字
    param = "John"; // 现在 param 为字符串
    
    PS:虽然JavaScript支持这种写法,但是我不推荐这种写法。大家尽量开始声明变量的时候就确定好将要 盛放什么类型的值,以后尽量不随意改变。
    

    JavaScript中的运算符

    运算符类型符号
    算数运算符±* /%、++、 –
    赋值运算符:=、 +=、-=、*=、 /=、%=
    字符串的连接符+
    逻辑运算符&&
    条件运算符?:
    比较运算符== 、!=、> 、<、 >=、 <=

    比较特殊的运算符:

    比较运算描述
    ===绝对等于(值和类型均相等)
    !==不绝对等于(值和类型有一个不相等,或两个都不相等)
    var x=5;
    var  res=(x===5); // true
    res=(x==='5');// false
    res=(x!==5); // false
    res=(x!=='5');// true
    

    JavaScript对象

    JavaScript的String对象

    String对象属性–长度属性

    var str="我喜欢看NBA,最喜欢的球员是\'小学生\'库里"; //注意:字符串中出现的\'是一个字符,转义为一个单引号 
    console.log(str); //获取字符串的长度:,切记:所有转移符号的长度都算一个,即\'长度为1 
    console.log("字符串的长度="+str.length);//22
    

    JavaScript的Array对象

    Array 对象用于在变量中存储多个值,也就是数组

    声明数组
    在这里插入图片描述

    数组的长度 length属性

    var nameArr=["宝玉","黛玉","湘云"];
    var len=nameArr.length; //获取数组的长度,因为是属所以不是length()
    

    JavaScript的Date对象

    创建日期对象

    var date1 = new Date();
    var date2 = new Date(milliseconds);
    var date3 = new Date(dateString);
    var date4 = new Date(year, month, day, hours, minutes, seconds, milliseconds);
    

    日期对象的常用方法

    方法描述
    getDate()从 Date 对象返回一个月中的某一天 (1 ~ 31)
    getDay()从 Date 对象返回一周中的某一天 (0 ~ 6)
    getFullYear()从 Date 对象以四位数字返回年份
    getHours()返回 Date 对象的小时 (0 ~ 23)
    getMinutes()返回 Date 对象的分钟 (0 ~ 59)
    getMonth()从 Date 对象返回月份 (0 ~ 11)
    getSeconds()返回 Date 对象的秒数 (0 ~ 59)
    setDate()设置 Date 对象中月的某一天 (1 ~ 31)
    setFullYear()设置 Date 对象中的年份(四位数字)
    setHours()设置 Date 对象中的小时 (0 ~ 23)
    setMinutes()设置 Date 对象中的分钟 (0 ~ 59)
    setSeconds()设置 Date 对象中的秒钟 (0 ~ 59)
    setMonth()设置 Date 对象中月份 (0 ~ 11)

    JavaScript的Math对象

    Math常用属性

    var pi=Math.PI;//返回圆周率
    

    Math常用方法

    var num=Math.random();// 返回 0 ~ 1 之间的随机数。 
    var max=Math.max(12,34,-90,9);//返回 n个数值中的最大值。
    var min=Math.min(12,34,-90,9);//返回 n个数值中的最小值。
    

    JavaScript的函数

    JavaScript的常用全局函数

    JavaScript中有个常用的全局属性NaN,即非数值(Not a Number),NaN 属性用于引用特殊的非数字 值,该属性指定的并不是不合法的数字

    isNaN(param)

    用于检查其参数是否是非数值字
    是数值的返回false,不是数值返回true

    console.log(isNaN(666));//false
    console.log(isNaN(1+2));//false
    console.log(isNaN("hello"));//true
    

    parseFloat(String)

    可解析一个字符串,并返回一个浮点数。该函数指定字符串中的首个字符是否是数字。如果是,则对字符串进行解析,直到到达数字的末端为止,然后以数字返回该数字,而不是作为字符串。

    console.log(parseFloat("66"));//66 
    console.log(parseFloat("199.99"));//199.99 
    console.log(parseFloat("1024 2048 4096"));//1024 
    console.log(parseFloat(" 128 "));//128 
    console.log(parseFloat("10年"));//10 
    console.log(parseFloat("今天是8号"));//NaN
    
    • 字符串中只返回第一个数字。
    • 开头和结尾的空格是允许的。
    • 如果字符串的第一个字符不能被转换为数字,那么 parseFloat() 会返回 NaN。

    parseInt(string,radix)

    可解析一个字符串,并返回一个整数

    参数描述
    string必需,要被解析的字符串。
    radix可选,表示要解析的数字的基数。该值介于 2 ~ 36 之间

    当参数 radix 的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。
    当忽略参数 radix , JavaScript 默认数字的基数如下:

    • 如果 string 以 “0x” 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数
    • 如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进 制或十六进制的数字
    • 如果 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数
    console.log(parseInt("66"));//66 
    console.log(parseInt("199.99"));//199 
    console.log(parseInt("1024 2048 4096"));//1024 
    console.log(parseInt(" 128 "));//128 
    console.log(parseInt("10年"));//10 
    console.log(parseInt("今天是8号"));//NaN
    console.log(parseInt("10",10));//10
    console.log(parseInt("010"));//10
    console.log(parseInt("10",8));//8
    console.log(parseInt("0x10"));//16
    console.log(parseInt("10",16));//16 
    
    PS:旧浏览器由于使用旧版本的ECMAScript(ECMAScript版本小于ECMAScript 5,当字符串以"0"开 头时默认使用八进制,ECMAScript 5使用的是十进制),所以在解析("010") 将输出8
    • 只有字符串中的第一个数字会被返回。
    • 开头和结尾的空格是允许的。
    • 如果字符串的第一个字符不能被转换为数字,那么 parseInt() 会返回 NaN。 在字符串以"0"为开始时旧的浏览器默认使用八进制基数。ECMAScript 5,默认的是十进制 的基数。

    JavaScript的自定义函数

    自定义函数语法
    使用function关键字定义函数

    function 自定义函数名称(参数列表){
    	 //函数体
    }
    

    自定义函数实例
    注意:1、函数的形参直接写参数名称,不需要声明类型,即不需要写var.
    2、函数的返回取决于函数体中是否有return关键字。

    在这里插入图片描述

    JavaScript的匿名函数

    在这里插入图片描述

    JavaScript变量的作用域

    局部 JavaScript 变量

    在 JavaScript 函数内部声明的变量(使用 var)是 变量,所以只能在函数内部访问。

    在不同的函数中可以声明名称相同变量,因为局部变量出该函数就失效了。

    全局 JavaScript 变量

    在函数外声明的变量是 变量,网页上的所有脚本和函数都能访问它。

    <script>
    	var userId = 1001; //全局变量:整个script脚本中都可用,要注意先后顺序
    	function printMessage() {
    		var userName = "李白";//局部变量:只在当前函数中生效 
    		document.write(userId);//使用全局变量的时候,保证使用(方法被调用)之前定义并赋值
    		document.write(message);
        printMessage();
    </script>
    <script>
        function printMessage2() {
    		var userName2 = "李白2";
    		document.write(userId);//这里也可以使用userId 
    		//document.write(userName1);//错误:调用不到printMessage函数中的局部变量 
    		document.write(userName2);//正确:可以使用自己函数中的局部变量
    }
    </script>
    

    变量的生命周期

    JavaScript 变量的生命期从它们被声明的时间开始。
    局部变量会在函数运行以后被删除。全局变量会在页面关闭后被删除。

    JavaScript自定义对象

    对象也是一个变量,但对象可以包含多个值(多个变量)

    定义对象

    对象中可以有属性,也可以有方法

    在这里插入图片描述

    对象的属性

    可以说 “JavaScript 对象是变量的容器”。
    但是,我们通常认为 “JavaScript 对象是键值对的容器”。
    键值对通常写法为 name : value (键与值以冒号分割)。
    键值对在 JavaScript 对象通常称为 对象属性。

    访问对象的属性

    //访问对象的属性
    //方式1:
    var n = student.name;
    //方式2:
    var n2 = student["name"];
    

    访问对象的方法

    在这里插入图片描述

    JavaScript Window–浏览器对象模型

    浏览器对象模型 (BOM) 使 JavaScript 有能力与浏览器"对话"。

    BOM:Browser Object Model,中文浏览器对象模型。

    虽然现在BOM尚无正式标准,但是由于现代浏览器已经(几乎)实现了 JavaScript 交互性方面的相同 方法和属性,因此window常被认为是 BOM 的方法和属性。

    window对象

    所有浏览器都支持 window 对象。它表示浏览器窗口。( 没有应用于 window 对象的公开标准,不过所有浏览器都支持该对象)。

    所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。 全局变量是 window 对象的属性。

    全局函数是 window 对象的方法。

    Window 对象表示浏览器中打开的窗口。

    window对象属性

    属性描述
    document对 Document 对象的只读引用
    history对 History 对象的只读引用
    location用于窗口或框架的 Location 对象
    name设置或返回窗口的名称

    history对象

    window.history 对象包含浏览器的历史。
    window.history对象在编写时可不使用 window 这个前缀。

    常用方法:

    • history.back() - 与在浏览器点击后退按钮相同
    • history.forward() - 与在浏览器中点击向前按钮相同
    • history.go(1/-1)
      参数为1:等同于 history.forward(),
      参数为-1,等同于 history.back()
    <a href="javascript:window.history.forward()">前进</a> 
    <a href="javascript:window.history.back()">后退</a>
    <a href="javascript:window.history.go(1)">前进go</a> 
    <a href="javascript:window.history.go(-1)">后退go</a>
    

    location对象

    window.location 对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面。

    常用属性和方法:

    • window.location 对象在编写时可不使用 window 这个前缀。
    • href 当前窗口正在浏览的网页地址
    • replace(url) 转向到url网页地址
    • reload() 重新载入当前网址,如同按下刷新按钮
    <a href="javascript:alert(window.location.href)">获取当前页面的URL地址</a>
    <a href="javascript:window.location.reload()">刷新</a><br />
    <a href="javascript:window.location.replace('index.html')">跳转到index</a><br />
    <a href="javascript:location.replace('https://www.baidu.com')">跳转到百度</a><br />
    

    window对象方法

    方法描述
    alert()显示带有一段消息和一个确认按钮的警告框
    confirm()显示带有一段消息以及确认按钮和取消按钮的对话框
    prompt()显示可提示用户输入的对话框
    open()设置或返回窗口的名称
    close()打开一个新的浏览器窗口或查找一个已命名的窗口
    setTimeout()关闭浏览器窗口
    setInterval()在指定的毫秒数后调用函数或计算表达式
    clearInterval()取消由 setInterval() 设置的 timeout
    clearTimeout()取消由 setTimeout() 方法设置的 timeout

    打开和关闭浏览器案例

    <a href="javascript:window.open('https://www.baidu.com')">打开百度</a> 
    <a href="javascript:window.open('index.html')">打开-index</a>
    <a href="javascript:window.close()">关闭当前页面</a>
    

    弹框案例

    <script>
    	//window对象常用的弹框方法
    	//1、基本弹框
    	window.alert("只有一个确定按钮的对话框"); 
    	//2、对话框:有确定和取消两个看你,点击确定返回true,点击取消返回false 
    	var res=window.confirm("确认要关闭吗?");
    	if(res){
    		alert("点击了确定按钮"); 
    	}else{
    		alert("点击取消按钮"); 
    	}
    	//3、输入框:prompt(提示信息,默认值) 
    	var age=prompt("请输入年龄:",19);
    	alert("输入的年龄信息是:"+age);
    </script>
    

    定时器案例

    <div id="today1"> 
    	div--显示时间1
    </div>
    <a href="javascript:window.clearInterval(flag1)">停止定时器clearInterval</a> 
    <div id="today2">
    	div--显示时间2 
    </div>
    <a href="javascript:window.clearTimeout(flag2)">停止定时器clearTimeout</a> 
    <script>
    	function showTime1(){
    	  	var time=new Date();
            var y=time.getFullYear();
            var mon=time.getMonth();
            var d=time.getDate();
    		var h=time.getHours();
    		var m=time.getMinutes();
    		var s=time.getSeconds(); 			
    		document.getElementById("today1").innerHTML=y+"年"+mon+"月"+d+"日
    "+h+":"+m+":"+s;
        }
    	//定时器setInterval(定时调用的函数,时间间隔毫秒)
        var flag1=window.setInterval("showTime1()",1000);
    </script>
    <script>
        function showTime2(){
            var time=new Date();
            var y=time.getFullYear();
            var mon=time.getMonth();
            var d=time.getDate();
            
            var h=time.getHours();
            var m=time.getMinutes();
            var s=time.getSeconds();
            
    		document.getElementById("today2").innerHTML=y+"年"+mon+"月"+d+"日 "+h+":"+m+":"+s;
            flag2=window.setTimeout("showTime2()",1000);
        }
    	//在指定的毫秒数后调用函数或计算表达式。
        var flag2=window.setTimeout("showTime2()",1000);
    </script>
    

    JavaScript之事件

    HTML 事件是发生在 HTML 元素上的事情。当在 HTML 页面中使用 JavaScript 时, JavaScript 可以触发这些事件。

    HTML事件

    HTML 事件可以是浏览器行为,也可以是用户行为。

    例如页面加载完成、你点击个按钮、文本框输入了文字等等,都是HTML事件的案例。

    通过当事件发生时,我们希望可以做些事情,例如点击完毕按钮之后希望跳转页面、文本框输入完毕之 后验证有效性等,那么这些要做的事情我们就可以通过JavaScript实现。

    常用的HTML事件

    事件描述
    onchangeHTML 元素改变
    onclick用户点击 HTML 元素
    onmouseover用户在一个HTML元素上移动鼠标
    onmouseout用户从一个HTML元素上移开鼠标
    onkeydown用户按下键盘按键
    onload浏览器已完成页面的加载
    onfocus元素获取焦点时触发
    onblur元素失去焦点时触发
    <script>
    	function fun1(){
    		alert('选择的内容发生了变化');
        }
        
        function fun2(){
    		alert("触发了单击事件"); 
    	}
    	
    	function fun3() {
    	 	document.getElementById("btn").innerHTML="鼠标移动到按钮上了";
        }
        
        function fun4() {
    		document.getElementById("btn").innerHTML="点击我试试"; 
    	}
    	
    	function fun5() { 
    		alert("键盘按下了");
        }
        
        function fun6() {
    		alert("获取到了焦点");
    	}
    	
    	function fun7() { 
    		alert("input失去了焦点");
        }
        
        function myLoad(){
    		alert("页面加载完毕"); 
    	}
    </script>
        <body onload="myLoad()">
            <input id="userName" onkeydown="fun5()" onfocus="fun6()" onblur="fun7()"/>
            <input id="password" type="password" />
            <button id="btn" type="button" onclick="fun2()"  
    		onmouseover="fun3()" onmouseout="fun4()">点击我试试</button>
    		
    		<select id="month" onchange="fun1()"> 
    			<option>1月份</option> 
    			<option>2月份</option>
    	    </select>
    	</body>
    

    JavaScript之DOM模型

    通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素。

    DOM:Document Object Model,文档对象模型

    当网页被加载时,浏览器会创建页面的文档对象模型

    HTML DOM 模型被构造为对象的树:

    在这里插入图片描述
    通过可编程的对象模型,JavaScript 获得了足够的能力来创建动态的 HTML:

    • JavaScript 能够改变页面中的所有 HTML
    • 元素 JavaScript 能够改变页面中的所有 HTML 属性
    • JavaScript 能够改变页面中的所有 CSS 样式
    • JavaScript 能够对页面中的所有事件做出反应

    document对象

    当浏览器载入 HTML 文档, 它就会成为 Document 对象

    Document 对象是 HTML 文档的根节点
    Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问

    提示: Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问。

    document对象常用方法

    查找 HTML 元素常用方法

    方法描述
    document.getElementById()返回对拥有指定 id 的第一个对象的引用。
    document.getElementsByClassName()返回文档中所有指定类名的元素集合,作为 NodeList 对象
    document.getElementsByTagName()返回带有指定标签名的对象集合
    document.getElementsByName()返回带有指定名称的对象集合
    <script>
        function myLoad(){
    		//页面加载完毕之后再去获取页面上的元素,否则获取不到
    		//根据ID 获取元素,只能获取到唯一元素(如果有重名的ID元素,获取到的是第一个元素) var div=document.getElementById("myDiv");
    		console.log(div);
    		//根据指定的类样式的名称获取元素,返回集合
    		var list=document.getElementsByClassName("demo"); 		
    		console.log("根据类样式的名称获取到的元素的集合长度是:"+list.length); for(var i=0;i<list.length;i++){
            console.log(list[i]);
    	}
    	
    	//根据指定HTML标签名称获取元素,返回集合
    	var list2=document.getElementsByTagName("li"); 
    	console.log("根据标签的名称获取到的元素的集合长度是:"+list2.length); 
    	for(var i=0;i<list2.length;i++){
                console.log(list2[i]);
            }
    	//根据指定HTML元素的name属性获取元素,返回集合
    	var list3=document.getElementsByName("myli"); console.log("根据标签的名称属性获取到的元素的集合长度是:"+list3.length); 
    	for(var i=0;i<list3.length;i++){
                console.log(list3[i]);
        	}
    }
    </script>
    <body onload="myLoad()">
        <p  class="demo"></p>
        <div id="myDiv" class="demo">
    		div
        </div>
        <ul class="demo">
            <li>li11111111111</li>
            <li name="myli">li11111111111</li>
            <li>li11111111111</li>
            <li name="myli">li11111111111</li>
        </ul>
    </body>
    

    修改 HTML 内容和属性

    修改内容

    修改 HTML 内容的最简单的方法是使用 innerHTML 属性

    修改 HTML 元素的内容的语法:
    document.getElementById(id).innerHTML= HTML

    PS: 绝对不要在文档(DOM)加载完成之后使用 document.write()。这会覆盖该文档

    修改 HTML 属性

    修改 HTML 元素属性的语法: 
    方式1:
    document.getElementById(id).attribute=新属性值;
    
    方式2:
    document.getElementById(id).setAttribute(属性名,属性值);
    
    <div id="mydiv">div</div>
    var mydiv=document.getElementById("mydiv"); 
    mydiv.innerHTML="新的div内容"; document.getElementById("myimg").src="x1.jpg";
    
    <h1 style="color: green;" id="myh1">hello world</h1> var h1=document.getElementById("myh1"); h1.setAttribute("class","bg");//设置属性 
    console.log(h1.getAttribute("class"));//获取属性class 
    console.log(h1.getAttribute("style"));//获取属性style
    

    修改 HTML 元素的css

    修改 HTML 元素css的语法:
    document.getElementById(id).style.property=新样式

    document.getElementById("myli").style.color="blue"; 
    document.getElementById("myli").style.fontFamily="微软雅黑"; 
    document.getElementById("myli").style.fontSize="24px";
    

    HTML DOM 元素 (节点)

    创建新的 HTML 元素

    要创建新的 HTML 元素 (节点)需要先创建一个元素,然后在已存在的元素中添加它。

    <button type="button" onclick="createNewP()">动态添加一个元素-- appendChild</button>
    <button type="button" onclick="createNewP2()">动态添加一个元素-- insertBefore</button>
    <div id="div1">
    	<p id="p1">这是段落1</p> 
    	<p id="p2">这是段落2</p>
    </div>
    <script>
    	function createNewP(){
    		var newElementP=document.createElement("p");//创建一个新的段落元素
    		var text=document.createTextNode("这是我新创建的段落");//新创建的文本节点 //将文本的节点添加到新创建的元素中
    		newElementP.appendChild(text);
    		//获取一个页面已经存在的元素
    		var div=document.getElementById("div1"); //添加新创建的元素p到已经存在的元素div中
    		div.appendChild(newElementP);
    	}
    	function createNewP2(){
    		var newElementP=document.createElement("p");//创建一个新的段落元素
    		var text=document.createTextNode("这是我新创建的段落p2");//新创建的文本节点 //将文本的节点添加到新创建的元素中
    		newElementP.appendChild(text);
    //获取一个页面已经存在的元素
    		var div=document.getElementById("div1"); 
    		var p1=document.getElementById("p1");
    		//添加新创建的元素p到已经存在的元素div中,指定插入到段落P1前面
            div.insertBefore(newElementP,p1);
        }
    </script>
    

    替换 HTML 元素

    -replaceChild()方法

    <div id="div1">
    	<p id="p1">这是一个段落。</p>
    	<p id="p2">这是另外一个段落。</p>
    </div>
    <button type="button" onclick="changeElemnt()">替换p1</button> <script>
    	function changeElemnt(){
    		var newElementP=document.createElement("p");//创建一个新的段落元素
    		var text=document.createTextNode("这是我新创建的段落p");//新创建的文本节点 //将文本的节点添加到新创建的元素中
    		newElementP.appendChild(text);
    //获取要被替换的元素p1及其父元素div
    		var div=document.getElementById("div1");
    		var p1=document.getElementById("p1");
    //将div中的元素p1替换为新创建的元素
    		div.replaceChild(newElementP,p1);
    	}
    </script>
    

    删除HTML元素

    -removeChild()方法

    <div id="div1">
    	<p id="p1">这是一个段落。</p>
    	<p id="p2">这是另外一个段落。</p>
    </div>
    <button type="button" onclick="deleteElement()">删除p1-方式1</button> <button type="button" onclick="deleteElement()">删除p1-方式2</button> 
    <script>
    	function deleteElement(){
    		var div=document.getElementById("div1"); 
    		var p1=document.getElementById("p1"); //从父元素div中删除子元素p1 div.removeChild(p1);
        }
        function deleteElement2(){
    		var p1=document.getElementById("p1"); //p1.parentNode:作用就是获取要删除元素p1的父元素div p1.parentNode.removeChild(p1);
    	}
    </script>
    

    表单验证

    表单验证意义与场景

    1. 降低服务器压力
      拦截不合格的数据,避免直接提交到服务器,可以显著降低服务器开销
    2. 提升用户体验
      早期的互联网,表单项都是非常多的,注册个账号,经常需要填写20+个字段。而其中有一个填写不正 确就要等待几十秒时间。如果有了表单验证,反馈是实时的,而且脚本还能把你定位到填写错误的具体 字段。现在虽然无刷新技术早已普及,但是只依赖服务端验证,还是会有几百毫秒的延迟,实际使用会 有一种很难受的粘滞感。

    表单验证常用事件与属性

    表单经常需要做一些非空验证、长度验证、合法性验证等。

    <!DOCTYPE html>
    <html>
        <head>
    		<meta charset="UTF-8"> 
    		<title>表单验证</title> 
    		<script>
    			function validateName(){
    //所有的表单项元素都value属性
    				var name=document.getElementById("userName").value; 
    				var msg=document.getElementById("nameMsg"); 		
    				if(name==null || name ==""){
    					msg.innerHTML="用户名不能为空!"; 		
    					msg.style.color="red";
    					return false;
    				} else if(name.length<6){ 
    					msg.innerHTML="用户名长度必须为大于6的!"; 	
    					msg.style.color="red";
    					return false;
    				}
    			 	msg.innerHTML="用户名可用"; msg.style.color="green"; 
    			 	return true;
    }
                function validatePwd(){
                    var password1=document.getElementById("password1").value;
                    var msg=document.getElementById("pwdMsg1");
                    if(password1==null || password1 ==""){
    					msg.innerHTML="密码不能为空!"; msg.style.color="red";
    					return false;
    				} else if(password1.length<8){ 
    					msg.innerHTML="密码的长度必须为大于8的!"; 		
    					msg.style.color="red";
    					return false;
    				}
    				msg.innerHTML="密码合法"; msg.style.color="green"; 
    				return true;
                }
                
                function confirmPwd(){
                    var pwd1=document.getElementById("password1").value;
                    var pwd2=document.getElementById("password2").value;
                    var msg=document.getElementById("pwdMsg2");
                    if(pwd1!=pwd2){
    					msg.innerHTML="两次输入的密码不一致!";
    					msg.style.color="red";
                        return false;
                    }
    				msg.innerHTML="两次输入的密码一致"; 		
    				msg.style.color="green";
    				return true;
    			}
    			
                function validateGender(){
                    var gender=document.getElementById("gender").value;
                    if(gender==-1){
    					alert("性别为必选项!");
                        return false;
                    }
                    return true;
                }
                function register(){
                    return validateName()&&validatePwd()&&confirmPwd()&&validateGender();
                }
            </script>
        </head>
    <body>
    	<h1>英雄会注册</h1>
    	<form action="提交.html" method="get" onsubmit="return register()">
    		*用户名:<input type="text" id="userName" placeholder="请输入用户名" onblur="validateName()" />
    		<span id="nameMsg">用户名长度至少6</span><br />
    	*密码:<input type="password" id="password1" placeholder="请输入密码" onblur="validatePwd()"/>
    		<span id="pwdMsg1">密码长度至少8</span><br />
    	*确认密码:<input type="password" id="password2" placeholder="请确认密 码" onblur="confirmPwd()" />
    		<span id="pwdMsg2">确认密码与密码一致</span><br /> 
    	*性别:<select id="gender">
    			<option value="-1">请选择性别</option>
    			<option value="0"></option>
    			<option value="1"></option>
    		</select><br /><br />
    	<button type="submit">注册</button>
    	<button type="reset">重置</button>
            </form>
        </body>
    </html>
    

    JavaScript的 RegExp 对象

    概念

    RegExp:是正则表达式(regular expression)的简写。

    正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)使用单个字符串来 描述、匹配一系列符合某个句法规则的字符串搜索模式。搜索模式可用于文本搜索和文本替换。

    语法

    语法:

    var reg=new RegExp(/正则表达式主体/,修饰符(可选)); 或更简单的方法
    var reg=/正则表达式主体/修饰符(可选);
    
    案例:
    var reg=new RegExp(/kaikeba/i);
    var reg = /kaikeba/i; //此处定义了一个一个正则表达式。 kaikeba 是一个正则表达式主体 (用于检索)。
    i 是一个修饰符 (搜索不区分大小写)

    修饰符

    修饰符描述
    i执行对大小写不敏感的匹配
    g执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)
    m执行多行匹配

    正则表达式模式

    方括号用于查找某个范围内的字符:

    表达式描述
    [a-z]查找方括号之间的任何字符
    [0-9]查找任何从 0 至 9 的数字
    (xIy)查找任何以 I 分隔的选项

    元字符是拥有特殊含义的字符:

    元字符描述
    \d查找数字
    \s查找空白字符
    \b匹配单词边界
    \uxxxx查找以十六进制数 xxxx 规定的 Unicode 字符

    量词:

    量词描述
    n+匹配任何包含至少一个 n 的字符串
    n*匹配任何包含零个或多个 n 的字符串
    n?匹配任何包含零个或一个 n 的字符串

    正则表达式的方法test(str)

    test() 方法用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。

    var reg = /budingCode/i;
    var res=reg.test("欢迎关注budingCode"); 
    console.log(res);//true
    
    var reg = /^[a-zA-Z]+[\u4e00-\u9fa5]*[0-9]$/; 
    var str="a公司拼音为9";
    var res=reg.test(str); console.log(res);//true 
    console.log(reg.test("a你好239"));//false
    

    常用的正则表达式校验案例

    <script> 
    	/*检查输入的身份证号是否正确*/ 
    	function checkCard(str) {
    		/*15位数身份证正则表达式:
    		* 编码规则顺序从左至右依次为6位数字地址码,6位数字出生年份后两位及日期,3位数字顺序
    		[1-9]\d{5} 						前六位地区,非0打头
    		\d{2}							出生年份后两位00-99
    		((0[1-9])|(10|11|12))			01-12月
    		(([0-2][1-9])|10|20|30|31)		01-31天
    		\d{3}							顺序码三位,没有校验码
    				*/
            var arg1 = /^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$/;
            if (arg1.length == 15 && !arg1.test(arg1)) {
                 return false;
    		}
    		
    		/*18位数身份证正则表达式:
    		* 编码规则顺序从左至右依次为6位数字地址码,6位数字出生年份后两位及日期,3位数字顺序
    		[1-9]\d{5} 						前六位地区,非0打头
    		(18|19|([23]\d))\d{2}			出生年份后两位00-99
    		((0[1-9])|(10|11|12))			01-12月
    		(([0-2][1-9])|10|20|30|31)		01-31天
    		\d{3}[0-9Xx]					顺序码三位,+ 一位校验码
    				*/
    		var arg2 = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
    		 if (arg2.length == 18 && !arg2.test(sfzhmcode)){
                 return false;
             }
            return true;
    	}
    
    	/*是否是小数*/
    	function isDecimal(strValue) {
            var objRegExp = /^\d+\.\d+$/;
            return objRegExp.test(strValue);
        }
        
    	/*校验是否中文名称组成 */ 
    	function ischina(str) {
            var reg = /^[\u4E00-\u9FA5]{2,4}$/;
            return reg.test(str);
        }
        
    	/*校验是否全由8位数字组成 */ 
    	function isNum(str) {
            var reg = /^[0-9]{8}$/;
            return reg.test(str);
        }
        
    	/*校验电话码格式 :座机和手机*/ 
    	function isTelCode(str) {
            var reg = /^((0\d{2,3}-\d{7,8})|(1[345789]\d{9}))$/;
            return reg.test(str);
        }
        
        /*校验手机号*/
    	function isPhoneNum(str) {
    	//如果你要精确验证手机号码,那个你可以使用第一个正则。这是根据电信,移动,联通目前发行的号码来的。验证比较精确。
            var reg = /^1[3|4|5|7|8][0-9]{9}$/;
    // 如果因为现有的号码不能满足市场需求,电信服务商会增大号码范围。所以一般情况下我们 只要验证手机号码为11位,且以1开头。
            var reg = /^^1[0-9]{10}$$/;
            return reg.test(str);
        }
        
    	/*校验邮件地址是否合法 */ 
    	function IsEmail(str) {
            var reg = /^\w+@[a-zA-Z0-9]{2,10}(?:\.[a-z]{2,4}){1,3}$/;
            return reg.test(str);
        }
        
    	/*检查输入的URL地址是否正确 */ 
    	function checkURL(str) {
            if(str.match(/http(s)?:\/\/[\w.]+[\w\/]*[\w.]*\??[\w=&\+\%]*/i) == null)
                return false;
            } else {
                return true;
            }
    	}
    </script>	
    

    JavaScript案例

    全选/全不选

    在这里插入图片描述

    <!DOCTYPE html>
    <html>
        <head>
    <meta charset="UTF-8"> <title>全选</title> <script>
                function myAll(){
                    var all=document.getElementById("all");
                    var oneList=document.getElementsByName("one");
                    for(var i=0;i<oneList.length;i++){
                        oneList[i].checked=all.checked;
                    }
                }
    			
                function myOne(){
                    var all=document.getElementById("all");
                    var oneList=document.getElementsByName("one");
                    for(var i=0;i<oneList.length;i++){
                        if(oneList[i].checked==false){
                            all.checked=false;
                            return;
    } }
                    all.checked=true;
                }
            </script>
        </head>
        <body>
            <table id="myTable" border="1" cellpadding="0" cellspacing="0" width="90%" height="180px">
                <tr>
    				<th>全选<input id="all" type="checkbox" onclick="myAll()"/>
    				</th> <th>序号</th>
    				<th>名称</th>
    				<th>单价</th>
    				<th>数量</th>
    				<th>总计</th> </tr>
    			</tr>
    			<tr>
    				<td><input name="one" type="checkbox" onclick="myOne()"/></td> 
    				<td>1</td>
    				<td>小熊饼干1</td>
    				<td>¥125</td>
    				<td>1</td>
    				<td>¥125</td>
    			</tr> 
    			<tr>
    				<td><input name="one" type="checkbox" onclick="myOne()"/></td> 
    				<td>1</td>
    				<td>小熊饼干2</td>
    				<td>¥125</td>
    				<td>1</td>
    				<td>¥125</td>
    			</tr> 
    			<tr>
    				<td><input name="one" type="checkbox" onclick="myOne()"/></td> 
    				<td>1</td>
    				<td>小熊饼干3</td>
    				<td>¥125</td>
    				<td>1</td>
    				<td>¥125</td>
    			</tr> 
            </table>
        </body>
    </html>
    
    

    动态表格

    表格的属性和方法描述
    table.rows获取表格中的所有行
    tr.cells获取表格中某一行的所有单元格
    tr.rowIndex获取表格中某一行的下标索引(从0开始)
    td.cellIndex获取单元格的下标索引
    table.insertRow()在表格中创建新行,并将行添加到rows集合中
    table.deleteRow()从表格即rows集合中删除指定行
    tr.insertCell())在表格的行中创建新的单元格,并将单元格添加到cells集合中

    遍历表格中的内容,动态添加行、删除行

    <!DOCTYPE html>
    	<html>
    		<head>
    			<meta charset="UTF-8"> 
    			<title>动态表格</title> 
    			<style>
                td,th{
                    padding: 10px;
    			}
    			</style>
    			<script>
    				function bianli(){
    					var tab=document.getElementById("myTable");//获取到了表格的js对象 //获取表格的所有行
    				var trArr=tab.rows;//遍历行
    				for(var i=0;i<trArr.length;i++){
    					var trObj=trArr[i]; //alert("行的下标索引:"+trObj.rowIndex); //获取每行的单元格的集合
    					var tdArr=trObj.cells;
    //遍历每个单元格
    					var str="";
    					for(var j=0;j<tdArr.length;j++){
    					var tdObj=tdArr[j];
    					var html=tdObj.innerHTML;//获取每个单元格中的内容 
    					var index=tdObj.cellIndex;//获取每个单元格的下标索引 str+=index+"-"+html+"=====";
    				}
    				console.log("行的下标索引:"+trObj.rowIndex+":"+str); }
    			}
    			
    			function addRow(){ //获取到表格的对象
    				var tab=document.getElementById("myTable");
    				//给表格添加一行
    				var newTr=tab.insertRow();//创建了一个空行,在页面上看不出来 //给新创建的行添加列
    				var newTd1=newTr.insertCell();//给新的行创建了一个新的单元格
    				var newTd2=newTr.insertCell();
    				var newTd3=newTr.insertCell();
    				var newTd4=newTr.insertCell();
    				var newTd5=newTr.insertCell();
    				//给每一个单元格中添加内容
    				var num=parseInt(Math.random()*10)+1;
    				newTd1.innerHTML=num;
    				newTd2.innerHTML="小熊饼干"+num;
    				newTd3.innerHTML="$125";
    				newTd4.innerHTML="1";
    				newTd5.innerHTML='<button type="button" onclick="delRow(this)">
    				删除</button>'; 
    			}
    			
    			function delRow(btn){
    				var tab=document.getElementById("myTable"); 
    				//btn:表示点击的当前的删除按钮, 
    				//btn.parentNode获取的按钮的父元素td,btn.parentNode.parentNode获取的按钮的父元素td的父元素tr
    				var trIndex=btn.parentNode.parentNode.rowIndex;
    				//根据行的下标索引删除行
                    tab.deleteRow(trIndex);
                }
            </script>
        </head>
        <body>
    		<button type="button" onclick="bianli()">遍历表格</button>
    		<button type="button" onclick="addRow()">添加</button>
            <table id="myTable" border="1" cellpadding="0" cellspacing="0" width="90%"  style="text-align: center;">
    
    		<tr> 
    			<th>序号</th>
    			<th>名称</th> 
    			<th>单价</th> 
    			<th>数量</th> 
    			<th>总计</th>
    		</tr> 
    		<tr>
    			<td>1</td>
    			<td>小熊饼干1</td>
    			<td>¥125</td>
    			<td>1</td>
    			<td><button type="button" onclick="delRow(this)">删除</button>
    		</tr>
    		<tr>
    			<td>2</td>
    			<td>小熊饼干2</td>
    			<td>¥125</td>
    			<td>1</td>
    			<td><button type="button" onclick="delRow(this)">删除</button>
        	</tr>
    		</table>
        </body>
    </html>
    

    省市级联特效

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
    		<title>省市级联</title> 
    	</head>
        <body>
            <select onchange="changeCity(this.value)">
    			<option>--请选择省份--</option> 
    			<option value="0">北京</option> 
    			<option value="1">浙江省</option> 
    			<option value="2">河北省</option>
    			<option value="3">广东省</option>
            </select>
            	<select id="city">
            </select>
        </body>
    </html>
    <script>
    //创建二维数组存储省份和对应的城市
    	var cityList=new Array();
    	cityList[0] = new Array("朝阳区", "海淀区", "东城区", "西城区"); 
    	cityList[1] = new Array("杭州市", "嘉兴市", "宁波市", "绍兴市"); 
    	cityList[2] = new Array("石家庄市", "唐山市", "承德市", "张家口市");
    	cityList[3] = new Array("广州市", "惠州市", "深圳市", "茂名市");
    	function changeCity(val){ //获取到城市的下拉列表框
    		var city=document.getElementById("city"); //先去清空原有的城市下拉列表内容 city.options.length=0;
    		var arr=cityList[val];
    		for(var i=0;i<arr.length;i++){
    		//创建option元素节点
    		var option=document.createElement("option"); 
    		//设置option元素节点的内容和value 
    		option.innerHTML=arr[i]; 
    		option.value=arr[i]; 
    		//将新创建的option节点添加到城市下拉框中 
    		city.appendChild(option);
    		} 
    	}
    </script>
    
    展开全文
  • JavaScript完全手册全面而详细地介绍了JavaScript的基本概念、编程技巧和属性参考说明。使用本书,你可以使用JavaScript创建动态、灵活的Web页。不管你是一位编程新手还是一位有经验的开发员,你都可以找到自己要找...
  • 学习JavaScript这一篇就够了

    万次阅读 多人点赞 2020-10-24 12:50:06
    目录第一章 JavaScript简介1.1、JavaScript的起源1.2、JavaScript的组成1.3、JavaScript的特点1.4、JavaScript的使用1.4.1、标签引用1.4.2、文件引用1.5、JavaScript的输出1.5.1、页面输出1.5.2、控制台输出1.5.3、...

    目录


    配套资料,免费下载
    链接:https://pan.baidu.com/s/152NnFqzAUx9br2qb49mstA
    提取码:ujyp
    复制这段内容后打开百度网盘手机App,操作更方便哦

    第一章 JavaScript简介

    1.1、JavaScript的起源

    JavaScript诞生于1995年,它的出现主要是用于处理网页中的前端验证。所谓的前端验证,就是指检查用户输入的内容是否符合一定的规则。比如:用户名的长度,密码的长度,邮箱的格式等。但是,有的同学可能会有疑问,这些验证,后端不也可以进行验证吗?确实,后端程序的确可以进行这些验证,但你要清楚,在1995年那个年代,网速是非常慢的,向后端发送一个请求,浏览器很久才能得到响应,那这无疑是一种非常不好的用户体验。

    为了解决前端验证的问题,当时的浏览器巨头NetScape(网景)公司就开发出一种脚本语言,起初命名为LiveScript,后来由于SUN公司的介入更名为了JavaScript。但是你要清楚,Java和JavaScript是没有什么关系的,只不过当时Java非常流行,为了蹭热度,才将LiveScript更名为JavaScript,它们的关系就像雷锋和雷峰塔的关系一样,没啥关系。

    但是,浏览器开发商不止网景一家,还有一个大家都知道的公司,微软公司,它们的主打产品是IE(Internet Explorer)浏览器,当网景公司的Netscape Navigator浏览器推出JavaScript语言时,微软就急了啊,好家伙,人网景都推出了专门用于前端验证的语言,不仅大大减少了后端程序的压力,还提高了用户的体验。我微软这么大的公司不也得整一个,在1996年,微软公司在其最新的IE3浏览器中引入了自己对JavaScript的实现JScript。

    于是在市面上存在两个版本的JavaScript,一个网景公司的JavaScript和微软的JScript,虽然当时浏览器的巨头是网景,但是网景的浏览器是收费的,虽然微软的IE浏览器在全球的市场份额远远不及网景,但是微软的拳头产品是Windows操作系统,每一个操作系统都自带一个IE浏览器并且免费,那么,未来的发展大家可能也想到了,网景让微软给干倒闭了,1998年11月,网景被美国在线(AOL)收购。

    老大哥就是老大哥,为了抢先获得规则制定权,网景最先将JavaScript作为草案提交给欧洲计算机制造商协会,也就是ECMA组织,希望能将JavaScript做成行业标准,最终在网景、SUN以及微软等公司的参与下,由一众程序员和相关组织人员组成的第39技术委员会也就是TC39发布了ECMA-262标准,这个标准定义了名为ECMAScript的全新脚本语言,为啥又来了个ECMAScript?

    因为Java是SUN的商标,SUN授权了NetScape可以叫JavaScript,但是ECMA没有SUN的授权就不能叫JavaScript,哪怕NetScape成员特别希望ECMA把它叫做JavaScript,但是ECMA也有成员并不希望这个标准就叫JavaScript,总之经过几轮磋商和博弈,ECMAScript这个名字就定下来。

    我们可以简单看一下历史事件发展表:

    image-20201012142902870

    1.2、JavaScript的组成

    ECMAScript是一个标准,而这个标准需要由各个厂商去实现,不同的浏览器厂商对该标准会有不同的实现。

    image-20201012144015831

    我们已经知道ECMAScript是JavaScript标准,所以一般情况下这两个词我们认为是一个意思。但是实际上JavaScript的含义却要更大一些。一个完整的JavaScript实现应该由以下三个部分构成:

    image-20201012144120964

    由此我们也知道了我们所要学习的内容就是这三部分,它们具体的含义后边章节会具体介绍。

    1.3、JavaScript的特点

    解释型语言

    JavaScript是一门解释型语言,所谓解释型值语言是指不需要被编译为机器码在执行,而是直接执行。由于少了编译这一步骤,所以解释型语言开发起来尤为轻松,但是解释型语言运行较慢也是它的劣势。不过解释型语言中使用了JIT技术,使得运行速度得以改善。

    动态语言

    JavaScript是一门动态语言,所谓的动态语言可以暂时理解为在语言中的一切内容都是不确定的。比如一个变量,这一时刻是个整型,下一时刻可能会变成字符串了。当然这个问题我们以后再谈。不过在补充一句动态语言相比静态语言性能上要差一些,不过由于JavaScript中应用的JIT技术,所以JavaScript可能是运行速度最快的动态语言了。

    类似于 C 和 Java 的语法结构

    JavaScript的语法结构与C和Java很像,向for、if、while等语句和Java的基本上是一模一样的。所以有过C和Java基础的同学学习起来会轻松很多。不过JavaScript和与Java的关系也仅仅是看起来像而已。

    基于原型的面向对象

    JavaScript是一门面向对象的语言。啥是对象?下次聊。

    Java也是一门面向对象的语言,但是与Java不同JavaScript是基于原型的面向对象。啥是原型?下次聊。

    严格区分大小写

    JavaScript是严格区分大小写的,也就是abc和Abc会被解析器认为是两个不同的东西。

    1.4、JavaScript的使用

    1.4.1、标签引用

    在HTML中在script标签中就可以编写JavaScript代码,以下是一个简单演示。

    <script>
        alert("Hello,World!");
    </script>
    

    1.4.2、文件引用

    在一个单独的js文件中也可以编写JavaScript代码,然后在HTML文件中使用script标签进行引用,以下是一个简单演示。

    main.html

    <script src="main.js"></script>
    

    main.js

    alert("Hello,World!");
    

    1.5、JavaScript的输出

    1.5.1、页面输出

    如何使用JavaScript向页面输出一句话,请参考以下代码。

    <script>
        document.write("Hello,World!");
    </script>
    

    1.5.2、控制台输出

    如何使用JavaScript向控制台输出一句话,请参考以下代码。

    注意:页面按F12弹出控制台

    <script>
        console.log("输出一条日志");//最常用
        console.info("输出一条信息");
        console.warn("输出一条警告");
        console.error("输出一条错误");
    </script>
    

    image-20201025103100826

    1.5.3、弹出窗口输出

    如何使用JavaScript向弹出窗口输出一句话,请参考以下代码。

    <script>
        alert("Hello,World!");
    </script>
    

    1.6、JavaScript的注释

    注释中的内容不会被解析器解析执行,但是会在源码中显示,我们一般会使用注释对程序中的内容进行解释。

    JS中的注释和Java的的一致,分为两种:

    • 单行注释:// 注释内容
    • 多行注释:/* 注释内容 */

    1.6.1、单行注释

    <script>
        // 这是注释内容
        console.log("Hello,World!");
    </script>
    

    1.6.2、多行注释

    <script>
        /**
         * 这是注释内容
         */
        console.log("Hello,World!");
    </script>
    

    第二章 JavaScript基础语法

    2.1、标识符

    所谓标识符,就是指给变量、函数、属性或函数的参数起名字。

    标识符可以是按照下列格式规则组合起来的一或多个字符:

    • 第一个字符必须是一个字母、下划线( _ )或一个美元符号( $ )。
    • 其它字符可以是字母、下划线、美元符号或数字。
    • 按照惯例,ECMAScript 标识符采用驼峰命名法。
    • 标识符不能是关键字和保留字符。

    关键字:

    image-20201012215759481

    保留字符:

    image-20201012215835171

    其它不建议使用的标识符:

    image-20201012215902568

    单个单词的标识符举例:

    name、age、gender、hobby
    

    多个单词的标识符举例:

    studentName、studentAge、studentGender、studentHobby
    

    2.2、字面量和变量

    2.2.1、字面量

    字面量实际上就是一些固定的值,比如:1、2 、3、true、false、null、NaN、“hello”,字面量都是不可以改变的,由于字面量不是很方便使用,所以在JavaScript中很少直接使用字面量,使用的而是变量。

    2.2.2、变量

    变量的作用是给某一个值或对象标注名称。比如我们的程序中有一个值123,这个值我们是需要反复使用的,这个时候 我们最好将123这个值赋值给一个变量,然后通过变量去使用123这个值。

    变量的声明: 使用var关键字声明一个变量。

    var a;
    

    变量的赋值: 使用=为变量赋值。

    a = 123;
    

    声明和赋值同时进行:

    var a = 123;
    

    2.3、数据类型

    2.3.1、类型分类

    数据类型决定了一个数据的特征,比如:123和”123”,直观上看这两个数据都是123,但实际上前者是一个数字,而后者是一个字符串。

    对于不同的数据类型我们在进行操作时会有很大的不同。

    JavaScript中一共有5种基本数据类型:

    • 字符串型(String)
    • 数值型(Number)
    • 布尔型(Boolean)
    • undefined型(Undefined)
    • null型(Null)

    这5种之外的类型都称为Object,所以总的来看JavaScript中共有六种数据类型。

    2.3.2、typeof运算符

    使用typeof操作符可以用来检查一个变量的数据类型。

    使用方式:

    typeof 数据
    

    示例代码:

    console.log(typeof 123);
    console.log(typeof "Hello,World!");
    console.log(typeof true);
    console.log(typeof undefined);
    console.log(typeof null);
    

    运行结果:

    image-20201013080324458

    2.3.3、String

    String用于表示一个字符序列,即字符串。字符串需要使用 单引号双引号 括起来。

    转义字符:

    image-20201013085608008

    注意:使用typeof运算符检查字符串时,会返回"string"。

    2.3.4、Number

    Number 类型用来表示整数和浮点数,最常用的功能就是用来表示10进制的整数和浮点数。

    Number表示的数字大小是有限的,如果超过了这个范围,则会返回 ±Infinity。

    • 最大值:+1.7976931348623157e+308
    • 最小值:-1.7976931348623157e+308
    • 0以上的最小值:5e-324

    特殊的数字:

    • Infinity:正无穷
    • -Infinity:负无穷
    • NaN:非法数字(Not A Number)

    其它的进制:

    • 二进制:0b 开头表示二进制,但是,并不是所有的浏览器都支持
    • 八进制:0 开头表示八进制
    • 十六进制:0x 开头表示十六进制

    注意:使用typeof检查一个Number类型的数据时(包括NaN 和 Infinity),会返回"number"。

    2.3.5、Boolean

    布尔型也被称为逻辑值类型或者真假值类型。

    布尔型只能够取真(true)和假(false)两种数值。除此以外, 其它的值都不被支持。

    2.3.6、Undefined

    Undefined 类型只有一个值,即特殊的 undefined。

    在使用 var 声明变量但未对其加以初始化时,这个变量的值就是 undefined。

    注意:使用typeof对没有初始化和没有声明的变量,会返回“undefined”。

    2.3.7、Null

    Null 类型是第二个只有一个值的数据类型,这个特殊的值是 null。

    undefined值实际上是由null值衍生出来的,所以如果比较undefined和null是否相等,会返回true。

    注意:从语义上看null表示的是一个空的对象,所以使用typeof检查null会返回一个Object。

    2.4、强制类型转换

    强制类型转换指将一个数据类型强制转换为其它的数据类型。一般是指,将其它的数据类型转换为String、Number、Boolean。

    2.4.1、转换为String类型

    将其它数值转换为字符串有三种方式:toString()、String()、 拼串。

    • 方式一:调用被转换数据类型的toString()方法,该方法不会影响到原变量,它会将转换的结果返回,但是注意:null和undefined这两个值没有toString()方法,如果调用它们的方法,会报错。

      var a = 123;
      a = a.toString();
      console.log(a);
      console.log(typeof a);
      
    • 方式二:调用String()函数,并将被转换的数据作为参数传递给函数,使用String()函数做强制类型转换时,对于Number和Boolean实际上就是调用的toString()方法,但是对于null和undefined,就不会调用toString()方法,它会将 null 直接转换为 “null”,将 undefined 直接转换为 “undefined”。

      var a = 123;
      a = String(a);
      console.log(a);
      console.log(typeof a);
      
      var b = undefined;
      b = String(b);
      console.log(b);
      console.log(typeof b);
      
      var c = null;
      c = String(c);
      console.log(c);
      console.log(typeof c);
      
    • 方式三:为任意的数据类型 +""

      var a = 123;
      a = a + "";
      console.log(a);
      console.log(typeof a);
      

    2.4.2、转换为Number类型

    有三个函数可以把非数值转换为数值:Number()、parseInt() 和parseFloat()。Number()可以用来转换任意类型的数据,而后两者只能用于转换字符串。parseInt()只会将字符串转换为整数,而parseFloat()可以将字符串转换为浮点数。

    • 方式一:使用Number()函数

      • 字符串 --> 数字
        • 如果是纯数字的字符串,则直接将其转换为数字
        • 如果字符串中有非数字的内容,则转换为NaN
        • 如果字符串是一个空串或者是一个全是空格的字符串,则转换为0
      • 布尔 --> 数字
        • true 转成 1
        • false 转成 0
      • null --> 数字
        • null 转成 0
      • undefined --> 数字
        • undefined 转成 NaN
    • 方式二:这种方式专门用来对付字符串,parseInt() 把一个字符串转换为一个整数

      var a = "123";
      a = parseInt(a);
      console.log(a);
      console.log(typeof a);
      
    • 方式三:这种方式专门用来对付字符串,parseFloat() 把一个字符串转换为一个浮点数

      var a = "123.456";
      a = parseFloat(a);
      console.log(a);
      console.log(typeof a);
      

    注意:如果对非String使用parseInt()或parseFloat(),它会先将其转换为String然后在操作

    2.4.3、转换为Boolean类型

    将其它的数据类型转换为Boolean,只能使用Boolean()函数。

    • 使用Boolean()函数
      • 数字 —> 布尔
        • 除了0和NaN,其余的都是true
      • 字符串 —> 布尔
        • 除了空串,其余的都是true
      • null和undefined都会转换为false
      • 对象也会转换为true

    2.5、运算符

    运算符也叫操作符,通过运算符可以对一个或多个值进行运算并获取运算结果。

    比如:typeof就是运算符,可以来获得一个值的类型,它会将该值的类型以字符串的形式返回(number string boolean undefined object)

    2.5.1、算术运算符

    算术运算符用于表达式计算。

    y=5,下面的表格解释了这些算术运算符:

    运算符描述例子x 运算结果y 运算结果在线实例
    +加法x=y+275实例 »
    -减法x=y-235实例 »
    *乘法x=y*2105实例 »
    /除法x=y/22.55实例 »
    %取模(求余数)x=y%215实例 »
    ++自增x=++y
    x=y++
    6
    5
    6
    6
    实例 »
    实例 »
    自减x=–y
    x=y–
    4
    5
    4
    4
    实例 »
    实例 »

    2.5.2、关系运算符

    关系运算符在逻辑语句中使用,以测定变量或值是否相等。

    x=5,下面的表格解释了比较运算符:

    运算符描述比较返回值实例
    >大于x>8false实例 »
    <小于x<8true实例 »
    >=大于或等于x>=8false实例 »
    <=小于或等于x<=8true实例 »

    2.5.3、赋值运算符

    赋值运算符用于给 JavaScript 变量赋值。

    x=10 和 y=5,下面的表格解释了赋值运算符:

    运算符例子等同于运算结果在线实例
    =x=yx=5实例 »
    +=x+=yx=x+yx=15实例 »
    -=x-=yx=x-yx=5实例 »
    *=x*=yx=x*yx=50实例 »
    /=x/=yx=x/yx=2实例 »
    %=x%=yx=x%yx=0实例 »

    2.5.4、逻辑运算符

    逻辑运算符用于测定变量或值之间的逻辑。

    给定 x=6 以及 y=3,下表解释了逻辑运算符:

    运算符描述例子
    &&and(x < 10 && y > 1) 为 true
    ||or(x==5 || y==5) 为 false
    !not!(x==y) 为 true

    关于逻辑运算符我们可以具体探讨一下:

    • && 与:&&可以对符号两侧的值进行与运算并返回结果,运算规则如下:
      • 两个值中只要有一个值为false,就返回false,只有两个值都为true时,才会返回true
      • JS中的“与”属于短路的与,如果第一个值为false,则不会检查第二个值
      • 非布尔值时:如果两个都为true,则返回第二个值,如果两个值中有false,则返回靠前的false的值
    • || 或:||可以对符号两侧的值进行或运算并返回结果,运算规则如下:
      • 两个值中只要有一个true,就返回true,只有两个值都为false,才会返回false
      • JS中的“或”属于短路的或,如果第一个值为true,则不会检查第二个值
      • 非布尔值时:如果两个都为false ,则返回第二个值,如果两个值中有true,则返回靠前的true的值
    • ! 非:!可以用来对一个值进行非运算,所谓非运算就是对一个布尔值进行取反操作,true变false,false变true,运算规则如下:
      • 如果对一个值进行两次取反,它不会变化
      • 非布尔值时:先会将其转换为布尔值,然后再取反,所以我们可以利用该特点,来将一个其它的数据类型转换为布尔值,可以为一个任意数据类型取两次反,来将其转换为布尔值,原理和Boolean()函数一样

    2.5.5、比较运算符

    比较运算符用来比较两个值是否相等,如果相等会返回true,否则返回false。

    • 使用 == 来做相等运算
      • 当使用==来比较两个值时,如果值的类型不同,则会自动进行类型转换,将其转换为相同的类型,然后在比较
    • 使用 != 来做不相等运算
      • 不相等用来判断两个值是否不相等,如果不相等返回true,否则返回false,不相等也会对变量进行自动的类型转换,如果转换后相等它也会返回false
    • 使用 === 来做全等运算
      • 用来判断两个值是否全等,它和相等类似,不同的是它不会做自动的类型转换,如果两个值的类型不同,直接返回false
    • 使用 !== 来做不全等运算
      • 用来判断两个值是否不全等,它和不等类似,不同的是它不会做自动的类型转换,如果两个值的类型不同,直接返回true

    2.5.6、条件运算符

    JavaScript 还包含了基于某些条件对变量进行赋值的条件运算符。

    语法:variablename=(condition)?value1:value2;

    举例:result=(age<18)?"年龄太小":"年龄合适";

    执行流程:如果condition为true,则执行语句1,并返回执行结果,如果为false,则执行语句2,并返回执行结果。

    2.5.7、逗号运算符

    使用逗号可以在一条语句中执行多次操作。

    比如:var num1=1, num2=2, num3=3;

    使用逗号运算符分隔的语句会从左到右顺 序依次执行。

    2.6、运算符优先级

    运算符优先级由上到下依次减小,对于同级运算符,采用从左向右依次执行的方法。

    image-20201013115557984

    2.7、代码块

    2.7.1、语句

    前边我所说表达式和运算符等内容可以理解成是我们一 门语言中的单词,短语。而语句(statement)就是我们这个语言中一句一句完 整的话了。语句是一个程序的基本单位,JavaScript的程序就是由一条一条语句构成的,每一条语句使用;结尾。

    JavaScript中的语句默认是由上至下顺序执行的,但是我们也可以通过一些流程控制语句来控制语句的执行顺序。

    2.7.2、代码块

    代码块是在大括号 {} 中所写的语句,以此将多条语句的集合视为一条语句来使用。

    例如:

    {
        var a = 123;
        a++;
        alert(a);
    }
    

    我们一般使用代码块将需要一起执行的语句进行分组,需要注意的是,代码块结尾不需要加 分号。

    2.8、条件语句

    条件语句是通过判断指定表达式的值来决定执行还是跳过某些语句,最基本的条件语句:

    • if…else
    • switch…case

    2.8.1、if…else

    if…else语句是一种最基本的控制语句,它让JavaScript可以有条件的执行语句。

    • 第一种形式:

      if(expression)
          statement
      
      var age = 16;
      if (age < 18) {
          console.log("未成年");
      }
      
    • 第二种形式:

      if(expression)
          statement
      else
          statement
      
      var age = 16;
      if (age < 18) {
          console.log("未成年");
      } else {
          console.log("已成年");
      }
      
    • 第三种形式:

      if(expression1)
          statement
      else if(expression2)
          statement
      else
          statement    
      
      var age = 18;
      if (age < 18) {
          console.log("小于18岁了");
      } else if (age == 18) {
          console.log("已经18岁了");
      } else {
          console.log("大于18岁了")
      }
      

    2.8.2、switch…case

    switch…case是另一种流程控制语句。

    switch语句更适用于多条分支使用同一条语句的情况。

    语法格式:

    switch (语句) {
        case 表达式1:
            语句...
        case 表达式2:
            语句...
        default:
            语句...
    }
    

    注意:需要注意的是一旦符合case的条件程序会一直运行到结束,所以我们一般会在case中添加break作为语句的结束。

    案例演示1:根据today的数值,输出今天是星期几。

    var today = 1;
    switch (today) {
        case 1:
            console.log("星期一");
            break;
        case 2:
            console.log("星期二");
            break;
        case 3:
            console.log("星期三");
            break;
        case 4:
            console.log("星期四");
            break;
        case 5:
            console.log("星期五");
            break;
        case 6:
            console.log("星期六");
            break;
        case 7:
            console.log("星期日");
            break;
        default:
            console.log("输入错误");
    }
    

    案例演示2:根据month的数值,输出对应月份的天数,2月默认28天。

    var month = 10;
    switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            console.log("31天");
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            console.log("30天");
            break;
        case 2:
            console.log("28天");
            break;
        default:
            console.log("输入错误");
    }
    

    2.9、循环语句

    循环语句和条件语句一样,也是基本的控制语句,只要满足一定的条件将会一直执行,最基本的循环语句:

    • while
    • do…while
    • for

    2.9.1、while

    while语句是一个最基本的循环语句,while语句也被称为while循环。

    语法格式:

    while(条件表达式){
        语句...
    }
    

    案例演示:输出1-10。

    var i = 1;
    while (i <= 10) {
        console.log(i);
        i++;
    }
    

    2.9.2、do…while

    do…while和while非常类似,只不过它会在循环的尾部而不是顶部检查表达式的值,因此,do…while循环会至少执行一次。相比于while,do…while的使用情况并不 是很多。

    语法格式:

    do{
        语句...
    }while(条件表达式);
    

    案例演示:输出1-10。

    var i = 1;
    do {
        console.log(i);
        i++;
    } while (i <= 10);
    

    2.9.3、for

    for语句也是循环控制语句,我们也称它为for循环。大部分循环都会有一个计数器用以控制循环执行的次数, 计数器的三个关键操作是初始化、检测和更新。for语句 就将这三步操作明确为了语法的一部分。

    语法格式:

    for(初始化表达式 ; 条件表达式 ; 更新表达式){
        语句...
    }
    

    案例演示:输出1-10。

    for (var i = 1; i <= 10; i++) {
        console.log(i);
    }
    

    2.9.4、跳转控制

    • break:结束最近的一次循环,可以在循环和switch语句中使用。
    • continue:结束本次循环,执行下一次循环,只能在循环中使用。

    那如果我们想要跳出多层循环或者跳到指定位置该怎么办呢?可以为循环语句创建一个label,来标识当前的循环,如下例子:

    outer: for (var i = 0; i < 10; i++) {
        for (var j = 0; j < 10; j++) {
            if (j == 5) {
                break outer;
            }
            console.log(j);
        }
    }
    

    2.10、对象基础

    2.10.1、概述

    Object类型,我们也称为一个对象,是JavaScript中的引用数据类型。它是一种复合值,它将很多值聚合到一起,可以通过名字访问这些值。对象也可以看做是属性的无序集合,每个属性都是一个名/值对。对象除了可以创建自有属性,还可以通过从一个名为原型的对象那里继承属性。除了字符串、数字、true、false、null和undefined之外,JavaScript中的值都是对象。

    2.10.2、创建对象

    创建对象有两种方式:

    • 第一种方式:

      var person = new Object();
      person.name = "孙悟空";
      person.age = 18;
      console.log(person);
      
    • 第二种方式:

      var person = {
          name: "孙悟空",
          age: 18
      };
      console.log(person);
      

    2.10.3、访问属性

    访问属性的两种方式:

    • 第一种方式:使用 . 来访问

      对象.属性名
      
    • 第二种方式:使用 [] 来访问

      对象[‘属性名’]
      

    2.10.4、删除属性

    删除对象的属性可以使用delete关键字,格式如下:

    delete 对象.属性名
    

    案例演示:

    var person = new Object();
    person.name = "孙悟空";
    person.age = 18;
    console.log(person);
    
    delete person.name
    console.log(person);
    

    2.10.5、遍历对象

    枚举遍历对象中的属性,可以使用for … in语句循环,对象中有几个属性,循环体就会执行几次。

    语法格式:

    for (var 变量 in 对象) {
    
    }
    

    案例演示:

    var person = {
        name: "zhangsan",
        age: 18
    }
    
    for (var personKey in person) {
        var personVal = person[personKey];
        console.log(personKey + ":" + personVal);
    }
    

    2.10.6、数据类型梳理

    2.10.6.1、基本数据类型

    JavaScript中的变量可能包含两种不同数据类型的值:基本数据类型和引用数据类型。

    JavaScript中一共有5种基本数据类型:String、Number、 Boolean、Undefined、Null。

    基本数据类型的值是无法修改的,是不可变的。

    基本数据类型的比较是值的比较,也就是只要两个变量的值相等,我们就认为这两个变量相等。

    2.10.6.2、引用数据类型

    引用类型的值是保存在内存中的对象。

    当一个变量是一个对象时,实际上变量中保存的并不是对象本身,而是对象的引用。

    当从一个变量向另一个变量复制引用类型的值时,会将对象的引用复制到变量中,并不是创建一个新的对象。

    这时,两个变量指向的是同一个对象。因此,改变其中一个变量会影响另一个。

    2.10.7、栈和堆梳理

    JavaScript在运行时数据是保存到栈内存和堆内存当中的。

    简单来说栈内存用来保存变量和基本类型,堆内存是用来保存对象。

    我们在声明一个变量时,实际上就是在栈内存中创建了一个空间用来保存变量。

    如果是基本类型则在栈内存中直接保存,如果是引用类型则会在堆内存中保存,变量中保存的实际上对象在堆内存中的地址。

    当我们写了下边这几句代码的时候,栈内存和堆内存的结构如下:

    var a = 123;
    var b = true;
    var c = "hello";
    var d = {name: 'sunwukong', age: 18};
    

    栈的特点:先进后出,后进先出

    image-20201014085429553

    2.11、函数

    2.11.1、概述

    函数是由一连串的子程序(语句的集合)所组成的,可以被外部程序调用,向函数传递参数之后,函数可以返回一定的值。

    通常情况下,JavaScript代码是自上而下执行的,不过函数体内部的代码则不是这样。如果只是对函数进行了声明,其中的代码并不会执行,只有在调用函数时才会执行函数体内部的代码。

    这里要注意的是JavaScript中的函数也是一个对象,使用typeof检查一个函数对象时,会返回function。

    2.11.2、函数创建

    • 使用 函数对象 来创建一个函数(几乎不用)

      语法格式:

      var 函数名 = new Function("执行语句");
      

      示例代码:

      var fun = new Function("console.log('这是我的第一个函数');");
      
    • 使用 函数声明 来创建一个函数(比较常用)

      语法格式:

      function 函数名([形参1,形参2,...,形参N]) {
          语句...
      }
      

      示例代码:

      function fun(){
          console.log("这是我的第二个函数");
      }
      
    • 使用 函数表达式 来创建一个函数(比较常用)

      语法格式:

      var 函数名  = function([形参1,形参2,...,形参N]) {
          语句....
      }
      

      示例代码:

      var fun  = function() {
          console.log("这是我的第三个函数");
      }
      

    2.11.3、函数调用

    • 对于无参函数调用:

      // 函数声明
      var fun = function () {
          console.log("哈哈,我执行啦!");
      }
      
      // 函数调用
      fun();
      
    • 对于有参函数调用:

      // 函数声明
      var sum = function (num1, num2) {
          var result = num1 + num2;
          console.log("num1 + num2 = " + result);
      }
      
      // 函数调用
      sum(10, 20);
      

    2.11.4、函数参数

    • JS中的所有的参数传递都是按值传递的,也就是说把函数外部的值赋值给函数内部的参数,就和把值从一个变量赋值给另一个变量是一样的,在调用函数时,可以在()中指定实参(实际参数),实参将会赋值给函数中对应的形参
    • 调用函数时,解析器不会检查实参的类型,所以要注意,是否有可能会接收到非法的参数,如果有可能,则需要对参数进行类型的检查,函数的实参可以是任意的数据类型
    • 调用函数时,解析器也不会检查实参的数量,多余实参不会被赋值,如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined

    2.11.5、函数返回值

    可以使用 return 来设置函数的返回值,return后的值将会作为函数的执行结果返回,可以定义一个变量,来接收该结果。

    注意:在函数中return后的语句都不会执行,如果return语句后不跟任何值就相当于返回一个undefined,如果函数中不写return,则也会返回undefined,return后可以跟任意类型的值

    语法格式:return 值

    案例演示:

    function sum(num1, num2) {
        return num1 + num2;
    }
    
    var result = sum(10, 20);
    console.log(result);
    

    2.11.6、嵌套函数

    嵌套函数:在函数中声明的函数就是嵌套函数,嵌套函数只能在当前函数中可以访问,在当前函数外无法访问。

    案例演示:

    function fu() {
        function zi() {
            console.log("我是儿子")
        }
    
        zi();
    }
    
    fu();
    

    2.11.7、匿名函数

    匿名函数:没有名字的函数就是匿名函数,它可以让一个变量来接收,也就是用 “函数表达式” 方式创建和接收。

    案例演示:

    var fun = function () {
        alert("我是一个匿名函数");
    }
    
    fun();
    

    2.11.8、立即执行函数

    立即执行函数:函数定义完,立即被调用,这种函数叫做立即执行函数,立即执行函数往往只会执行一次。

    案例演示:

    (function () {
        alert("我是一个匿名函数");
    })();
    

    2.11.9、对象中的函数

    对象的属性值可以是任何的数据类型,也可以是个函数。

    如果一个函数作为一个对象的属性保存,那么我们称这个函数是这个对象的方法,调用这个函数就说调用对象的方法(method)。

    注意:方法和函数只是名称上的区别,没有其它别的区别

    案例演示:

    var person = {
        name: "zhangsan",
        age: 18,
        sayHello: function () {
            console.log(name + " hello")
        }
    }
    
    person.sayHello();
    

    2.11.10、this对象

    解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的上下文对象,根据函数的调用方式的不同,this会指向不同的对象

    • 以函数的形式调用时,this永远都是window
    • 以方法的形式调用时,this就是调用方法的那个对象

    案例演示:

    //创建一个全局变量name
    var name = "全局变量name";
    
    //创建一个函数
    function fun() {
        console.log(this.name);
    }
    
    //创建一个对象
    var obj = {
        name: "孙悟空",
        sayName: fun
    };
    
    //我们希望调用obj.sayName()时可以输出obj的名字而不是全局变量name的名字
    obj.sayName();
    

    2.12、对象进阶

    2.12.1、用工厂方法创建对象

    我们之前已经学习了如何创建一个对象,那我们要是想要创建多个对象又该怎么办?聪明的同学可能会说,直接在写几个对象不就好了吗?比如下边的代码:

    var person1 = {
        name: "孙悟空",
        age: 18,
        sayName: function () {
            console.log(this.name);
        }
    };
    
    var person2 = {
        name: "猪八戒",
        age: 19,
        sayName: function () {
            console.log(this.name);
        }
    };
    
    var person3 = {
        name: "沙和尚",
        age: 20,
        sayName: function () {
            console.log(this.name);
        }
    };
    
    console.log(person1);
    console.log(person2);
    console.log(person3);
    

    的确,上述代码确实可以创建多个对象,但是,这样的解决方案真的好吗?对于少量对象可能使用,我们假设说,要用循环创建1000个对象,那你这种办法似乎就没用了,我们可以这么做,如下代码:

    // 使用工厂模式创建对象
    function createPerson() {
        // 创建新的对象
        var obj = new Object();
        // 设置对象属性
        obj.name = "孙悟空";
        obj.age = 18;
        // 设置对象方法
        obj.sayName = function () {
            console.log(this.name);
        };
        //返回新的对象
        return obj;
    }
    
    var person1 = createPerson();
    var person2 = createPerson();
    var person3 = createPerson();
    
    console.log(person1);
    console.log(person2);
    console.log(person3);
    

    上述代码看起来更加简洁,但是你会发现每一个人都是孙悟空,我们要是想要给每一个人不同的属性值,请参考:

    // 使用工厂模式创建对象
    function createPerson(name, age) {
        // 创建新的对象
        var obj = new Object();
        // 设置对象属性
        obj.name = name;
        obj.age = age;
        // 设置对象方法
        obj.sayName = function () {
            console.log(this.name);
        };
        //返回新的对象
        return obj;
    }
    
    var person1 = createPerson("孙悟空", 18);
    var person2 = createPerson("猪八戒", 19);
    var person3 = createPerson("沙和尚", 20);
    
    console.log(person1);
    console.log(person2);
    console.log(person3);
    

    现在再看上述代码,发现好像已经完美的解决了创建多个对象的难题,那我们是不是可以用循环批量创建1000个对象了呢?那我们就来试试:

    // 使用工厂模式创建对象
    function createPerson(name, age) {
        // 创建新的对象
        var obj = new Object();
        // 设置对象属性
        obj.name = name;
        obj.age = age;
        // 设置对象方法
        obj.sayName = function () {
            console.log(this.name);
        };
        //返回新的对象
        return obj;
    }
    
    for (var i = 1; i <= 1000; i++) {
        var person = createPerson("person" + i, 18);
        console.log(person);
    }
    

    这样我们就实现了批量创建对象的功能,至于对象的名称和年龄,我们可以通过名称数组和年龄数组来获取,但这并不是我们本小节的重点,我们就忽略了。

    2.12.2、用构造函数创建对象

    在前一节中,我们学会了使用工厂模式创建对象,但是,你会发现我们所创建的对象类型都是Object,具体代码如下:

    // 使用工厂模式创建对象
    function createPerson(name, age) {
        // 创建新的对象
        var obj = new Object();
        // 设置对象属性
        obj.name = name;
        obj.age = age;
        // 设置对象方法
        obj.sayName = function () {
            console.log(this.name);
        };
        //返回新的对象
        return obj;
    }
    
    for (var i = 1; i <= 1000; i++) {
        var person = createPerson("person" + i, 18);
        console.log(typeof person);
    }
    

    image-20201016083849601

    那这有问题吗?看起来有,看起来好像又没有,每创建一个都是对象,但是在实际生活中,人应该是一个确定的类别,属于人类,对象是一个笼统的称呼,万物皆对象,它并不能确切的指明当前对象是人类,那我们要是既想实现创建对象的功能,同时又能明确所创建出来的对象是人类,那么似乎问题就得到了解决,这就用到了构造函数,每一个构造函数你都可以理解为一个类别,用构造函数所创建的对象我们也成为类的实例,那我们来看看是如何做的:

    // 使用构造函数来创建对象
    function Person(name, age) {
        // 设置对象的属性
        this.name = name;
        this.age = age;
        // 设置对象的方法
        this.sayName = function () {
            console.log(this.name);
        };
    }
    
    var person1 = new Person("孙悟空", 18);
    var person2 = new Person("猪八戒", 19);
    var person3 = new Person("沙和尚", 20);
    
    console.log(person1);
    console.log(person2);
    console.log(person3);
    

    image-20201016085351603

    那这构造函数到底是什么呢?我来解释一下:

    构造函数:构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写,构造函数和普通函数的还有一个区别就是调用方式的不同,普通函数是直接调用,而构造函数需要使用new关键字来调用。

    那构造函数是怎么执行创建对象的过程呢?我再来解释一下:

    1. 调用构造函数,它会立刻创建一个新的对象
    2. 将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象
    3. 逐行执行函数中的代码
    4. 将新建的对象作为返回值返回

    你会发现构造函数有点类似工厂方法,但是它创建对象和返回对象都给我们隐藏了,使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。我们将通过一个构造函数创建的对象,称为是该类的实例。

    现在,this又出现了一种新的情况,为了不让大家混淆,我再来梳理一下:

    • 当以函数的形式调用时,this是window
    • 当以方法的形式调用时,谁调用方法this就是谁
    • 当以构造函数的形式调用时,this就是新创建的那个对象

    我们可以使用 instanceof 运算符检查一个对象是否是一个类的实例,它返回true或false

    语法格式:

    对象 instanceof 构造函数
    

    案例演示:

    console.log(person1 instanceof Person);
    

    2.12.3、原型

    在前一节中,我们学习了使用构造函数的方式进行创建对象,但是,它还是存在一个问题,那就是,你会发现,每一个对象的属性不一样这是一定的,但是它的方法似乎好像是一样的,如果我创建1000个对象,那岂不是内存中就有1000个相同的方法,那要是有10000个,那对内存的浪费可不是一点半点的,我们有没有什么好的办法解决,没错,我们可以把函数抽取出来,作为全局函数,在构造函数中直接引用就可以了,上代码:

    // 使用构造函数来创建对象
    function Person(name, age) {
        // 设置对象的属性
        this.name = name;
        this.age = age;
        // 设置对象的方法
        this.sayName = sayName
    }
    
    // 抽取方法为全局函数
    function sayName() {
        console.log(this.name);
    }
    
    var person1 = new Person("孙悟空", 18);
    var person2 = new Person("猪八戒", 19);
    var person3 = new Person("沙和尚", 20);
    
    person1.sayName();
    person2.sayName();
    person3.sayName();
    

    image-20201016085859719

    但是,在全局作用域中定义函数却不是一个好的办法,为什么呢?因为,如果要是涉及到多人协作开发一个项目,别人也有可能叫sayName这个方法,这样在工程合并的时候就会导致一系列的问题,污染全局作用域,那该怎么办呢?有没有一种方法,我只在Person这个类的全局对象中添加一个函数,然后在类中引用?答案肯定是有的,这就需要原型对象了,我们先看看怎么做的,然后在详细讲解原型对象。

    // 使用构造函数来创建对象
    function Person(name, age) {
        // 设置对象的属性
        this.name = name;
        this.age = age;
    }
    
    // 在Person类的原型对象中添加方法
    Person.prototype.sayName = function() {
        console.log(this.name);
    };
    
    var person1 = new Person("孙悟空", 18);
    var person2 = new Person("猪八戒", 19);
    var person3 = new Person("沙和尚", 20);
    
    person1.sayName();
    person2.sayName();
    person3.sayName();
    

    image-20201016091223379

    那原型(prototype)到底是什么呢?

    我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象,即显式原型,原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。

    如果函数作为普通函数调用prototype没有任何作用,当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__(隐式原型)来访问该属性。当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。

    以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。

    2.12.4、原型链

    访问一个对象的属性时,先在自身属性中查找,找到返回, 如果没有,再沿着__proto__这条链向上查找,找到返回,如果最终没找到,返回undefined,这就是原型链,又称隐式原型链,它的作用就是查找对象的属性(方法)。

    我们使用一张图来梳理一下上一节原型案例的代码:

    image-20201016092628653

    注意:Object对象是所有对象的祖宗,Object的原型对象指向为null,也就是没有原型对象

    2.12.5、toString方法

    toString()函数用于将当前对象以字符串的形式返回。该方法属于Object对象,由于所有的对象都"继承"了Object的对象实例,因此几乎所有的实例对象都可以使用该方法,所有主流浏览器均支持该函数。

    // 使用构造函数来创建对象
    function Person(name, age) {
        // 设置对象的属性
        this.name = name;
        this.age = age;
    }
    
    //创建对象的一个实例对象
    var p = new Person("张三", 20);
    console.log(p.toString());
    

    image-20201025104527044

    JavaScript的许多内置对象都重写了该函数,以实现更适合自身的功能需要。

    类型行为描述
    String返回 String 对象的值。
    Number返回 Number 的字符串表示。
    Boolean如果布尔值是true,则返回"true"。否则返回"false"。
    Object
    (默认)
    返回"[object ObjectName]",其中 ObjectName 是对象类型的名称。
    Array将 Array 的每个元素转换为字符串,并将它们依次连接起来,两个元素之间用英文逗号作为分隔符进行拼接。
    Date返回日期的文本表示。
    Error返回一个包含相关错误信息的字符串。
    Function返回如下格式的字符串,其中 functionname 是一个函数的名称
    此函数的 toString 方法被调用: “function functionname() { [native code] }”

    注意:这里我们只是演示toString()方法,其它的一些没有讲到的知识后边会将,我们只看效果就可。

    // 字符串
    var str = "Hello";
    console.log(str.toString());
    
    // 数字
    var num = 15.26540;
    console.log(num.toString());
    
    // 布尔
    var bool = true;
    console.log(bool.toString());
    
    // Object
    var obj = {name: "张三", age: 18};
    console.log(obj.toString());
    
    // 数组
    var array = ["CodePlayer", true, 12, -5];
    console.log(array.toString());
    
    // 日期
    var date = new Date(2013, 7, 18, 23, 11, 59, 230);
    console.log(date.toString());
    
    // 错误
    var error = new Error("自定义错误信息");
    console.log(error.toString());
    
    // 函数
    console.log(Function.toString());
    

    image-20201025111357084

    2.12.6、hasOwnProperty方法

    前边章节我们学过,如何遍历一个对象所有的属性和值,那我们要是判断当前对象是否包含指定的属性或方法可以使用 in 运算符来检查,如下代码演示:

    // 创造一个构造函数
    function MyClass() {
    }
    
    // 向MyClass的原型中添加一个name属性
    MyClass.prototype.name = "我是原型中的名字";
    
    // 创建一个MyClass的实例
    var mc = new MyClass();
    mc.age = 18;
    
    // 使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
    console.log("age" in mc);
    console.log("name" in mc);
    

    image-20201016094121739

    如果我只想要检查自身对象是否含有某个方法或属性,我们可以使用Object的hasOwnProperty()方法,它返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。如下代码演示:

    // 创造一个构造函数
    function MyClass() {
    }
    
    // 向MyClass的原型中添加一个name属性
    MyClass.prototype.name = "我是原型中的名字";
    
    // 创建一个MyClass的实例
    var mc = new MyClass();
    mc.age = 18;
    
    // 使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
    console.log("age" in mc);
    console.log("name" in mc);
    
    // 可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性,使用该方法只有当对象自身中含有属性时,才会返回true
    console.log(mc.hasOwnProperty("age"));
    console.log(mc.hasOwnProperty("name"));
    

    image-20201016094051484

    有同学可能会有疑问,我的这个MyClass类对象中没有hasOwnProperty这个方法啊,它是哪来的?对了,就是原型中的,在执行方法的时候它会通过原型链进行查找,这个方法是Object的特有方法,如下代码演示:

    // 创造一个构造函数
    function MyClass() {
    }
    
    // 向MyClass的原型中添加一个name属性
    MyClass.prototype.name = "我是原型中的名字";
    
    // 创建一个MyClass的实例
    var mc = new MyClass();
    mc.age = 18;
    
    // 检查当前对象
    console.log(mc.hasOwnProperty("hasOwnProperty"));
    // 检查当前对象的原型对象
    console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));
    // 检查当前对象的原型对象的原型对象
    console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));
    

    image-20201016094021988

    2.12.7、对象继承

    前边我们一直在说继承,那什么是继承?它有什么作用?如何实现继承?将会是本章节探讨的问题。

    面向对象的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。但是在JavaScript中没有类的概念,前边我们说所的类只是我们自己这么叫,大家要清楚。因此它的对象也与基于类的对象有所不同。实际上,JavaScript语言是通过一种叫做原型(prototype)的方式来实现面向对象编程的。

    那实现继承有一个最大的好处就是子对象可以使用父对象的属性和方法,从而简化了一些代码。

    JavaScript有六种非常经典的对象继承方式,但是我们只学习前三种:

    • 原型链继承
    • 借用构造函数继承
    • 组合继承(重要)
    • 原型式继承
    • 寄生式继承
    • 寄生组合式继承

    2.12.7.1、原型链继承

    核心思想: 子类型的原型为父类型的一个实例对象

    基本做法:

    1. 定义父类型构造函数
    2. 给父类型的原型添加方法
    3. 定义子类型的构造函数
    4. 创建父类型的对象赋值给子类型的原型
    5. 将子类型原型的构造属性设置为子类型
    6. 给子类型原型添加方法
    7. 创建子类型的对象: 可以调用父类型的方法

    案例演示:

    // 定义父类型构造函数
    function SupperType() {
        this.supProp = 'Supper property';
    }
    
    // 给父类型的原型添加方法
    SupperType.prototype.showSupperProp = function () {
        console.log(this.supProp);
    };
    
    // 定义子类型的构造函数
    function SubType() {
        this.subProp = 'Sub property';
    }
    
    // 创建父类型的对象赋值给子类型的原型
    SubType.prototype = new SupperType();
    
    // 将子类型原型的构造属性设置为子类型
    SubType.prototype.constructor = SubType;
    
    // 给子类型原型添加方法
    SubType.prototype.showSubProp = function () {
        console.log(this.subProp)
    };
    
    // 创建子类型的对象: 可以调用父类型的方法
    var subType = new SubType();
    subType.showSupperProp();
    subType.showSubProp();
    

    image-20201025114537583

    缺点描述:

    1. 原型链继承多个实例的引用类型属性指向相同,一个实例修改了原型属性,另一个实例的原型属性也会被修改
    2. 不能传递参数
    3. 继承单一

    2.12.7.2、借用构造函数继承

    核心思想: 使用.call()和.apply()将父类构造函数引入子类函数,使用父类的构造函数来增强子类实例,等同于复制父类的实例给子类

    基本做法:

    1. 定义父类型构造函数
    2. 定义子类型的构造函数
    3. 给子类型的原型添加方法
    4. 创建子类型的对象然后调用

    案例演示:

    借用构造函数继承的重点就在于SuperType**.call(this, name)**,调用了SuperType构造函数,这样,SubType的每个实例都会将SuperType中的属性复制一份。

    // 定义父类型构造函数
    function SuperType(name) {
        this.name = name;
        this.showSupperName = function () {
            console.log(this.name);
        };
    }
    
    // 定义子类型的构造函数
    function SubType(name, age) {
        // 在子类型中调用call方法继承自SuperType
        SuperType.call(this, name);
        this.age = age;
    }
    
    // 给子类型的原型添加方法
    SubType.prototype.showSubName = function () {
        console.log(this.name);
    };
    
    // 创建子类型的对象然后调用
    var subType = new SubType("孙悟空", 20);
    subType.showSupperName();
    subType.showSubName();
    console.log(subType.name);
    console.log(subType.age);
    

    image-20201025125050202

    缺点描述:

    1. 只能继承父类的实例属性和方法,不能继承原型属性和方法
    2. 无法实现构造函数的复用,每个子类都有父类实例函数的副本,影响性能,代码会臃肿

    2.12.7.3、组合继承

    核心思想: 原型链+借用构造函数的组合继承

    基本做法:

    1. 利用原型链实现对父类型对象的方法继承
    2. 利用super()借用父类型构建函数初始化相同属性

    案例演示:

    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    
    Person.prototype.setName = function (name) {
        this.name = name;
    };
    
    function Student(name, age, price) {
        Person.call(this, name, age); // 为了得到父类型的实例属性和方法
        this.price = price; // 添加子类型私有的属性
    }
    
    Student.prototype = new Person(); // 为了得到父类型的原型属性和方法
    Student.prototype.constructor = Student; // 修正constructor属性指向
    Student.prototype.setPrice = function (price) { // 添加子类型私有的方法 
        this.price = price;
    };
    
    var s = new Student("孙悟空", 24, 15000);
    console.log(s.name, s.age, s.price);
    s.setName("猪八戒");
    s.setPrice(16000);
    console.log(s.name, s.age, s.price);
    

    image-20201025131516264

    缺点描述:

    1. 父类中的实例属性和方法既存在于子类的实例中,又存在于子类的原型中,不过仅是内存占用,因此,在使用子类创建实例对象时,其原型中会存在两份相同的属性和方法

    注意:这个方法是JavaScript中最常用的继承模式

    2.12.8、垃圾回收

    垃圾回收(GC):就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾,这些垃圾积攒过多以后,会导致程序运行的速度过慢,所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾。

    当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须进行清理。

    在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作,我们需要做的只是要将不再使用的对象设置null即可。

    案例演示:

    // 使用构造函数来创建对象
    function Person(name, age) {
        // 设置对象的属性
        this.name = name;
        this.age = age;
    }
    
    var person1 = new Person("孙悟空", 18);
    var person2 = new Person("猪八戒", 19);
    var person3 = new Person("沙和尚", 20);
    
    person1 = null;
    person2 = null;
    person3 = null;
    

    2.13、作用域

    作用域指一个变量的作用的范围,在JS中一共有两种作用域:

    • 全局作用域
    • 函数作用域

    2.13.1、声明提前

    • 变量的声明提前:使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值),但是如果声明变量时不使用var关键字,则变量不会被声明提前
    • 函数的声明提前:使用函数声明形式创建的函数 function 函数名(){} ,它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数。使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用

    2.13.2、作用域

    2.13.2.1、全局作用域

    • 直接编写在script标签中的JavaScript代码,都在全局作用域
    • 全局作用域在页面打开时创建,在页面关闭时销毁
    • 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,它由浏览器创建,我们可以直接使用
    • 在全局作用域中:
      • 创建的变量都会作为window对象的属性保存
      • 创建的函数都会作为window对象的方法保存
    • 全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问的到

    2.13.2.2、函数作用域

    • 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁
    • 每调用一次函数就会创建一个新的函数作用域,它们之间是互相独立的
    • 在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量
    • 在函数中要访问全局变量可以使用window对象
    • 作用域链:当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用,如果没有则向上一级作用域中寻找,直到找到全局作用域,如果全局作用域中依然没有找到,则会报错ReferenceError

    2.13.3、作用域链

    多个上下级关系的作用域形成的链,它的方向是从下向上的(从内到外),查找变量时就是沿着作用域链来查找的。

    查找一个变量的查找规则:

    1. 在当前作用域下的执行上下文中查找对应的属性,如果有直接返回,否则进入2
    2. 在上一级作用域的执行上下文中查找对应的属性,如果有直接返回,否则进入3
    3. 再次执行2的相同操作,直到全局作用域,如果还找不到就抛出找不到的ReferenceError异常

    第三章 JavaScript常用对象

    3.1、数组对象

    3.1.1、概述

    数组也是对象的一种,数组是一种用于表达有顺序关系的值的集合的语言结构,也就是同类数据元素的有序集合。

    数组的存储性能比普通对象要好,在开发中我们经常使用数组来存储一些数据。但是在JavaScript中是支持数组可以是不同的元素,这跟JavaScript的弱类型有关,此处不用纠结,我们大多数时候都是相同类型元素的集合。数组内的各个值被称作元素,每一个元素都可以通过索引(下标)来快速读取,索引是从零开始的整数。

    使用typeof检查一个数组对象时,会返回object。

    3.1.2、创建数组

    3.1.2.1、使用对象创建

    • 同类型有序数组创建:

      var arr = new Array();
      arr[0] = 1;
      arr[1] = 2;
      arr[2] = 3;
      arr[3] = 4;
      arr[4] = 5;
      arr[5] = 6;
      arr[6] = 7;
      arr[7] = 8;
      arr[8] = 9;
      
    • 不同类型有序数组创建:

      var arr = new Array();
      arr[0] = 1;
      arr[1] = "2";
      arr[2] = 3;
      arr[3] = "4";
      arr[4] = 5;
      arr[5] = "6";
      arr[6] = 7;
      arr[7] = "8";
      arr[8] = 9;
      

    3.1.2.2、使用字面量创建

    • 同类型有序数组创建:

      var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
      
    • 不同类型有序数组创建:

      var arr = [1, "2", 3, "4", 5, "6", 7, "8", 9];
      

    3.1.3、遍历数组

    for (var i = 0; i < arr.length; i++) {
        console.log(arr[i]);
    }
    

    3.1.4、数组属性

    constructor属性演示:返回创建数组对象的原型函数

    var arr = [1,2,3,4];
    console.log(arr.constructor);
    

    image-20201017213941462

    length属性演示:设置或返回数组元素的个数

    var arr = [1,2,3,4];
    console.log(arr.length);
    

    image-20201017214117638

    3.1.5、数组方法

    push()方法演示:该方法可以向数组的末尾添加一个或多个元素,并返回数组的新的长度

    var arr = ["孙悟空", "猪八戒", "沙和尚"];
    var result = arr.push("唐僧", "蜘蛛精", "白骨精", "玉兔精");
    console.log(arr);
    console.log(result);
    

    image-20201017215218010

    pop()方法演示:该方法可以删除数组的最后一个元素,并将被删除的元素作为返回值返回

    var arr = ["孙悟空", "猪八戒", "沙和尚"];
    var result = arr.pop();
    console.log(arr);
    console.log(result);
    

    image-20201017215359638

    unshift()方法演示:该方法向数组开头添加一个或多个元素,并返回新的数组长度

    var arr = ["孙悟空", "猪八戒", "沙和尚"];
    var result = arr.unshift("牛魔王", "二郎神");
    console.log(arr);
    console.log(result);
    

    image-20201017215527496

    shift()方法演示:该方法可以删除数组的第一个元素,并将被删除的元素作为返回值返回

    var arr = ["孙悟空", "猪八戒", "沙和尚"];
    var result = arr.shift();
    console.log(arr);
    console.log(result);
    

    image-20201017215800977

    forEach()方法演示:该方法可以用来遍历数组

    forEach()方法需要一个函数作为参数,像这种函数,由我们创建但是不由我们调用的,我们称为回调函数。数组中有几个元素函数就会执行几次,每次执行时,浏览器会将遍历到的元素,以实参的形式传递进来,我们可以来定义形参,来读取这些内容,浏览器会在回调函数中传递三个参数:

    • 第一个参数:就是当前正在遍历的元素
    • 第二个参数:就是当前正在遍历的元素的索引
    • 第三个参数:就是正在遍历的数组

    注意:这个方法只支持IE8以上的浏览器,IE8及以下的浏览器均不支持该方法,所以如果需要兼容IE8,则不要使用forEach(),还是使用for循环来遍历数组。

    var arr = ["孙悟空", "猪八戒", "沙和尚"];
    arr.forEach(function (value, index, obj) {
        console.log(value + " #### " + index + " #### " + obj);
    });
    

    image-20201017220618530

    slice()方法演示:该方法可以用来从数组提取指定元素,该方法不会改变元素数组,而是将截取到的元素封装到一个新数组中返回

    参数:

    • 第一个参数:截取开始的位置的索引,包含开始索引
    • 第二个参数:截取结束的位置的索引,不包含结束索引,第二个参数可以省略不写,此时会截取从开始索引往后的所有元素

    注意:索引可以传递一个负值,如果传递一个负值,则从后往前计算,-1代表倒数第一个,-2代表倒数第二个。

    var arr = ["孙悟空", "猪八戒", "沙和尚", "唐僧", "白骨精"];
    var result = arr.slice(1, 4);
    console.log(result);
    result = arr.slice(3);
    console.log(result);
    result = arr.slice(1, -2);
    console.log(result);
    

    image-20201018090855439

    splice()方法演示:该方法可以用于删除数组中的指定元素,该方法会影响到原数组,会将指定元素从原数组中删除,并将被删除的元素作为返回值返回

    参数:

    • 第一个参数:表示开始位置的索引
    • 第二个参数:表示要删除的元素数量
    • 第三个参数及以后参数:可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边
    var arr = ["孙悟空", "猪八戒", "沙和尚", "唐僧", "白骨精"];
    var result = arr.splice(3, 2);
    console.log(arr);
    console.log(result);
    result = arr.splice(1, 0, "牛魔王", "铁扇公主", "红孩儿");
    console.log(arr);
    console.log(result);
    

    image-20201018091447071

    concat()方法演示:该方法可以连接两个或多个数组,并将新的数组返回,该方法不会对原数组产生影响

    var arr = ["孙悟空", "猪八戒", "沙和尚"];
    var arr2 = ["白骨精", "玉兔精", "蜘蛛精"];
    var arr3 = ["二郎神", "太上老君", "玉皇大帝"];
    var result = arr.concat(arr2, arr3, "牛魔王", "铁扇公主");
    console.log(result);
    

    image-20201018122134527

    join()方法演示:该方法可以将数组转换为一个字符串,该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回,在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符,如果不指定连接符,则默认使用,作为连接符

    var arr = ["孙悟空", "猪八戒", "沙和尚"];
    var result = arr.join("@-@");
    console.log(result);
    

    image-20201018122403396

    reverse()方法演示:该方法用来反转数组(前边的去后边,后边的去前边),该方法会直接修改原数组

    var arr = ["孙悟空", "猪八戒", "沙和尚"];
    arr.reverse();
    console.log(arr);
    

    image-20201018122520134

    sort()方法演示:该方法可以用来对数组中的元素进行排序,也会影响原数组,默认会按照Unicode编码进行排序

    var arr = ["b", "c", "a"];
    arr.sort();
    console.log(arr);
    

    image-20201018123042465

    注意:即使对于纯数字的数组,使用sort()排序时,也会按照Unicode编码来排序,所以对数字进排序时,可能会得到错误的结果。

    var arr = [1, 3, 2, 11, 5, 6];
    arr.sort();
    console.log(arr);
    

    image-20201018123124230

    我们可以自己来指定排序的规则,我们可以在sort()添加一个回调函数,来指定排序规则,回调函数中需要定义两个形参,浏览器将会分别使用数组中的元素作为实参去调用回调函数,使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边,浏览器会根据回调函数的返回值来决定元素的顺序,如下:

    • 如果返回一个大于0的值,则元素会交换位置
    • 如果返回一个小于0的值,则元素位置不变
    • 如果返回一个等于0的值,则认为两个元素相等,也不交换位置

    经过上边的规则,我们可以总结下:

    • 如果需要升序排列,则返回 a-b
    • 如果需要降序排列,则返回 b-a
    var arr = [1, 3, 2, 11, 5, 6];
    arr.sort(function (a, b) {
        return a - b;
    });
    console.log(arr);
    

    image-20201018123008856

    3.2、函数对象

    3.2.1、call()和apply()

    call()和apply()这两个方法都是函数对象的方法,需要通过函数对象来调用,当对函数调用call()和apply()都会调用函数执行,在调用call()和apply()可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this,call()方法可以将实参在对象之后依次传递,apply()方法需要将实参封装到一个数组中统一传递,如下演示:

    call()方法演示:

    function fun(a, b) {
        console.log("a = " + a);
        console.log("b = " + b);
        console.log("fun = " + this);
    }
    
    var obj = {
        name: "obj",
        sayName: function () {
            console.log(this.name);
        }
    };
    
    fun(2, 3);
    console.log("===============");
    fun.call(obj, 2, 3);
    

    image-20201018124051021

    注意:默认fun()函数调用,this指向的是window对象,你可以使用call()调用函数,在调用的时候传入一个对象,这个对象就是this所指向的对象,也就是说,可以自己指定this的指向,然后从第二个参数开始,实参将会依次传递

    apply()方法演示:

    function fun(a, b) {
        console.log("a = " + a);
        console.log("b = " + b);
        console.log("fun = " + this);
    }
    
    var obj = {
        name: "obj",
        sayName: function () {
            console.log(this.name);
        }
    };
    
    fun(2, 3);
    console.log("===============");
    fun.apply(obj, [2, 3]);
    

    image-20201018123915931

    注意:默认fun()函数调用,this指向的是window对象,你可以使用apply()调用函数,在调用的时候传入一个对象,这个对象就是this所指向的对象,也就是说,可以自己指定this的指向,然后从第二个参数开始,需要制定一个实参数组进行参数传递

    3.2.2、this指向

    • 以函数形式调用时,this永远都是window
    • 以方法的形式调用时,this是调用方法的对象
    • 以构造函数的形式调用时,this是新创建的那个对象
    • 使用call和apply调用时,this是传入的那个指定对象

    3.2.3、arguments参数

    在调用函数时,浏览器每次都会传递进两个隐含的参数:

    1. 函数的上下文对象: this
    2. 封装实参的对象: arguments

    this对象我们已经学习过了,那arguments对象是什么呢?

    arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度,在调用函数时,我们所传递的实参都会在arguments中保存,比如:arguments.length 可以用来获取实参的长度,我们即使不定义形参,也可以通过arguments来使用实参,只不过比较麻烦,例如:

    • arguments[0]:表示第一个实参
    • arguments[1]:表示第二个实参

    它里边有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数的对象。

    arguments对象演示:

    function fun(a, b) {
        // 通过下标获取第一个参数
        console.log(arguments[0]);
        // 通过下标获取第二个参数
        console.log(arguments[1]);
        // 获取实参的个数
        console.log(arguments.length);
        // 看看它的函数对象
        console.log(arguments.callee);
        console.log(arguments.callee == fun);
    }
    
    fun("Hello", "World");
    

    image-20201018125309350

    3.3、Date对象

    在JavaScript中使用Date对象来表示一个时间,如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间。

    案例演示:

    var date = new Date();
    console.log(date);
    
    console.log(date.getFullYear());//获取当前日期对象的年份(四位数字年份)
    console.log(date.getMonth());//获取当前日期对象的月份(0 ~ 11)
    console.log(date.getDate());//获取当前日期对象的日数(1 ~ 31)
    console.log(date.getHours());//获取当前日期对象的小时(0 ~ 23)
    console.log(date.getMinutes());//获取当前日期对象的分钟(0 ~ 59)
    console.log(date.getSeconds());//获取当前日期对象的秒钟(0 ~ 59)
    console.log(date.getMilliseconds());//获取当前日期对象的毫秒(0 ~ 999)
    

    image-20201018130252223

    更多方法: 参考网站

    3.4、Math对象

    Math和其它的对象不同,它不是一个构造函数,它属于一个工具类不用创建对象,它里边封装了数学运算相关的属性和方法。

    案例演示:

    /*固定值*/
    console.log("PI = " + Math.PI);
    console.log("E  = " + Math.E);
    console.log("===============");
    /*正数*/
    console.log(Math.abs(1));        //可以用来计算一个数的绝对值
    console.log(Math.ceil(1.1));     //可以对一个数进行向上取整,小数位只有有值就自动进1
    console.log(Math.floor(1.99));   //可以对一个数进行向下取整,小数部分会被舍掉
    console.log(Math.round(1.4));    //可以对一个数进行四舍五入取整
    console.log("===============");
    /*负数*/
    console.log(Math.abs(-1));       //可以用来计算一个数的绝对值
    console.log(Math.ceil(-1.1));    //可以对一个数进行向上取整,小数部分会被舍掉
    console.log(Math.floor(-1.99));  //可以对一个数进行向下取整,小数位只有有值就自动进1
    console.log(Math.round(-1.4));   //可以对一个数进行四舍五入取整
    console.log("===============");
    /*随机数*/
    //Math.random():可以用来生成一个0-1之间的随机数
    //生成一个0-x之间的随机数:Math.round(Math.random()*x)
    //生成一个x-y之间的随机数:Math.round(Math.random()*(y-x)+x)
    console.log(Math.round(Math.random() * 10));            //生成一个0-10之间的随机数
    console.log(Math.round(Math.random() * (10 - 1) + 1));  //生成一个1-10之间的随机数
    console.log("===============");
    /*数学运算*/
    console.log(Math.pow(12, 3));   //Math.pow(x,y):返回x的y次幂
    console.log(Math.sqrt(4));      //Math.sqrt(x) :返回x的平方根
    

    image-20201018132005284

    更多方法: 参考网站

    3.5、String对象

    3.5.1、概述

    在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象

    • String():可以将基本数据类型字符串转换为String对象
    • Number():可以将基本数据类型的数字转换为Number对象
    • Boolean():可以将基本数据类型的布尔值转换为Boolean对象

    但是注意:我们在实际应用中不会使用基本数据类型的对象,如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果,在这一章节中,我们重点介绍String()对象的属性和方法。

    3.5.2、字符串属性

    constructor属性演示:返回创建字符串对象的原型函数

    var str = "Hello,World!";
    console.log(str.constructor);
    

    image-20201018152739858

    length属性演示:可以用来获取字符串的长度

    var str = "Hello,World!";
    console.log(str.length);
    

    image-20201018152511480

    3.5.3、字符串方法

    charAt()方法演示:该方法可以根据索引获取指定位置的字符

    var str = "Hello,World!";
    console.log(str.charAt(1));
    

    image-20201018153002150

    charCodeAt()方法演示:该方法获取指定位置字符的字符编码(Unicode编码)

    var str = "Hello,World!";
    console.log(str.charCodeAt(1));
    

    image-20201018153218872

    concat()方法演示:该方法可以用来连接两个或多个字符串

    var str = "Hello,World!";
    console.log(str.concat("你好,", "世界!"));
    

    image-20201018153504935

    indexof()方法演示:该方法可以检索一个字符串中是否含有指定内容,如果字符串中含有该内容,则会返回其第一次出现的索引,如果没有找到指定的内容,则返回-1,可以指定一个第二个参数,指定开始查找的位置

    var str = "Hello,World!";
    console.log(str.indexOf("o"));
    console.log(str.indexOf("o", 5));
    

    image-20201018160212146

    lastIndexOf()方法演示:该方法的用法和indexOf()一样,不同的是indexOf是从前往后找,而lastIndexOf是从后往前找,也可以指定开始查找的位置

    var str = "Hello,World!";
    console.log(str.lastIndexOf("o"));
    console.log(str.lastIndexOf("o", 5));
    

    slice()方法演示:可以从字符串中截取指定的内容,不会影响原字符串,而是将截取到内容返回

    参数:

    • 第一个参数:开始位置的索引(包括开始位置)
    • 第二个参数:结束位置的索引(不包括结束位置),如果省略第二个参数,则会截取到后边所有的

    注意:也可以传递一个负数作为参数,负数的话将会从后边计算

    var str = "Hello,World!";
    var result = str.slice(1, 4);
    console.log(result);
    result = str.slice(1);
    console.log(result);
    result = str.slice(1, -1);
    console.log(result);
    

    image-20201018160909634

    substring()方法演示:可以用来截取一个字符串,它和slice()类似

    参数:

    • 第一个参数:开始截取位置的索引(包括开始位置)
    • 第二个参数:结束位置的索引(不包括结束位置),如果省略第二个参数,则会截取到后边所有的

    注意:不同的是这个方法不能接受负值作为参数,如果传递了一个负值,则默认使用0,而且它还自动调整参数的位置,如果第二个参数小于第一个,则自动交换

    var str = "Hello,World!";
    var result = str.substring(1, 4);
    console.log(result);
    result = str.substring(1);
    console.log(result);
    result = str.substring(1, -1);
    console.log(result);
    

    image-20201018160942481

    substr()方法演示:该方法用来截取字符串

    参数:

    • 第一个参数:截取开始位置的索引
    • 第二个参数:截取的长度
    var str = "Hello,World!";
    var result = str.substr(6, 6);
    console.log(result);
    

    image-20201018161859192

    split()方法演示:该方法可以将一个字符串拆分为一个数组,需要一个字符串作为参数,将会根据该字符串去拆分数组

    var str = "Hello,World!";
    var result = str.split(",");
    console.log(result);
    

    image-20201018162029011

    toUpperCase()方法演示:将一个字符串转换为大写并返回

    var str = "Hello,World!";
    var result = str.toUpperCase();
    console.log(result);
    

    image-20201018162118218

    toLowerCase()方法演示:将一个字符串转换为小写并返回

    var str = "Hello,World!";
    var result = str.toLowerCase();
    console.log(result);
    

    image-20201018162241087

    3.6、RegExp对象

    3.6.1、概述

    正则表达式用于定义一些字符串的规则,计算机可以根据正则表达式,来检查一个字符串是否符合规则,获取将字符串中符合规则的内容提取出来。

    使用typeof检查正则对象,会返回object。

    3.6.2、创建正则对象

    3.6.2.1、使用对象创建

    语法格式:

    var 变量名 = new RegExp("正则表达式","匹配模式");
    

    匹配模式:

    • i:忽略大小写
    • g:全局匹配模式
    • ig:忽略大小写且全局匹配模式

    案例演示:

    // 这个正则表达式可以来检查一个字符串中是否含有a
    var reg = new RegExp("ab", "i");
    var str = "Abc";
    var result = reg.test(str);
    console.log(result);
    

    image-20201018163156692

    3.6.2.2、使用字面量创建

    语法格式:

    var 变量名 = /正则表达式/匹配模式;
    

    匹配模式:

    • i:忽略大小写
    • g:全局匹配模式
    • m:执行多行匹配

    注意:可以为一个正则表达式设置多个匹配模式,且顺序无所谓

    案例演示:

    // 这个正则表达式可以来检查一个字符串中是否含有a
    var reg = /a/i;
    var str = "Abc";
    var result = reg.test(str);
    console.log(result);
    

    image-20201018163156692

    3.6.3、正则进阶

    需求信息:创建一个正则表达式,检查一个字符串中是否有a或b

    语法格式:使用 | 表示或者的意思

    // 这个正则表达式可以来检查一个字符串中是否含有a
    var reg = /a|b|c/;
    var str = "Abc";
    var result = reg.test(str);
    console.log(result);
    

    image-20201018164941099

    试想一下,如果我们现在要是想要检查一个字符串是否含有小写字母,那我们是不是可以reg = /a|b|c|d|e|f|g ... /;这么写,但是你会发现,好啰嗦啊,怎么这么麻烦呢,有没有一种更简单的方式,答案是肯定的。

    需求信息:创建一个正则表达式,检查一个字符串中是否有字母

    语法格式:[ ] 里的内容也是或的关系

    // 这个正则表达式可以来检查一个字符串中是否含有字母
    var reg = /[A-z]/;
    var str = "Abc";
    var result = reg.test(str);
    console.log(result);
    

    image-20201018171936882

    常见组合:

    • [a-z]:任意小写字母
    • [A-Z]:任意大写字母
    • [A-z]:任意字母
    • [0-9]:任意数字

    需求信息:创建一个正则表达式,检查一个字符串中是否含有 abc 或 adc 或 aec

    // 这个正则表达式可以来检查一个字符串中是否含有abc或adc或aec
    var reg = /a[bde]c/;
    var str = "abc123";
    var result = reg.test(str);
    console.log(result);
    

    那现在我们已经学会了判断是否包含,那要是判断除了某些字符序列该咋整,只需要这么写[^字符序列]

    常见组合:

    • [^a-z]:除了任意小写字母
    • [^A-Z]:除了任意大写字母
    • [^A-z]:除了任意字母
    • [^0-9]:除了任意数字

    需求信息:创建一个正则表达式,检查一个字符串中是否除了数字还有其它字母

    // 这个正则表达式可以来检查一个字符串中是否除了数字还有其它字母
    var reg = /[^0-9]/;
    var str = "0123456789";
    var result = reg.test(str);
    console.log(result);
    

    3.6.4、正则方法

    这些正则方法其实都是字符串的方法,但是它的参数需要传递正则表达式,在这里,我就先称为正则方法。

    split()方法演示:该方法可以将一个字符串拆分为一个数组,方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串,这个方法即使不指定全局匹配,也会全都插分

    var str = "1a2b3c4d5e6f7";
    var result = str.split(/[A-z]/);
    console.log(result);
    

    image-20201018212920528

    search()方法演示:该方法可以搜索字符串中是否含有指定内容,如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回-1,它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串,serach()只会查找第一个,即使设置全局匹配也没用

    var str = "hello abc hello aec afc";
    var result = str.search(/a[bef]c/);
    console.log(result);
    

    image-20201018213217017

    match()方法演示:该方法可以根据正则表达式,从一个字符串中将符合条件的内容提取出来,默认情况下我们的match()只会找到第一个符合要求的内容,找到以后就停止检索,我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容,可以为一个正则表达式设置多个匹配模式,且顺序无所谓,match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果

    var str = "1a2a3a4a5e6f7A8B9C";
    var result = str.match(/[a-z]/ig);
    console.log(result);
    

    image-20201018213447809

    replace()方法演示:该方法可以将字符串中指定内容替换为新的内容,默认只会替换第一个,但是可以设置全局匹配替换全部

    参数:

    • 第一个参数:被替换的内容,可以接受一个正则表达式作为参数
    • 第二个参数:新的内容
    var str = "1a2a3a4a5e6f7A8B9C";
    var result = str.replace(/[a-z]/gi, "@_@");
    console.log(result);
    

    image-20201018213653322

    3.6.5、正则量词

    通过量词可以设置一个内容出现的次数,量词只对它前边的一个内容起作用,如果有多个内容可以使用 () 括起来,常见量词如下:

    • {n} :正好出现n次
    • {m,} :出现m次及以上
    • {m,n} :出现m-n次
    • + :至少一个,相当于{1,}
    • * :0个或多个,相当于{0,}
    • ? :0个或1个,相当于{0,1}
    var str = "abbc";
    
    reg = /(ab){3}/;
    console.log(reg.test(str));
    console.log("===============");
    reg = /b{3}/;
    console.log(reg.test(str));
    console.log("===============");
    reg = /ab{1,3}c/;
    console.log(reg.test(str));
    console.log("===============");
    reg = /ab{3,}c/;
    console.log(reg.test(str));
    console.log("===============");
    reg = /ab+c/;
    console.log(reg.test(str));
    console.log("===============");
    reg = /ab*c/;
    console.log(reg.test(str));
    console.log("===============");
    reg = /ab?c/;
    console.log(reg.test(str));
    console.log("===============");
    

    image-20201018214346309

    3.6.6、正则高阶

    如果我们要检查或者说判断是否以某个字符或者字符序列开头或者结尾就会使用^$

    • ^ :表示开头,注意它在[^字符序列]表达的意思不一样
    • $ :表示结尾

    需求描述:检查一个字符串中是否以a开头

    var str = "abcabca";
    var reg = /^a/;
    console.log(reg.test(str));
    

    image-20201018214857304

    需求描述:检查一个字符串中是否以a结尾

    var str = "abcabca";
    var reg = /a$/;
    console.log(reg.test(str));
    

    image-20201018214953184

    那如果我们想要检查一个字符串中是否含有.\就会使用转义字符

    • \. :表示.
    • \\ :表示\

    注意:使用构造函数时,由于它的参数是一个字符串,而\是字符串中转义字符,如果要使用\则需要使用\\来代替

    var reg1 = /\./;
    var reg2 = /\\/;
    var reg3 = new RegExp("\\.");
    var reg4 = new RegExp("\\\\");
    

    除了以上两种特殊的字符,其实还有很多如下所示:

    • \w :任意字母、数字、_,相当于[A-z0-9_]
    • \W :除了字母、数字、_,相当于[^A-z0-9_]
    • \d :任意的数字,相当于[0-9]
    • \D :除了任意的数字,相当于[^0-9]
    • \s :空格
    • \S :除了空格
    • \b :单词边界
    • \B :除了单词边界

    这里边我们就演示最后四个,其它的都比较简单,后边的案例也会涉及,这里就不演示了

    需求描述:创建一个正则表达式,去除掉字符串中的前后的空格

    var str = "  hello child  "
    var reg = /^\s*|\s*$/g;
    console.log(str);
    str = str.replace(reg, "");
    console.log(str);
    

    image-20201018220522294

    需求描述:创建一个正则表达式,检查一个字符串中是否含有单词child

    var str = "hello child"
    var reg = /\bchild\b/;
    console.log(reg.test(str));
    

    image-20201018220305875

    3.6.7、正则案例

    3.6.7.1、检查手机号

    var phoneStr = "15131494600";
    var phoneReg = /^1[3-9][0-9]{9}$/;
    console.log(phoneReg.test(phoneStr));
    

    image-20201018220305875

    3.6.7.2、检查邮箱号

    var emailStr = "abc.def@163.com";
    var emailReg = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;
    console.log(emailReg.test(emailStr));
    

    image-20201018220717578

    第四章 JavaScript DOM

    4.1、DOM概述

    当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。

    HTML DOM 模型被结构化为 对象树

    image-20201019104459658

    通过这个对象模型,JavaScript 获得创建动态 HTML 的所有力量:

    • JavaScript 能改变页面中的所有 HTML 元素
    • JavaScript 能改变页面中的所有 HTML 属性
    • JavaScript 能改变页面中的所有 CSS 样式
    • JavaScript 能删除已有的 HTML 元素和属性
    • JavaScript 能添加新的 HTML 元素和属性
    • JavaScript 能对页面中所有已有的 HTML 事件作出反应
    • JavaScript 能在页面中创建新的 HTML 事件

    换言之:HTML DOM 是关于如何获取、更改、添加或删除 HTML 元素的标准。

    4.2、DOM文档节点

    4.2.1、节点概述

    节点Node,是构成我们网页的最基本的组成部分,网页中的每一个部分都可以称为是一个节点。

    比如:html标签、属性、文本、注释、整个文档等都是一个节点。

    虽然都是节点,但是实际上它们的具体类型是不同的。

    比如:标签我们称为元素节点、属性称为属性节点、文本称为 文本节点、文档称为文档节点。

    节点的类型不同,属性和方法也都不尽相同。

    节点:Node——构成HTML文档最基本的单元。

    常用节点分为四类:

    • 文档节点:整个HTML文档
    • 元素节点:HTML文档中的HTML标签
    • 属性节点:元素的属性
    • 文本节点:HTML标签中的文本内容

    image-20201019115515595

    4.2.2、节点属性

    image-20201019115655478

    4.2.3、文档节点

    文档节点(Document)代表的是整个HTML文 档,网页中的所有节点都是它的子节点。

    document对象作为window对象的属性存在的,我们不用获取可以直接使用。

    通过该对象我们可以在整个文档访问内查找节点对象,并可以通过该对象创建各种节点对象。

    4.2.4、元素节点

    HTML中的各种标签都是元素节点(Element),这也是我们最常用的一个节点。

    浏览器会将页面中所有的标签都转换为一个元素节点, 我们可以通过document的方法来获取元素节点。

    例如:document.getElementById(),根据id属性值获取一个元素节点对象。

    4.2.5、属性节点

    属性节点(Attribute)表示的是标签中的一个一个的属 性,这里要注意的是属性节点并非是元素节点的子节点,而是元素节点的一部分。可以通过元素节点来获取指定的属性节点。

    例如:元素节点.getAttributeNode("属性名"),根据元素节点的属性名获取一个属性节点对象。

    注意:我们一般不使用属性节点。

    4.2.6、文本节点

    文本节点(Text)表示的是HTML标签以外的文本内容,任意非HTML的文本都是文本节点,它包括可以字面解释的纯文本内容。文本节点一般是作为元素节点的子节点存在的。获取文本节点时,一般先要获取元素节点,在通过元素节点获取文本节点。

    例如:元素节点.firstChild;,获取元素节点的第一个子节点,一般为文本节点。

    4.3、DOM文档操作

    文档对象代表您的网页,,如果您希望访问 HTML 页面中的任何元素,那么您总是从访问 document 对象开始。

    下面是一些如何使用 document 对象来访问和操作 HTML 的实例。

    4.3.1、查找 HTML 元素

    4.3.1.1、方法介绍

    方法描述
    document.getElementById(id)通过元素 id 来查找元素。
    document.getElementsByTagName(name)通过标签名来查找元素。
    document.getElementsByClassName(name)通过类名来查找元素。
    document.querySelector(CSS选择器)通过CSS选择器选择一个元素。
    document.querySelectorAll(CSS选择器)通过CSS选择器选择多个元素。

    4.3.1.2、方法演示

    需求描述:创建一个按钮,通过id获取按钮节点对象

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <button id="btn">我是按钮</button>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var btn = document.getElementById("btn");
        console.log(btn);
    </script>
    </body>
    </html>
    

    image-20201019140936584

    需求描述:创建一个按钮,通过标签名获取按钮节点对象数组

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <button>我是按钮</button>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var btn = document.getElementsByTagName("button");
        console.log(btn);
    </script>
    </body>
    </html>
    

    image-20201019141202534

    需求描述:创建一个按钮,通过类名获取按钮节点对象数组

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <button class="btn">我是按钮</button>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var btn = document.getElementsByClassName("btn");
        console.log(btn);
    </script>
    </body>
    </html>
    

    image-20201019141405002

    需求描述:创建一个按钮,通过CSS选择器选择该按钮

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <button class="btn">我是按钮</button>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var btn = document.querySelector(".btn");
        console.log(btn);
    </script>
    </body>
    </html>
    

    image-20201020090857926

    需求描述:创建一个无序列表,通过CSS选择器选择该列表的所有li

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <ul class="list">
        <li>列表项1</li>
        <li>列表项2</li>
        <li>列表项3</li>
        <li>列表项4</li>
    </ul>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var list = document.querySelectorAll(".list li");
        console.log(list);
    </script>
    </body>
    </html>
    

    image-20201020091354415

    4.3.2、获取 HTML 的值

    4.3.2.1、方法介绍

    方法描述
    元素节点.innerText获取 HTML 元素的 inner Text。
    元素节点.innerHTML获取 HTML 元素的 inner HTML。
    元素节点.属性获取 HTML 元素的属性值。
    元素节点.getAttribute(attribute)获取 HTML 元素的属性值。
    元素节点.style.样式获取 HTML 元素的行内样式值。

    4.3.2.2、方法演示

    需求描述:创建一个按钮,然后获取按钮的文本内容

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <button id="btn">我是按钮</button>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var btn = document.getElementById("btn");
        console.log(btn.innerText);
    </script>
    </body>
    </html>
    

    image-20201020093332082

    需求描述:创建一个div,然后在div中插入一个h1标题,获取div中的html代码

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div id="box">
        <h1>我是Box中的大标题</h1>
    </div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var box = document.getElementById("box");
        console.log(box.innerHTML);
    </script>
    </body>
    </html>
    

    image-20201020093459855

    需求描述:创建一个超链接,默认为空,设置href属性为https://www.baidu.com ,使用JavaScript代码读取href属性

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <a id="a" href="https://www.baidu.com">打开百度,你就知道!</a>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var a = document.getElementById("a");
        console.log(a.href);
    </script>
    </body>
    </html>
    

    image-20201020093633259

    需求描述:创建一个超链接,默认为空,设置href属性为https://www.baidu.com ,使用JavaScript代码读取href属性

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <a id="a" href="https://www.baidu.com">打开百度,你就知道!</a>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var a = document.getElementById("a");
        console.log(a.getAttribute("href"));
    </script>
    </body>
    </html>
    

    image-20201020093817197

    需求描述:创建一个正方形div,默认颜色为红色,使用JavaScript代码获取div的宽度

    注意:如果CSS的样式名中含有-,这种名称在JS中是不合法的比如background-color,需要将这种样式名修改为驼峰命名法,去掉-,然后将-后的字母大写,我们通过style属性设置的样式都是行内样式,同样的获取也是行内样式,而行内样式有较高的优先级,所以通过JS修改的样式往往会立即显示,但是如果在样式中写了!important,则此时样式会有最高的优先级,即使通过JS也不能覆盖该样式,此时将会导致JS修改样式失效,所以尽量不要为样式添加!important

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div style="width: 100px;height: 100px;background: red;" id="box"></div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var box = document.getElementById("box");
        console.log(box.style.width);
    </script>
    </body>
    </html>
    

    image-20201020094411123

    拓展知识1:

    通过style属性设置和读取的都是内联样式,无法读取样式表中的样式或者说正在应用的样式,如果想要读取当前正在应用的样式属性我们可以使用元素.currentStyle.样式名来获取元素的当前显示的样式,它可以用来读取当前元素正在显示的样式,如果当前元素没有设置该样式,则获取它的默认值,但是currentStyle只有IE浏览器支持,其它的浏览器都不支持,在其它浏览器中可以使用getComputedStyle()这个方法来获取元素当前的样式,这个方法是window的方法,可以直接使用,但是需要两个参数:

    • 第一个参数:要获取样式的元素
    • 第二个参数:可以传递一个伪元素,一般都传null

    该方法会返回一个对象,对象中封装了当前元素对应的样式,可以通过 对象.样式名 来读取样式,如果获取的样式没有设置,则会获取到真实的值,而不是默认值,比如:没有设置width,它不会获取到auto,而是一个长度,但是该方法不支持IE8及以下的浏览器。通过currentStyle和getComputedStyle()读取到的样式都是只读的,不能修改,如果要修改必须通过style属性,因此,我们可以写一个适配各个浏览器的读取元素样式的方法。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            /*样式表的样式*/
            #box {
                width: 200px;
                height: 200px;
                background-color: green;
            }
        </style>
    </head>
    <body>
    <div style="width: 100px;height: 100px;" id="box"></div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        /*通用的获取元素样式的方法*/
        function getStyle(obj, name) {
            if (window.getComputedStyle) {
                //正常浏览器的方式,具有getComputedStyle()方法
                return getComputedStyle(obj, null)[name];
            } else {
                //IE8的方式,没有getComputedStyle()方法
                return obj.currentStyle[name];
            }
        }
    
        var box = document.getElementById("box");
    
        console.log(getStyle(box, "width"));
        console.log(getStyle(box, "height"));
        console.log(getStyle(box, "background-color"));
    </script>
    </body>
    </html>
    

    谷歌浏览器:

    image-20201020100255039

    火狐浏览器:

    image-20201020100316096

    IE9-IE11 浏览器:

    image-20201020100443311

    IE5-IE8 浏览器:

    image-20201020100934400

    有同学会说,在IE5-IE8 浏览器中,老师这不是还不一样吗?因此我们建议设置颜色数值一般采用rgb或者rgba,最好不要采用英文单词的这种颜色值,这样最终展示出来的效果就一致了。

    拓展知识2:编写一段兼容性代码,用来获取任意标签的文本内容

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <a href="https://www.baidu.com" id="a">打开百度,你就知道!</a>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var a = document.getElementById("a");
    
        console.log(getInnerText(a));
    
        /*获取任意标签的内容*/
        function getInnerText(element) {
            // 判断浏览器是否支持textContent,如果支持,则使用textContent获取内容,否则使用innerText获取内容。
            if(typeof element.textContent == "undefined") {
                return element.innerText;
            } else {
                return element.textContent;
            }
        }
    </script>
    </body>
    </html>
    

    谷歌浏览器:

    image-20201021141646565

    火狐浏览器:

    image-20201021141729927

    IE5-IE11浏览器:

    image-20201021141805607

    4.3.3、改变 HTML 的值

    4.3.3.1、方法介绍

    方法描述
    元素节点.innerText = new text content改变元素的 inner Text。
    元素节点.innerHTML = new html content改变元素的 inner HTML。
    元素节点.属性 = new value改变 HTML 元素的属性值。
    元素节点.setAttribute(attribute, value)改变 HTML 元素的属性值。
    元素节点.style.样式 = new style改变 HTML 元素的行内样式值。

    4.3.3.2、方法演示

    需求描述:创建一个按钮,然后改变按钮的文本内容

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <button id="btn">我是按钮</button>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var btn = document.getElementById("btn");
        btn.innerText = "我是JavaScript的按钮";
        console.log(btn);
    </script>
    </body>
    </html>
    

    image-20201019142137016

    需求描述:创建一个div,然后在div中插入一个h1标题

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div id="box"></div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var box = document.getElementById("box");
        box.innerHTML = "<h1>我是Box中的大标题</h1>";
        console.log(box);
    </script>
    </body>
    </html>
    

    image-20201019152023559

    **需求描述:创建一个超链接,默认为空,使用JavaScript代码设置href属性为https://www.baidu.com **

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <a id="a" href="">打开百度,你就知道!</a>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var a = document.getElementById("a");
        a.href="https://www.baidu.com";
        console.log(a);
    </script>
    </body>
    </html>
    

    image-20201019152337340

    **需求描述:创建一个超链接,默认为空,使用JavaScript代码设置href属性为https://www.baidu.com **

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <a id="a" href="">打开百度,你就知道!</a>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var a = document.getElementById("a");
        a.setAttribute("href", "https://www.baidu.com");
        console.log(a);
    </script>
    </body>
    </html>
    

    image-20201019152509296

    需求描述:创建一个正方形div,默认颜色为红色,使用JavaScript代码改变为绿色

    注意:如果CSS的样式名中含有-,这种名称在JS中是不合法的比如background-color,需要将这种样式名修改为驼峰命名法,去掉-,然后将-后的字母大写,我们通过style属性设置的样式都是行内样式,同样的获取也是行内样式,而行内样式有较高的优先级,所以通过JS修改的样式往往会立即显示,但是如果在样式中写了!important,则此时样式会有最高的优先级,即使通过JS也不能覆盖该样式,此时将会导致JS修改样式失效,所以尽量不要为样式添加!important

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div style="width: 100px;height: 100px;background: red;" id="box"></div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var box = document.getElementById("box");
        box.style.background = "green";
        console.log(box);
    </script>
    </body>
    </html>
    

    image-20201019152811146

    拓展知识1:

    修改节点的内容除了常用的innerHTML和innerText之外,还有insertAdjacentHTML和insertAdjacentText方法,可以在指定的地方插入内容。insertAdjacentText方法与insertAdjacentHTML方法类似,只不过是插入纯文本,参数相同。

    语法说明:

    object.insertAdjacentHTML(where,html);
    object.insertAdjacentText(where,text)
    

    参数说明:

    • where:

      • beforeBegin:插入到开始标签的前面
      • beforeEnd:插入到结束标签的前面
      • afterBegin:插入到开始标签的后面
      • afterEnd:插入到结束标签的后面

      img

    • html:一段html代码

    • text:一段文本值

    注意事项:

    1. 这两个方法必须等文档加载好后才能执行,否则会出错。
    2. insertAdjacentText只能插入普通文本,insertAdjacentHTML插入html代码。
    3. 使用insertAdjacentHTML方法插入script脚本文件时,必须在script元素上定义defer属性。
    4. 使用insertAdjacentHTML方法插入html代码后,页面上的元素集合将发生变化。
    5. insertAdjacentHTML方法不适用于单个的空的元素标签(如img,input等)。

    案例演示:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div id="insert">
        <p>你是我的小丫小苹果</p>
    </div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var div = document.getElementById("insert");
        div.insertAdjacentHTML('beforeBegin', '你是我的小丫小苹果');
    </script>
    </body>
    </html>
    

    image-20201020115614268

    拓展知识2:编写一段兼容性代码,用来设置任意标签的文本内容

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <a href="https://www.baidu.com" id="a">打开百度,你就知道!</a>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var a = document.getElementById("a");
        
        setInnerText(a, "你要打开百度吗?");
    
        console.log(getInnerText(a));
    
        /*获取任意标签的内容*/
        function getInnerText(element) {
            // 判断浏览器是否支持textContent,如果支持,则使用textContent获取内容,否则使用innerText获取内容。
            if (typeof element.textContent == "undefined") {
                return element.innerText;
            } else {
                return element.textContent;
            }
        }
    
        /*设置任意标签的内容*/
        function setInnerText(element, text) {
            // 判断浏览器是否支持textContent,如果支持,则使用textContent设置内容,否则使用innerText设置内容。
            if (typeof element.textContent == "undefined") {
                return element.innerText = text;
            } else {
                return element.textContent = text;
            }
        }
    </script>
    </body>
    </html>
    

    谷歌浏览器:

    image-20201021142036915

    火狐浏览器:

    image-20201021142051365

    IE5-IE11浏览器:

    image-20201021142124568

    4.3.4、修改 HTML 元素

    4.3.4.1、方法介绍

    方法描述
    document.createElement(element)创建 HTML 元素节点。
    document.createAttribute(attribute)创建 HTML 属性节点。
    document.createTextNode(text)创建 HTML 文本节点。
    元素节点.removeChild(element)删除 HTML 元素。
    元素节点.appendChild(element)添加 HTML 元素。
    元素节点.replaceChild(element)替换 HTML 元素。
    元素节点.insertBefore(element)在指定的子节点前面插入新的子节点。

    4.3.4.2、方法演示

    案例演示1:创建一个ul列表,然后在该列表中追加4个li标签

    第一种方法:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var ul = document.createElement("ul");
    
        var li1 = document.createElement("li");
        var text1 = document.createTextNode("列表项1");
        li1.appendChild(text1);
        ul.appendChild(li1);
    
        var li2 = document.createElement("li");
        var text2 = document.createTextNode("列表项2");
        li2.appendChild(text2);
        ul.appendChild(li2);
    
        var li3 = document.createElement("li");
        var text3 = document.createTextNode("列表项3");
        li3.appendChild(text3);
        ul.appendChild(li3);
    
        var li4 = document.createElement("li");
        var text4 = document.createTextNode("列表项4");
        li4.appendChild(text4);
        ul.appendChild(li4);
    
        document.getElementsByTagName("body")[0].appendChild(ul);
    </script>
    </body>
    </html>
    

    image-20201020111240435

    第二种方法:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var ul = document.createElement("ul");
    
        var li1 = document.createElement("li");
        li1.innerHTML = "列表项1";
        ul.appendChild(li1);
    
        var li2 = document.createElement("li");
        li2.innerHTML = "列表项2";
        ul.appendChild(li2);
    
        var li3 = document.createElement("li");
        li3.innerHTML = "列表项3";
        ul.appendChild(li3);
    
        var li4 = document.createElement("li");
        li4.innerHTML = "列表项4";
        ul.appendChild(li4);
    
        document.getElementsByTagName("body")[0].appendChild(ul);
    </script>
    </body>
    </html>
    

    image-20201020111408190

    第三种方法:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var ul = document.createElement("ul");
    
        var li1 = "<li>列表项1</li>";
        var li2 = "<li>列表项2</li>";
        var li3 = "<li>列表项3</li>";
        var li4 = "<li>列表项4</li>";
        ul.innerHTML = li1 + li2 + li3 + li4;
    
        document.getElementsByTagName("body")[0].appendChild(ul);
    </script>
    </body>
    </html>
    

    image-20201020111719891

    案例演示2:创建一个ul列表,里边有四个li子元素,删除第一个li,替换最后一个li

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <ul id="ul">
        <li id="first">列表项1</li>
        <li>列表项2</li>
        <li>列表项3</li>
        <li id="last">列表项4</li>
    </ul>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var ul = document.getElementById("ul");
        var first = document.getElementById("first");
        var last = document.getElementById("last");
    
        /*删除第一个*/
        ul.removeChild(first);
    
        /*替换最后一个*/
        var replaceLi = document.createElement("li");
        replaceLi.innerHTML = "列表4的替换";
        ul.replaceChild(replaceLi, last);
    </script>
    </body>
    </html>
    

    image-20201020113211173

    案例演示3:创建一个ul列表,里边有四个li子元素,在第一个li前边插入一个id为zero的li

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <ul id="ul">
        <li id="first">列表项1</li>
        <li>列表项2</li>
        <li>列表项3</li>
        <li>列表项4</li>
    </ul>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var ul = document.getElementById("ul");
        var first = document.getElementById("first");
    
        var zero = document.createElement("li");
        zero.innerHTML = "列表0的新增";
        
        ul.insertBefore(zero, first);
    </script>
    </body>
    </html>
    

    image-20201020115016443

    拓展知识:

    动态判断、添加、删除、切换样式,支持IE5-IE11,谷歌浏览器、火狐浏览器等

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .b1 {
                width: 100px;
                height: 100px;
                background-color: red;
            }
    
            .b2 {
                width: 300px;
                height: 300px;
                background-color: yellow;
            }
        </style>
    </head>
    <body>
    <button id="btn0">判断b2样式</button>
    <button id="btn1">添加b2样式</button>
    <button id="btn2">删除b2样式</button>
    <button id="btn3">切换b2样式</button>
    
    <br>
    <br>
    
    <div id="box" class="b1"></div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var btn0 = document.getElementById("btn0");
        var btn1 = document.getElementById("btn1");
        var btn2 = document.getElementById("btn2");
        var btn3 = document.getElementById("btn3");
        var box = document.getElementById("box");
    
        btn0.onclick = function () {
            alert(hasClass(box, "b2"));
        };
    
        btn1.onclick = function () {
            addClass(box, "b2");
        };
    
        btn2.onclick = function () {
            removeClass(box, "b2");
        };
    
        btn3.onclick = function () {
            toggleClass(box, "b2");
        };
    
        /*
         * 判断一个元素中是否含有指定的class属性值
         * 如果有该class,则返回true,没有则返回false
         */
        function hasClass(obj, cn) {
            var reg = new RegExp("\\b" + cn + "\\b");
            return reg.test(obj.className);
        }
    
        /*
         * 向一个元素中添加指定的class属性值
         * 参数:
         * 	obj 要添加class属性的元素
         *  cn 要添加的class值
         */
        function addClass(obj, cn) {
            // 检查obj中是否含有cn
            if (!hasClass(obj, cn)) {
                obj.className += " " + cn;
            }
        }
    
        /*
         * 删除一个元素中的指定的class属性
         */
        function removeClass(obj, cn) {
            var reg = new RegExp("\\b" + cn + "\\b");
            obj.className = obj.className.replace(reg, "");
        }
    
        /*
         * toggleClass可以用来切换一个类
         * 	如果元素中具有该类,则删除
         * 	如果元素中没有该类,则添加
         */
        function toggleClass(obj, cn) {
            // 判断obj中是否含有cn
            if (hasClass(obj, cn)) {
                // 存在,则删除
                removeClass(obj, cn);
            } else {
                // 没有,则添加
                addClass(obj, cn);
            }
        }
    </script>
    </body>
    </html>
    

    image-20201022124939559

    4.3.5、查找 HTML 父子

    4.3.5.1、方法介绍

    方法描述
    元素节点.parentNode返回元素的父节点。
    元素节点.parentElement返回元素的父元素。
    元素节点.childNodes返回元素的一个子节点的数组(包含空白文本Text节点)。
    元素节点.children返回元素的一个子元素的集合(不包含空白文本Text节点)。
    元素节点.firstChild返回元素的第一个子节点(包含空白文本Text节点)。
    元素节点.firstElementChild返回元素的第一个子元素(不包含空白文本Text节点)。
    元素节点.lastChild返回元素的最后一个子节点(包含空白文本Text节点)。
    元素节点.lastElementChild返回元素的最后一个子元素(不包含空白文本Text节点)。
    元素节点.previousSibling返回某个元素紧接之前节点(包含空白文本Text节点)。
    元素节点.previousElementSibling返回指定元素的前一个兄弟元素(相同节点树层中的前一个元素节点)。
    元素节点.nextSibling返回某个元素紧接之后节点(包含空白文本Text节点)。
    元素节点.nextElementSibling返回指定元素的后一个兄弟元素(相同节点树层中的下一个元素节点)。

    4.3.5.2、方法演示

    案例演示:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div id="box">
        <ul id="ul">
            <li><a href="https://www.baidu.com">我是超链接1</a></li>
            <li id="two"><a href="https://www.baidu.com">我是超链接2</a></li>
            <li><a href="https://www.baidu.com">我是超链接3</a></li>
            <li><a href="https://www.baidu.com">我是超链接4</a></li>
        </ul>
    </div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var box = document.getElementById("box");
        var ul = document.getElementById("ul");
        var two = document.getElementById("two");
    
        console.log(ul.parentNode);
        console.log(ul.parentElement);
        console.log("===============");
    
        console.log(box.childNodes);
        console.log(box.children);
        console.log("===============");
    
        console.log(ul.firstChild);
        console.log(ul.firstElementChild);
        console.log(ul.lastChild);
        console.log(ul.lastElementChild);
        console.log("===============");
    
        console.log(two.previousSibling);
        console.log(two.previousElementSibling);
        console.log(two.nextSibling);
        console.log(two.nextElementSibling);
    </script>
    </body>
    </html>
    

    image-20201020202807593

    兼容性方法:

    /*获取任意一个父级元素的第一个子元素*/
    function getfirstElementChild(element) {
    	if(element.firstElementChild) {
    		return element.firstElementChild;
    	} else {
    		var node = element.firstChild;
    		while(node && node.nodeType != 1) {
    			node = node.nextSibling;
    		}
    		return node;
    	}
    }
    
    /*获取任意一个父级元素的最后一个子元素*/
    function getLastElementChild(element) {
    	if(element.lastElementChild) {
    		return element.lastElementChild;
    	} else {
    		var node = element.lastChild;
    		while(node && node.nodeType != 1) {
    			node = node.previousSibling;
    		}
    		return node;
    	}
    }
    
    /*获取任意一个子元素的前一个兄弟元素*/
    function getPreviousElementSibling(element) {
    	if(element.previousElementSibling) {
    		return element.previousElementSibling;
    	} else {
    		var node = element.previousSibling;
    		while(node && node.nodeType != 1) {
    			node = node.previousSibling;
    		}
    		return node;
    	}
    }
    
    /*获取任意一个子元素的后一个兄弟元素*/
    function getNextElementSibling(element) {
    	if(element.nextElementSibling) {
    		return element.nextElementSibling;
    	} else {
    		var node = element.nextSibling;
    		while(node && node.nodeType != 1) {
    			node = node.nextSibling;
    		}
    		return node;
    	}
    }
    

    案例演示:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div id="container">
        <p>前面的P标签</p>
        <b>加粗文本</b>
        <a href="https://www.baidu.com" id="a">百度一下</a>
        <i>斜体文本</i>
        <p>最后的P标签</p>
    </div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        /*第一个子元素*/
        var firstNode = getfirstElementChild(document.getElementById("container"));
        console.log(firstNode.innerHTML);
        /*最后一个子元素*/
        var lastNode = getLastElementChild(document.getElementById("container"));
        console.log(lastNode.innerHTML);
        /*指定元素的前一个子元素*/
        var node1 = getPreviousElementSibling(document.getElementById("a"));
        console.log(node1.innerHTML);
        /*指定元素的后一个子元素*/
        var node2 = getNextElementSibling(document.getElementById("a"));
        console.log(node2.innerHTML);
    
        /*获取任意一个父级元素的第一个子元素*/
        function getfirstElementChild(element) {
            if (element.firstElementChild) {
                return element.firstElementChild;
            } else {
                var node = element.firstChild;
                while (node && node.nodeType != 1) {
                    node = node.nextSibling;
                }
                return node;
            }
        }
    
        /*获取任意一个父级元素的最后一个子元素*/
        function getLastElementChild(element) {
            if (element.lastElementChild) {
                return element.lastElementChild;
            } else {
                var node = element.lastChild;
                while (node && node.nodeType != 1) {
                    node = node.previousSibling;
                }
                return node;
            }
        }
    
        /*获取任意一个子元素的前一个兄弟元素*/
        function getPreviousElementSibling(element) {
            if (element.previousElementSibling) {
                return element.previousElementSibling;
            } else {
                var node = element.previousSibling;
                while (node && node.nodeType != 1) {
                    node = node.previousSibling;
                }
                return node;
            }
        }
    
        /*获取任意一个子元素的后一个兄弟元素*/
        function getNextElementSibling(element) {
            if (element.nextElementSibling) {
                return element.nextElementSibling;
            } else {
                var node = element.nextSibling;
                while (node && node.nodeType != 1) {
                    node = node.nextSibling;
                }
                return node;
            }
        }
    </script>
    </body>
    </html>
    

    谷歌浏览器:

    image-20201021144241079

    火狐浏览器:

    image-20201021144301183

    IE5-IE11浏览器:

    image-20201021144609631

    4.4、DOM文档事件

    4.4.1、事件概述

    HTML事件可以触发浏览器中的行为,比方说当用户点击某个 HTML 元素时启动一段 JavaScript。

    4.4.2、窗口事件

    由窗口触发该事件 (同样适用于 <body> 标签):

    属性描述
    onblur当窗口失去焦点时运行脚本。
    onfocus当窗口获得焦点时运行脚本。
    onload当文档加载之后运行脚本。
    onresize当调整窗口大小时运行脚本。
    onstorage当 Web Storage 区域更新时(存储空间中的数据发生变化时)运行脚本。

    案例演示1:当窗口失去焦点时,输出“窗口失去焦点”

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        window.onblur = function () {
            console.log("窗口失去焦点");
        };
    </script>
    </body>
    </html>
    

    image-20201021081411240

    案例演示2:当窗口获取焦点时,输出“窗口获取焦点”

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        window.onfocus = function () {
            console.log("窗口获取焦点");
        };
    </script>
    </body>
    </html>
    

    image-20201021081456060

    案例演示3:当页面文档加载完成后,输出"Hello, World"

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        window.onload = function () {
            console.log("Hello,World");
        };
    </script>
    </body>
    </html>
    

    image-20201019153100531

    案例演示4:当调整窗口大小时,输出"窗口大小正在改变"

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        window.onresize = function () {
            console.log("窗口大小正在改变");
        };
    </script>
    </body>
    </html>
    

    image-20201019153423408

    4.4.3、表单事件

    表单事件在HTML表单中触发 (适用于所有 HTML 元素,但该HTML元素需在form表单内):

    属性描述
    onblur当元素失去焦点时运行脚本。
    onfocus当元素获得焦点时运行脚本。
    onchange当元素改变时运行脚本。
    oninput当元素获得用户输入时运行脚本。
    oninvalid当元素无效时运行脚本。
    onselect当选取元素时运行脚本。
    onsubmit当提交表单时运行脚本。

    案例演示1:当文本框获取焦点,文本框背景为红色,当文本框失去焦点,文本框背景为黄色

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <form>
        <input type="text" id="text">
    </form>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var textInput = document.getElementById("text");
    
        /* 当文本框获取焦点,文本框背景为红色 */
        textInput.onfocus = function () {
            this.style.background = "red";
        };
    
        /* 当文本框失去焦点,文本框背景为绿色 */
        textInput.onblur = function () {
            this.style.background = "green";
        };
    </script>
    </body>
    </html>
    

    注意:这里为什么要用this,你不用this也可以,就直接textInput.style.background = "red";也不是不可以的,但是方法的调用规则就是谁调用this,this就指向谁,这样我们就可以简化代码了

    案例演示2:当文本框内容改变时,鼠标离开文本框,自动将文本框的内容输出到控制台

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <form>
        <input type="text" id="text">
    </form>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var textInput = document.getElementById("text");
    
        /* 当文本框内容改变时,鼠标离开文本框,自动将文本框的内容输出到控制台 */
        textInput.onchange = function () {
            console.log(this.value);
        };
    </script>
    </body>
    </html>
    

    image-20201019155326750

    案例演示3:当文本框内容改变时,立即将改变的内容输出到控制台

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <form>
        <input type="text" id="text">
    </form>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var textInput = document.getElementById("text");
    
        /* 当文本框内容改变时,立即将改变的内容输出到控制台 */
        textInput.oninput = function () {
            console.log(this.value);
        };
    </script>
    </body>
    </html>
    

    image-20201021111352033

    案例演示4:如果单击“submit”,则不填写文本字段,将发生警报消息

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <form>
        <input type="text" id="text" required>
        <input type="submit" value="submit">
    </form>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var textInput = document.getElementById("text");
    
        /* 如果单击“submit”,则不填写文本字段,将发生警报消息 */
        textInput.oninvalid = function () {
            console.log("请您完善表单内容!");
        };
    </script>
    </body>
    </html>
    

    image-20201021111647136

    案例演示5:当选中文本框的内容时,输出“您已经选择了文本框内容!”

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <form>
        <input type="text" id="text">
    </form>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var textInput = document.getElementById("text");
    
        /* 当选中文本框的内容时,输出“您已经选择了文本框内容!” */
        textInput.onselect = function () {
            console.log("您已经选择了文本框内容!");
        };
    </script>
    </body>
    </html>
    

    image-20201021112207508

    案例演示6:当提交表单的时候,在控制台输出“表单提交”

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <form id="myform">
        <input type="submit" id="submit">
    </form>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var myform = document.getElementById("myform");
    
        /* 当提交表单的时候,在控制台输出“表单提交” */
        myform.onsubmit = function () {
            console.log("表单提交");
            return false;/* 用来阻止表单提交的,你不写它会跳转请求 */
        };
    </script>
    </body>
    </html>
    

    image-20201021112810436

    4.4.4、键盘事件

    通过键盘触发事件,类似用户的行为:

    属性描述
    onkeydown当按下按键时运行脚本。
    onkeyup当松开按键时运行脚本。
    onkeypress当按下并松开按键时运行脚本。

    案例演示1:当键盘按下判断当前的按键是不是 a ,如果是就输出true,否则输出false

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        /* 当键盘按下判断当前的按键是不是 a ,如果是就输出true,否则输出false */
        window.onkeydown = function (event) {
            /* 解决兼容性问题 */
            event = event || window.event;
    
            if (event.keyCode == 65) {
                console.log("true");
            } else {
                console.log("false");
            }
        };
    </script>
    </body>
    </html>
    

    image-20201019160028364

    案例演示2:使div可以根据不同的方向键向不同的方向移动

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div id="box" style="width: 100px;height: 100px;background: red;position: absolute;"></div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var box = document.getElementById("box");
    
        //为document绑定一个按键按下的事件
        document.onkeydown = function (event) {
            event = event || window.event;
    
            // 定义移动速度
            var speed = 10;
    
            // 选择移动方向
            switch (event.keyCode) {
                case 37:
                    box.style.left = box.offsetLeft - speed + "px";
                    break;
                case 39:
                    box.style.left = box.offsetLeft + speed + "px";
                    break;
                case 38:
                    box.style.top = box.offsetTop - speed + "px";
                    break;
                case 40:
                    box.style.top = box.offsetTop + speed + "px";
                    break;
            }
        };
    </script>
    </body>
    </html>
    

    image-20201021121141325

    拓展知识:

    当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数。

    Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标的状态。

    在IE8中,响应函数被触发时,浏览器不会传递事件对象,在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存的。

    解决事件对象的兼容性问题:event = event || window.event;

    键鼠属性:

    属性描述
    ctrlKey返回当事件被触发时,“CTRL” 键是否被按下。
    altKey返回当事件被触发时,“ALT” 是否被按下。
    shiftKey返回当事件被触发时,“SHIFT” 键是否被按下。
    clientX返回当事件被触发时,鼠标指针的水平坐标。
    clientY返回当事件被触发时,鼠标指针的垂直坐标。
    screenX返回当某个事件被触发时,鼠标指针的水平坐标。
    screenY返回当某个事件被触发时,鼠标指针的垂直坐标。

    4.4.5、鼠标事件

    通过鼠标触发事件,类似用户的行为:

    属性描述
    onclick当单击鼠标时运行脚本。
    ondblclick当双击鼠标时运行脚本。
    onmousedown当按下鼠标按钮时运行脚本。
    onmouseup当松开鼠标按钮时运行脚本。
    onmousemove当鼠标指针移动时运行脚本。
    onmouseover当鼠标指针移至元素之上时运行脚本,不可以阻止冒泡。
    onmouseout当鼠标指针移出元素时运行脚本,不可以阻止冒泡。
    onmouseenter当鼠标指针移至元素之上时运行脚本,可以阻止冒泡。
    onmouseleave当鼠标指针移出元素时运行脚本,可以阻止冒泡。
    onmousewheel当转动鼠标滚轮时运行脚本。
    onscroll当滚动元素的滚动条时运行脚本。

    案例演示1:创建一个正方形div,默认颜色为黑色,当鼠标移入div,背景颜色变为红色,当鼠标移出div,背景颜色变为绿色

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div id="box" style="width: 100px;height: 100px;background: black;"></div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var box = document.getElementById("box");
    
        /* 当鼠标移入div,背景颜色变为红色 */
        box.onmouseenter = function () {
            this.style.background = "red";
        };
    
        /* 当鼠标移出div,背景颜色变为绿色 */
        box.onmouseleave = function () {
            this.style.background = "green";
        };
    </script>
    </body>
    </html>
    

    image-20201021121332681

    案例演示2:编写一个通用的拖拽元素函数,创建两个div,进行拖拽演示,要求兼容IE8、火狐、谷歌等主流浏览器

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <div id="box1" style="width: 100px;height: 100px;background: red;position: absolute;"></div>
    <div id="box2" style="width: 100px;height: 100px;background: green;position: absolute;"></div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var box1 = document.getElementById("box1");
        var box2 = document.getElementById("box2");
    
        drag(box1);
        drag(box2);
    
        /*
         * 提取一个专门用来设置拖拽的函数
         * 参数:开启拖拽的元素
         */
        function drag(obj) {
            //当鼠标在被拖拽元素上按下时,开始拖拽
            obj.onmousedown = function (event) {
                // 解决事件的兼容性问题
                event = event || window.event;
    
                // 设置obj捕获所有鼠标按下的事件
                /**
                 * setCapture():
                 * 只有IE支持,但是在火狐中调用时不会报错,
                 * 而如果使用chrome调用,它也会报错
                 */
                obj.setCapture && obj.setCapture();
    
                // obj的偏移量 鼠标.clentX - 元素.offsetLeft
                // obj的偏移量 鼠标.clentY - 元素.offsetTop
                var ol = event.clientX - obj.offsetLeft;
                var ot = event.clientY - obj.offsetTop;
    
                // 为document绑定一个鼠标移动事件
                document.onmousemove = function (event) {
                    // 解决事件的兼容性问题
                    event = event || window.event;
                    // 当鼠标移动时被拖拽元素跟随鼠标移动
                    // 获取鼠标的坐标
                    var left = event.clientX - ol;
                    var top = event.clientY - ot;
                    // 修改obj的位置
                    obj.style.left = left + "px";
                    obj.style.top = top + "px";
                };
    
                // 为document绑定一个鼠标松开事件
                document.onmouseup = function () {
                    // 取消document的onmousemove事件
                    document.onmousemove = null;
                    // 取消document的onmouseup事件
                    document.onmouseup = null;
                    // 当鼠标松开时,取消对事件的捕获
                    obj.releaseCapture && obj.releaseCapture();
                };
    
                /*
                 * 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
                 * 此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
                 * 如果不希望发生这个行为,则可以通过return false来取消默认行为,
                 * 但是这招对IE8不起作用
                 */
                return false;
            };
        }
    </script>
    </body>
    </html>
    

    image-20201021120652857

    4.4.6、媒体事件

    通过视频(videos),图像(images)或音频(audio) 触发该事件。

    属性描述
    onabort当发生中止事件时运行脚本。
    oncanplay当媒介能够开始播放但可能因缓冲而需要停止时运行脚本。
    oncanplaythrough当媒介能够无需因缓冲而停止即可播放至结尾时运行脚本。
    ondurationchange当媒介长度改变时运行脚本。
    onemptied当媒介资源元素突然为空时(网络错误、加载错误等)运行脚本。
    onended当媒介已抵达结尾时运行脚本。
    onerror当在元素加载期间发生错误时运行脚本。
    onloadeddata当加载媒介数据时运行脚本。
    onloadedmetadata当媒介元素的持续时间以及其它媒介数据已加载时运行脚本。
    onloadstart当浏览器开始加载媒介数据时运行脚本。
    onpause当媒介数据暂停时运行脚本。
    onplay当媒介数据将要开始播放时运行脚本。
    onplaying当媒介数据已开始播放时运行脚本。
    onprogress当浏览器正在取媒介数据时运行脚本。
    onratechange当媒介数据的播放速率改变时运行脚本。
    onreadystatechange当就绪状态(ready-state)改变时运行脚本。
    onseeked当媒介元素的定位属性不再为真且定位已结束时运行脚本。
    onseeking当媒介元素的定位属性为真且定位已开始时运行脚本。
    onstalled当取回媒介数据过程中(延迟)存在错误时运行脚本。
    onsuspend当浏览器已在取媒介数据但在取回整个媒介文件之前停止时运行脚本。
    ontimeupdate当媒介改变其播放位置时运行脚本。
    onvolumechange当媒介改变音量亦或当音量被设置为静音时运行脚本。
    onwaiting当媒介已停止播放但打算继续播放时运行脚本。

    4.4.7、其它事件

    属性描述
    onshow当 <menu> 元素在上下文显示时触发。
    ontoggle当用户打开或关闭 <details> 元素时触发。

    4.4.8、事件冒泡

    事件的冒泡(Bubble):所谓的冒泡指的就是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发,在开发中大部分情况冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡。

    案例演示1:创建两个div,叠放在一起,分别绑定单击事件,点击最里边的div,会触发两个div的单击事件

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            #div1 {
                width: 200px;
                height: 200px;
                background: pink;
            }
    
            #div2 {
                width: 100px;
                height: 100px;
                background: coral;
            }
        </style>
    </head>
    <body>
    <div id="div1">
        我是DIV1
        <div id="div2">
            我是DIV2
        </div>
    </div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var div1 = document.getElementById("div1");
        var div2 = document.getElementById("div2");
    
        // 为div1绑定单击事件
        div1.onclick = function () {
            console.log("div1 的单击事件触发了!");
        };
    
        // 为div2绑定单击事件
        div2.onclick = function () {
            console.log("div2 的单击事件触发了!");
        };
    </script>
    </body>
    </html>
    

    image-20201021135641651

    案例演示2:创建两个div,叠放在一起,分别绑定单击事件,点击最里边的div,不会触发两个div的单击事件,只会触发自己的单击事件,这时候我们可以取消事件冒泡

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            #div1 {
                width: 200px;
                height: 200px;
                background: pink;
            }
    
            #div2 {
                width: 100px;
                height: 100px;
                background: coral;
            }
        </style>
    </head>
    <body>
    <div id="div1">
        我是DIV1
        <div id="div2">
            我是DIV2
        </div>
    </div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var div1 = document.getElementById("div1");
        var div2 = document.getElementById("div2");
    
        // 为div1绑定单击事件
        div1.onclick = function () {
            console.log("div1 的单击事件触发了!");
            stopBubble();
        };
    
        // 为div2绑定单击事件
        div2.onclick = function () {
            console.log("div2 的单击事件触发了!");
            stopBubble();
        };
    
        // 取消事件冒泡
        function stopBubble(event) {
            // 如果提供了事件对象,则这是一个非IE浏览器
            if (event && event.stopPropagation) {
                // 因此它支持W3C的stopPropagation()方法
                event.stopPropagation();
            } else {
                // 否则,我们需要使用IE的方式来取消事件冒泡
                window.event.cancelBubble = true;
            }
        }
    </script>
    </body>
    </html>
    

    image-20201021140430458

    案例演示3:当点击a标签的时候,阻止a标签的默认跳转事件,采用事件阻止

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            #div1 {
                width: 200px;
                height: 200px;
                background: pink;
            }
    
            #div2 {
                width: 100px;
                height: 100px;
                background: coral;
            }
        </style>
    </head>
    <body>
    <a href="https://www.baidu.com" id="a">打开百度,你就知道!</a>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var a = document.getElementById("a");
    
        // 为a绑定单击事件
        a.onclick = function () {
            stopDefault();
        };
    
        // 阻止浏览器的默认行为
        function stopDefault(event) {
            if (event && event.preventDefault) {
                // 阻止默认浏览器动作(W3C)
                event.preventDefault();
            } else {
                // IE中阻止函数器默认动作的方式
                window.event.returnValue = false;
            }
            return false;
        }
    </script>
    </body>
    </html>
    

    image-20201021140928214

    4.4.9、事件委派

    我们希望只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的,我们可以尝试将其绑定给元素的共同的祖先元素,也就是事件的委派。事件的委派,是指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。事件委派是利用了事件冒泡,通过委派可以减少事件绑定的次数,提高程序的性能。

    案例演示:为ul列表中的所有a标签都绑定单击事件

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <ul id="u1">
        <li><a href="javascript:;" class="link">超链接一</a></li>
        <li><a href="javascript:;" class="link">超链接二</a></li>
        <li><a href="javascript:;" class="link">超链接三</a></li>
    </ul>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var u1 = document.getElementById("u1");
    
        // 为ul绑定一个单击响应函数
        u1.onclick = function (event) {
            event = event || window.event;
            // 如果触发事件的对象是我们期望的元素,则执行,否则不执行
            if (event.target.className == "link") {
                console.log("我是ul的单击响应函数");
            }
        };
    </script>
    </body>
    </html>
    

    image-20201021134924509

    4.4.10、事件绑定

    我们以前绑定事件代码只能一个事件绑定一个函数,那我们要是想一个事件对应多个函数,并且不存在兼容性的问题该如何解决呢?

    接下来,我会直接提供两个已经编写好的事件绑定和事件解绑的兼容性代码,如下:

    /*为元素绑定事件兼容性代码*/
    function addEventListener(element, type, fn) {
    	if(element.addEventListener) {
    		element.addEventListener(type, fn, false);
    	} else if(element.attachEvent) {
    		element.attachEvent("on" + type, fn);
    	} else {
    		element["on" + type] = fn;
    	}
    }
    
    /*为元素解绑事件兼容性代码*/
    function removeEventListener(element, type, fnName) {
    	if(element.removeEventListener) {
    		element.removeEventListener(type, fnName, false);
    	} else if(element.detachEvent) {
    		element.detachEvent("on" + type, fnName);
    	} else {
    		element["on" + type] = null;
    	}
    }
    

    案例演示:为按钮1的单击事件绑定两个函数,然后点击按钮2取消按钮1的单机事件绑定函数f1

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <button id="btn1">按钮1</button>
    <button id="btn2">按钮2</button>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        function f1() {
            console.log("output1 ...");
        };
    
        function f2() {
            console.log("output2 ...");
        };
    
        // 为按钮1的单击事件绑定两个函数
        addEventListener(document.getElementById("btn1"), "click", f1);
        addEventListener(document.getElementById("btn1"), "click", f2);
    
        // 点击按钮2取消按钮1的单机事件绑定函数f1
        document.getElementById("btn2").onclick = function () {
            removeEventListener(document.getElementById("btn1"), "click", f1);
        };
    
        /*为元素绑定事件兼容性代码*/
        function addEventListener(element, type, fn) {
            if (element.addEventListener) {
                element.addEventListener(type, fn, false);
            } else if (element.attachEvent) {
                element.attachEvent("on" + type, fn);
            } else {
                element["on" + type] = fn;
            }
        }
    
        /*为元素解绑事件兼容性代码*/
        function removeEventListener(element, type, fnName) {
            if (element.removeEventListener) {
                element.removeEventListener(type, fnName, false);
            } else if (element.detachEvent) {
                element.detachEvent("on" + type, fnName);
            } else {
                element["on" + type] = null;
            }
        }
    </script>
    </body>
    </html>
    

    谷歌浏览器:

    image-20201021143905794

    火狐浏览器:

    image-20201021143929547

    IE8-IE11浏览器:

    image-20201021144005993

    4.4.11、事件传播

    事件的传播:关于事件的传播网景公司和微软公司有不同的理解

    微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。

    网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后在向内传播给后代元素。

    W3C综合了两个公司的方案,将事件传播分成了三个阶段:

    1. 捕获阶段:在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
    2. 目标阶段:事件捕获到目标元素,捕获结束开始在目标元素上触发事件
    3. 冒泡阶段:事件从目标元素向它的祖先元素传递,依次触发祖先元素上的事件

    image-20201021145200137

    注意:如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true,一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false,并且注意,IE8及以下的浏览器中没有捕获阶段,我们可以使用event.stopPropagation();取消事件传播。

    第五章 JavaScript BOM

    5.1、BOM概述

    浏览器对象模型(BOM)使 JavaScript 有能力与浏览器"对话"。

    浏览器对象模型(Browser Object Model (BOM))尚无正式标准。

    由于现代浏览器已经(几乎)实现了 JavaScript 交互性方面的相同方法和属性,因此常被认为是BOM的方法和属性。

    浏览器对象模型(BOM)可以使我们通过JS来操作浏览器,在BOM中为我们提供了一组对象,用来完成对浏览器的操作,常见的BOM对象如下:

    • Window:代表的是整个浏览器的窗口,同时window也是网页中的全局对象
    • Navigator:代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
    • Location:代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
    • History:代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录,由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时有效
    • Screen:代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息

    这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用。

    5.2、Window对象

    5.2.1、弹出框

    JavaScript 有三种类型的弹出框:警告框、确认框和提示框。

    5.2.1.1、警告框

    如果要确保信息传递给用户,通常会使用警告框。当警告框弹出时,用户将需要单击“确定”来继续。

    语法

    window.alert("sometext");
    

    注意:window.alert() 方法可以不带 window 前缀来写。

    实例

    alert("我是一个警告框!");
    

    5.2.1.2、确认框

    如果您希望用户验证或接受某个东西,则通常使用“确认”框。

    当确认框弹出时,用户将不得不单击“确定”或“取消”来继续进行。

    如果用户单击“确定”,该框返回 true。如果用户单击“取消”,该框返回 false。

    语法

    window.confirm("sometext");
    

    注意:window.confirm() 方法可以不带 window 前缀来编写。

    实例

    var r = confirm("请按按钮");
    if (r == true) {
        x = "您按了确认!";
    } else {
        x = "您按了取消!";
    }
    

    5.2.1.3、提示框

    如果您希望用户在进入页面前输入值,通常会使用提示框。

    当提示框弹出时,用户将不得不输入值后单击“确定”或点击“取消”来继续进行。

    如果用户单击“确定”,该框返回输入值。如果用户单击“取消”,该框返回 NULL。

    语法

    window.prompt("sometext","defaultText");
    

    window.prompt() 方法可以不带 window 前缀来编写。

    实例

    var person = prompt("请输入您的姓名", "比尔盖茨");
    if (person != null) {
        console.log(person);
    }
    

    5.2.2、定时事件

    JavaScript 可以在时间间隔内执行,这就是所谓的定时事件( Timing Events)。

    window 对象允许以指定的时间间隔执行代码,这些时间间隔称为定时事件。

    通过 JavaScript 使用的有两个关键的方法:

    • setTimeout(function, milliseconds)

      在等待指定的毫秒数后执行函数。

    • setInterval(function, milliseconds)

      等同于 setTimeout(),但持续重复执行该函数。

    setTimeout() 和 setInterval() 都属于 window 对象的方法。

    5.2.2.1、延时器

    setTimeout() 方法:延时器

    window.setTimeout(function, milliseconds);
    

    注意:window.setTimeout() 方法可以不带 window 前缀来编写。

    • 第一个参数是要执行的函数。
    • 第二个参数指示执行之前的毫秒数。

    案例演示:单击按钮,等待 3 秒,然后控制台会输出 "Hello"

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <button id="btn">按钮</button>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var btn = document.getElementById("btn");
    
        btn.onclick = function () {
            // 创建延时器
            var timer = setTimeout(function () {
                console.log("Hello");
            }, 3000);
            
            // 清除延时器
            // clearTimeout(timer);        
        };
    </script>
    </body>
    </html>
    

    5.2.2.2、定时器

    setInterval() 方法:定时器

    setInterval() 方法在每个给定的时间间隔重复给定的函数。

    window.setInterval(function, milliseconds);
    

    注意:window.setInterval() 方法可以不带 window 前缀来写。

    • 第一个参数是要执行的函数。
    • 第二个参数每个执行之间的时间间隔的长度。

    案例演示:单击按钮,每隔一秒向控制台输出 "Hello"

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <button id="btn">按钮</button>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var btn = document.getElementById("btn");
    
        btn.onclick = function () {
            // 创建定时器
            var timer = setInterval(function () {
                console.log("Hello");
            }, 1000);
    
            // 清除定时器
            // clearInterval(timer);
        };
    </script>
    </body>
    </html>
    

    拓展知识:

    做一个通用移动函数来实现小汽车(黑色方块)移动的效果

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            /*控制器样式*/
            .controller {
                width: 600px;
                height: 50px;
                line-height: 50px;
            }
    
            .controller button {
                outline: none;
                border: none;
                margin: 0px;
                padding: 0px;
                width: 200px;
                height: 50px;
                font-size: 16px;
                line-height: 50px;
                text-align: center;
                background-color: #E9E9E9;
                cursor: pointer;
                float: left;
                -webkit-box-sizing: border-box;
                -moz-box-sizing: border-box;
                box-sizing: border-box;
                border: 2px solid #F0F0F0;
            }
    
            .controller button:hover {
                background-color: #F9F9F9;
            }
    
    
            /*公路样式*/
            .road {
                width: 100%;
                height: 100px;
                position: relative;
                margin-top: 50px;
                background: #3DB1FF;
                opacity: .90;
            }
    
            .road800 {
                width: 800px;
                height: 100px;
                background: pink;
                position: absolute;
                top: 0px;
                left: 0px;
                z-index: 1000;
                opacity: .75;
            }
    
            .road1200 {
                width: 1200px;
                height: 100px;
                background: orange;
                position: absolute;
                top: 0px;
                left: 0px;
                z-index: 500;
            }
    
    
            /*小汽车样式*/
            div#car {
                width: 135px;
                height: 100px;
                display: block;
                background: black;
                position: absolute;
                top: 0px;
                left: 0px;
                z-index: 1500;
                -webkit-box-sizing: border-box;
                -moz-box-sizing: border-box;
                box-sizing: border-box;
                /*border: 1px solid #F0F0F0;*/
            }
        </style>
    </head>
    <body>
    <div class="controller">
        <button id="btn1">移动到800PX</button>
        <button id="btn2">移动到1200PX</button>
        <button id="btn3">回家</button>
    </div>
    
    <div class="road">
        <div class="road800"></div>
        <div class="road1200"></div>
        <div id="car"></div>
    </div>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        document.getElementById("btn1").onclick = function () {
            move(document.getElementById("car"), 800);
        };
    
        document.getElementById("btn2").onclick = function () {
            move(document.getElementById("car"), 1200);
        };
    
        document.getElementById("btn3").onclick = function () {
            move(document.getElementById("car"), 0);
        };
    
        /*移动函数*/
        function move(element, target) {
            // 先清理定时器
            clearInterval(element.timeId);
            // 一会要清理定时器(只产生一个定时器)
            element.timeId = setInterval(function () {
                // 获取对象当前的位置
                var current = element.offsetLeft;
                // 每次移动多少像素
                var step = 10;
                // 判断是往正方向走还是往相反方向走
                step = current < target ? step : -step;
                // 每次移动后的距离
                current += step;
                // 判断当前移动后的位置是否到达目标位置
                if (Math.abs(target - current) > Math.abs(step)) {
                    element.style.left = current + "px";
                } else {
                    // 清理定时器
                    clearInterval(element.timeId);
                    element.style.left = target + "px";
                }
            }, 20);
        }
    </script>
    </body>
    </html>
    

    image-20201022093955689

    5.2.3、常用窗口属性

    两个属性可用用于确定浏览器窗口的尺寸。

    这两个属性都以像素返回尺寸:

    • window.innerHeight - 浏览器窗口的内高度(以像素计)
    • window.innerWidth - 浏览器窗口的内宽度(以像素计)

    浏览器窗口(浏览器视口)不包括工具栏和滚动条。

    对于 Internet Explorer 8, 7, 6, 5:

    • document.documentElement.clientHeight
    • document.documentElement.clientWidth

    • document.body.clientHeight
    • document.body.clientWidth

    一个实用的 JavaScript 解决方案(包括所有浏览器):该例显示浏览器窗口的高度和宽度(不包括工具栏和滚动条)

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
    <script>
        var w = window.innerWidth
            || document.documentElement.clientWidth
            || document.body.clientWidth;
    
        var h = window.innerHeight
            || document.documentElement.clientHeight
            || document.body.clientHeight;
    
        console.log(w);
        console.log(h);
    </script>
    </body>
    </html>
    

    5.2.4、其它窗口方法

    • window.open() :打开新的窗口

      语法介绍:

      window.open(URL,name,specs,replace);
      

      参数介绍:

      image-20201022094734710

      案例演示:

      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="UTF-8">
          <title></title>
      </head>
      <body>
      <button onclick="openWin()">打开窗口</button>
      
      <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
      <script>
          function openWin() {
              myWindow = window.open('', '', 'width=200,height=100');
              myWindow.document.write("<p>这是新建窗口</p>");
          }
      </script>
      </body>
      </html>
      
    • window.close() :关闭当前窗口

      语法介绍:

      window.close();
      

      案例演示:

      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="UTF-8">
          <title></title>
      </head>
      <body>
      <button onclick="openWin()">打开窗口</button>
      <button onclick="closeWin()">关闭窗口</button>
      
      <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
      <script>
          function openWin() {
              myWindow = window.open('', '', 'width=200,height=100');
              myWindow.document.write("<p>这是新建窗口</p>");
          }
      
          function closeWin() {
              myWindow.close();
          }
      </script>
      </body>
      </html>
      
    • window.moveTo() :移动当前窗口

      语法介绍:

      window.moveTo(x,y);
      

      案例演示:

      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="UTF-8">
          <title></title>
      </head>
      <body>
      <button onclick="openWin()">打开窗口</button>
      <button onclick="moveWin()">移动窗口</button>
      
      <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
      <script>
          function openWin() {
              myWindow = window.open('', '', 'width=200,height=100');
              myWindow.document.write("<p>这是新建窗口</p>");
          }
      
          function moveWin() {
              myWindow.moveTo(300, 300);
              myWindow.focus();
          }
      </script>
      </body>
      </html>
      
    • window.resizeTo() :调整当前窗口

      语法介绍:

      window.resizeTo(width,height);
      

      案例演示:

      <!DOCTYPE html>
      <html>
      <head>
          <meta charset="UTF-8">
          <title></title>
      </head>
      <body>
      <button onclick="openWin()">打开窗口</button>
      <button onclick="resizeWin()">调整窗口</button>
      
      <!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
      <script>
          function openWin() {
              myWindow = window.open('', '', 'width=200,height=100');
              myWindow.document.write("<p>这是新建窗口</p>");
          }
      
          function resizeWin() {
              myWindow.resizeTo(300, 300);
              myWindow.focus();
          }
      </script>
      </body>
      </html>
      

    5.3、Navigator对象

    Navigator代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器,由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了,一般我们只会使用userAgent来判断浏览器的信息,userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,不同的浏览器会有不同的userAgent,如下代码:

    var ua = navigator.userAgent;
    console.log(ua);
    

    谷歌浏览器:

    • Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36

    火狐浏览器:

    • Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0

    IE11浏览器:

    • Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; rv:11.0) like Gecko

    IE10浏览器:

    • Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)

    IE9浏览器:

    • Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)

    IE8浏览器:

    • Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)

    IE7浏览器:

    • Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729)

    于是乎,我们就可以实现对浏览器类型的判断:

    var ua = navigator.userAgent;
    if (/firefox/i.test(ua)) {
        alert("你是火狐浏览器");
    } else if (/chrome/i.test(ua)) {
        alert("你是谷歌浏览器");
    } else if (/msie/i.test(ua)) {
        alert("你是IE5-IE10浏览器");
    } else if ("ActiveXObject" in window) {
        alert("你是IE11浏览器");
    }
    

    注意:在IE11中已经将微软和IE相关的标识都已经去除了,所以我们基本已经不能通过UserAgent来识别一个浏览器是否是IE了,如果通过UserAgent不能判断,还可以通过一些浏览器中特有的对象,来判断浏览器的信息,比如:ActiveXObject

    5.4、Location对象

    Location对象中封装了浏览器的地址栏的信息,如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)

    5.4.1、常用属性

    常用属性:

    console.log(location);          //输出location对象
    console.log(location.href);     //输出当前地址的全路径地址
    console.log(location.origin);   //输出当前地址的来源
    console.log(location.protocol); //输出当前地址的协议
    console.log(location.hostname); //输出当前地址的主机名
    console.log(location.host);     //输出当前地址的主机
    console.log(location.port);     //输出当前地址的端口号
    console.log(location.pathname); //输出当前地址的路径部分
    console.log(location.search);   //输出当前地址的?后边的参数部分
    

    image-20201022115026894

    修改地址:

    location = "https://www.baidu.com";
    
    location.href = "https://www.baidu.com";
    

    5.4.2、常用方法

    assign():用来跳转到其它的页面,作用和直接修改location一样

    location.assign("https://www.baidu.com");
    

    reload():用于重新加载当前页面,作用和刷新按钮一样,如果在方法中传递一个true,作为参数,则会强制清空缓存刷新页面

    location.reload(true);
    

    replace():可以使用一个新的页面替换当前页面,调用完毕也会跳转页面,它不会生成历史记录,不能使用回退按钮回退

    location.replace("https://www.baidu.com");
    

    5.5、History对象

    History对象可以用来操作浏览器向前或向后翻页

    5.5.1、常用属性

    console.log(history);           //输出history对象
    console.log(history.length);    //可以获取到当成访问的链接数量
    

    image-20201022114945012

    5.5.2、常用方法

    back():可以回退到上一个页面,作用和浏览器的回退按钮一样

    history.back();
    

    forward():可以跳转到下一个页面,作用和浏览器的前进按钮一样

    history.forward();
    

    go():可以用来跳转到指定的页面,它需要一个整数作为参数

    • 1:表示向前跳转一个页面,相当于forward()
    • 2:表示向前跳转两个页面
    • -1:表示向后跳转一个页面,相当于back()
    • -2:表示向后跳转两个页面
    history.go(-2);
    

    5.6、Screen对象

    Screen 对象包含有关客户端显示屏幕的信息。

    注意:没有应用于 screen 对象的公开标准,不过所有浏览器都支持该对象。

    5.6.1、Screen对象描述

    每个 Window 对象的 screen 属性都引用一个 Screen 对象。Screen 对象中存放着有关显示浏览器屏幕的信息。JavaScript 程序将利用这些信息来优化它们的输出,以达到用户的显示要求。例如,一个程序可以根据显示器的尺寸选择使用大图像还是使用小图像,它还可以根据显示器的颜色深度选择使用 16 位色还是使用 8 位色的图形。另外,JavaScript 程序还能根据有关屏幕尺寸的信息将新的浏览器窗口定位在屏幕中间。

    5.6.2、Screen对象属性

    属性描述
    availHeight返回显示屏幕的高度 (除 Windows 任务栏之外)。
    availWidth返回显示屏幕的宽度 (除 Windows 任务栏之外)。
    bufferDepth设置或返回调色板的比特深度。
    colorDepth返回目标设备或缓冲器上的调色板的比特深度。
    deviceXDPI返回显示屏幕的每英寸水平点数。
    deviceYDPI返回显示屏幕的每英寸垂直点数。
    fontSmoothingEnabled返回用户是否在显示控制面板中启用了字体平滑。
    height返回显示屏幕的高度。
    logicalXDPI返回显示屏幕每英寸的水平方向的常规点数。
    logicalYDPI返回显示屏幕每英寸的垂直方向的常规点数。
    pixelDepth返回显示屏幕的颜色分辨率(比特每像素)。
    updateInterval设置或返回屏幕的刷新率。
    width返回显示器屏幕的宽度。

    第六章 JavaScript高级语法

    6.1、Exception

    6.1.1、异常概述

    在ES3之前JavaScript代码执行的过程中,一旦出现错误,整个JavaScript代码都会停止执行,这样就显的代码非常的不健壮。

    在Java或C#等一些高级语言中,都提供了异常处理机制,可以处理出现的异常,而不会停止整个应用程序。

    从ES3开始,JavaScript也提供了类似的异常处理机制,从而让JavaScript代码变的更健壮,即使执行的过程中出现了异常,也可以让程序具有了一部分的异常恢复能力。

    当错误发生时,JavaScript 提供了错误信息的内置 error 对象。

    error 对象提供两个有用的属性:namemessage

    Error 对象属性

    属性描述
    name设置或返回错误名
    message设置或返回错误消息(一条字符串)

    Error Name Values

    error 的 name 属性可返回六个不同的值:

    错误名描述
    EvalError已在 eval() 函数中发生的错误
    RangeError已发生超出数字范围的错误
    ReferenceError已发生非法引用
    SyntaxError已发生语法错误
    TypeError已发生类型错误
    URIError在 encodeURI() 中已发生的错误

    6.1.2、异常捕捉

    ES3开始引入了 try-catch 语句,是 JavaScript 中处理异常的标准方式。

    语法格式:

    try {
        // 可能发生异常的代码
    } catch (error) {
        // 发生错误执行的代码
    } finally {
        // 无论是否出错都会执行的代码
    }
    

    在 try…catch 中,try 中一旦出现错误则其它语句不能执行,如果不出现错误则 catch 中的语句不会执行。

    Javascript 参考其它编程语言,也提供了一种 finally 语句:不管 try 中的语句有没有错误,在最后都会执行 finally 中的语句。也就是说,try 中语句不发生错误执行完毕后会执行 finally 中的语句,try 中的语句发生错误,则执行 catch中的语句,catch 中的语句执行完毕后也会执行 finally 中的语句。

    案例演示:

    try {
        console.log(a);
        console.log("a未定义肯定报错,你看不见我");
    } catch (error) {
        // 发生错误执行的代码
        console.log(error);
    } finally {
        // 无论是否出错都会执行的代码
        console.log("finally 执行了 ...")
    }
    

    image-20201023080345639

    在JavaScript中,如果添加了 finally 语句,则 catch 语句可以省略。但是如果没有 catch 语句,则一旦发生错误就无法捕获这个错误,所以在执行完 finally 中的语句后,程序就会立即停止了。所以,在实际使用中,最好一直带着 catch 语句。如果你写了 catch 语句,则finally 语句也是可以省略的。

    6.1.3、异常演示

    6.1.3.1、Eval 错误

    EvalError 指示 eval() 函数中的错误。更新版本的 JavaScript 不会抛出任何 EvalError,请使用 SyntaxError 代替。

    案例演示:

    try {
        eval("alert('Hello)");   // 缺少 ' 会产生错误
    } catch (error) {
        console.log(error)
    }
    

    image-20201023081303304

    6.1.3.2、范围错误

    RangeError 会在您使用了合法值的范围之外的数字时抛出。

    案例演示:您不能将数字的有效位数设置为 500。

    var num = 1;
    try {
        num.toPrecision(500);   // 数无法拥有 500 个有效数
    } catch (error) {
        console.log(error)
    }
    

    image-20201023081001501

    6.1.3.3、引用错误

    假如您使用(引用)了尚未声明的变量,则 ReferenceError 会被抛出:

    案例演示:

    var x;
    try {
        x = y + 1;   // y 无法被引用(使用)
    } catch (error) {
        console.log(error)
    }
    

    image-20201023081145369

    6.1.3.4、语法错误

    假如您计算带语法错误的代码,会 SyntaxError 被抛出:

    案例演示:

    try {
        eval("alert('Hello)");   // 缺少 ' 会产生错误
    } catch (error) {
        console.log(error)
    }
    

    image-20201023081303304

    6.1.3.5、类型错误

    假如您使用的值不在期望值的范围之内,则 TypeError 被抛出:

    案例演示:

    var num = 1;
    try {
        num.toUpperCase();   // 您无法将数字转换为大写
    } catch (error) {
        console.log(error)
    }
    

    image-20201023081357388

    6.1.3.6、URI 错误

    假如您在 URI 函数中使用非法字符,则 URIError 被抛出:

    案例演示:

    try {
        decodeURI("%%%");   // 您无法对这些百分号进行 URI 编码
    } catch (error) {
        console.log(error)
    }
    

    image-20201023081458426

    6.1.4、异常抛出

    在大部分的代码执行过程中,都是出现错误的时候,由浏览器(javascript引擎)抛出异常,然后程序或者停止执行或被try…catch 捕获。

    然而有时候我们在检测到一些不合理的情况发生的时候也可以主动抛出错误,请使用 throw 关键字抛出来主动抛出异常。

    注意事项:

    1. thow后面就是我们要抛出的异常对象,在以前的时候都是出现错误的时候浏览器抛出异常对象,只是现在是我们自己主动抛出的异常对象。
    2. 只要有异常对象抛出,不管是浏览器抛出的,还是代码主动抛出,都会让程序停止执行。如果想让程序继续执行,则有也可以用try…catch来捕获。
    3. 每一个错误类型都可以传入一个参数,表示实际的错误信息。
    4. 我们可以在适当的时候抛出任何我们想抛出的异常类型。throw new SyntaxError("语法错误...");

    6.1.4.1、主动抛出内置异常

    /*该函数接收一个数字,返回它的平方。*/
    function foo(num) {
        if (typeof num == "number") {
            return num * num;
        } else {
            throw new TypeError("您输入的是一个非法数字!")
        }
    }
    
    console.log(foo(4));
    console.log(foo("abc"));
    

    image-20201023082421480

    6.1.4.2、主动抛出自定义异常

    我们不仅仅可以抛出js内置的错误类型的对象,也可以自定义错误类型,然后抛出自定义错误类型的对象。

    如果要自定义错误类型,只需要继承任何一个自定义错误类型都可以,一般直接继承Error即可。

    /*自定义错误*/
    function MyError(message) {
        this.message = "注意:这是自定义的错误"
        this.name = "自定义错误";
    }
    MyError.prototype = new Error();
    
    try {
        throw new MyError("注意:这是自定义错误类型")
    } catch (error) {
        console.log(error.message)
    }
    

    image-20201023082719743

    6.2、JSON

    6.2.1、JSON概述

    JSON:JavaScript Object Notation(JavaScript 对象标记法),它是一种存储和交换数据的语法。

    当数据在浏览器与服务器之间进行交换时,这些数据只能是文本,JSON 属于文本并且我们能够把任何 JavaScript 对象转换为 JSON,然后将 JSON 发送到服务器。我们也能把从服务器接收到的任何 JSON 转换为 JavaScript 对象。以这样的方式,我们能够把数据作为 JavaScript 对象来处理,无需复杂的解析和转译。

    6.2.2、JSON语法

    在json中,每一个数据项,都是由一个键值对(或者说是名值对)组成的,但是键必须是字符串,且由双引号包围,而值必须是以下数据类型之一:

    • 字符串(在 JSON 中,字符串值必须由双引号编写)
    • 数字
    • 对象(JSON 对象)
    • 数组
    • 布尔
    • null

    JSON 的值不可以是以下数据类型之一:

    • 函数
    • 日期
    • undefined

    因为 JSON 语法由 JavaScript 对象标记法衍生而来,所以很少需要其它额外的软件来处理 JavaScript 中的 JSON。

    通过 JavaScript,您能够创建对象并向其分配数据,就像这样:

    var person = {"name": "zhangsan", "age": 62, "city": "BeiJing"};
    console.log(person);
    

    image-20201023091704109

    6.2.3、JSON数据类型

    6.2.3.1、JSON 字符串

    JSON 中的字符串必须用双引号包围。

    {"name": "John"}
    

    6.2.3.2、JSON 数字

    JSON 中的数字必须是整数或浮点数。

    {"age": 30}
    

    6.2.3.3、JSON 对象

    JSON 中的值可以是对象,JSON 中作为值的对象必须遵守与 JSON 对象相同的规则。

    {
        "employee": {"name": "Bill Gates", "age": 62, "city": "Seattle"}
    }
    

    6.2.3.4、JSON 数组

    JSON 中的值可以是数组。

    {
        "employees": ["Bill", "Steve", "David"]
    }
    

    6.2.3.5、JSON 布尔

    JSON 中的值可以是 true/false。

    {"sale": true}
    

    6.2.3.6、JSON null

    JSON 中的值可以是 null。

    {"middlename": null}
    

    6.2.4、JSON字符串转JS对象

    JSON.parse():可以将以JSON字符串转换为JS对象,它需要一个JSON字符串作为参数,会将该字符串转换为JS对象并返回

    案例演示:

    var jsonStr = '{"name":"孙悟空","age":18,"gender":"男"}';
    var obj = JSON.parse(jsonStr);
    console.log(obj);
    

    image-20201023093124404

    注意 :JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错

    6.2.5、JS对象转JSON字符串

    JSON.stringify():可以将一个JS对象转换为JSON字符串,需要一个js对象作为参数,会返回一个JSON字符串

    案例演示:

    var obj = {name: "猪八戒", age: 28, gender: "男"};
    var jsonStr = JSON.stringify(obj);
    console.log(jsonStr);
    

    image-20201023093346336

    注意 :JSON这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错

    6.3、AJAX

    6.3.1、AJAX概述

    传统的web交互是用户触发一个http请求服务器,然后服务器收到之后,在做出响应到用户,并且返回一个新的页面,每当服务器处理客户端提交的请求时,客户都只能空闲等待,并且哪怕只是一次很小的交互、只需从服务器端得到很简单的一个数据,都要返回一个完整的HTML页,而用户每次都要浪费时间和带宽去重新读取整个页面。这个做法浪费了许多带宽,由于每次应用的交互都需要向服务器发送请求,应用的响应时间就依赖于服务器的响应时间,这导致了用户界面的响应比本地应用慢得多。

    AJAX 的出现,刚好解决了传统方法的缺陷,AJAX 是一种用于创建快速动态网页的技术,通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新,这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

    6.3.2、AJAX的XMLHttpRequest对象

    AJAX 的核心是 XMLHttpRequest 对象。 所有现代浏览器都支持 XMLHttpRequest 对象。

    XMLHttpRequest 对象用于幕后同服务器交换数据,这意味着可以更新网页的部分,而不需要重新加载整个页面。

    所有现代浏览器(Chrom、IE7+、Firefox、Safari 以及 Opera)都有内建的 XMLHttpRequest 对象。

    创建 XMLHttpRequest 的语法是:

    variable = new XMLHttpRequest();
    

    老版本的 Internet Explorer(IE5 和 IE6)使用 ActiveX 对象:

    variable = new ActiveXObject("Microsoft.XMLHTTP");
    

    为了应对所有浏览器,包括 IE5 和 IE6,请检查浏览器是否支持 XMLHttpRequest 对象。如果支持,创建 XMLHttpRequest 对象,如果不支持,则创建 ActiveX 对象:

    var xhttp;
    if (window.XMLHttpRequest) {
        xhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    

    但是需要注意的是,出于安全原因,现代浏览器不允许跨域访问,这意味着尝试加载的网页和 XML 文件都必须位于相同服务器上。

    6.3.3、AJAX的XMLHttpRequest对象方法

    方法描述
    new XMLHttpRequest()创建新的 XMLHttpRequest 对象
    abort()取消当前请求
    getAllResponseHeaders()返回头部信息
    getResponseHeader()返回特定的头部信息
    open(method, url, async, user, psw)规定请求method:请求类型 GET 或 POST
    url:文件位置
    async:true(异步)或 false(同步)
    user:可选的用户名称
    psw:可选的密码
    send()将请求发送到服务器,用于 GET 请求
    send(string)将请求发送到服务器,用于 POST 请求
    setRequestHeader()向要发送的报头添加标签/值对

    6.3.4、AJAX的XMLHttpRequest对象属性

    属性描述
    onreadystatechange定义当 readyState 属性发生变化时被调用的函数
    readyState保存 XMLHttpRequest 的状态。
    0:请求未初始化
    1:服务器连接已建立
    2:请求已收到
    3:正在处理请求
    4:请求已完成且响应已就绪
    responseText以字符串返回响应数据
    responseXML以 XML 数据返回响应数据
    status返回请求的状态号
    200: "OK"
    403: "Forbidden"
    404: "Not Found"
    如需完整列表请访问 Http 消息参考手册
    statusText返回状态文本(比如 “OK” 或 “Not Found”)

    6.3.5、AJAX的GET请求

    工程结构:

    image-20201023095114457

    users.json

    [
      {"name":"孙悟空","age":18,"gender":"男"},
      {"name":"猪八戒","age":19,"gender":"男"},
      {"name":"唐僧","age":20,"gender":"男"},
      {"name":"沙和尚","age":21,"gender":"男"}
    ]
    

    index.html

    //步骤一:创建异步对象
    var ajax = new XMLHttpRequest();
    //步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url
    ajax.open("get", "users.json");
    //步骤三:发送请求
    ajax.send();
    //步骤四:注册事件 onreadystatechange 状态改变就会调用
    ajax.onreadystatechange = function () {
        if (ajax.readyState == 4 && ajax.status == 200) {
            //步骤五:如果能够进到这个判断,说明数据完美的回来了,并且请求的页面是存在的
            console.log(ajax.responseText);//输入响应的内容
        }
    };
    

    控制台:

    image-20201023095301891

    6.3.6、AJAX的POST请求

    工程结构:

    image-20201023095114457

    users.json

    [
      {"name":"孙悟空","age":18,"gender":"男"},
      {"name":"猪八戒","age":19,"gender":"男"},
      {"name":"唐僧","age":20,"gender":"男"},
      {"name":"沙和尚","age":21,"gender":"男"}
    ]
    

    index.html

    //步骤一:创建异步对象
    var ajax = new XMLHttpRequest();
    //步骤二:设置请求的类型及url,注意:post请求一定要添加请求头才行不然会报错
    ajax.open("post", "users.json");
    ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    //步骤三:发送请求
    ajax.send();
    //步骤四:注册事件 onreadystatechange 状态改变就会调用
    ajax.onreadystatechange = function () {
        //步骤五:如果能够进到这个判断,说明数据完美的回来了,并且请求的页面是存在的
        if (ajax.readyState == 4 && ajax.status == 200) {
            console.log(ajax.responseText);//输入响应的内容
        }
    };
    

    控制台:

    image-20201023095301891

    6.3.7、AJAX的请求整合

    工程结构:

    image-20201023095114457

    users.json

    [
      {"name":"孙悟空","age":18,"gender":"男"},
      {"name":"猪八戒","age":19,"gender":"男"},
      {"name":"唐僧","age":20,"gender":"男"},
      {"name":"沙和尚","age":21,"gender":"男"}
    ]
    

    index.html

    var Ajax = {
        get: function (url, fn) {
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) {
                    fn.call(this, xhr.responseText);
                }
            };
            xhr.send();
        },
        post: function (url, data, fn) {
            var xhr = new XMLHttpRequest();
            xhr.open("POST", url, true);
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
                    fn.call(this, xhr.responseText);
                }
            };
            xhr.send(data);
        }
    };
    
    // 演示GET请求
    Ajax.get("users.json", function (response) {
        console.log(response);
    });
    
    // 演示POST请求
    Ajax.post("users.json", "", function (response) {
        console.log(response);
    });
    

    控制台:

    image-20201023100152816

    6.4、Cookie

    6.4.1、Cookie概述

    Cookie 是一些数据,存储于你电脑上的文本文件中,当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息,Cookie 的作用就是用于解决 “如何记录客户端的用户信息”:

    • 当用户访问 web 页面时,它的名字可以记录在 cookie 中。
    • 在用户下一次访问该页面时,可以在 cookie 中读取用户访问记录。

    Cookie 以名/值对形式存储,如下所示:

    username=zhangsan
    

    当浏览器从服务器上请求 web 页面时, 属于该页面的 cookie 会被添加到该请求中,服务端通过这种方式来获取用户的信息。

    JavaScript 可以使用 document.cookie 属性来创建 、读取、及删除 Cookie。

    6.4.2、Cookie创建

    JavaScript 中,创建 cookie 如下所示:

    document.cookie = "username=zhangsan";
    

    您还可以为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除。

    document.cookie = "username=zhangsan; expires=Thu, 18 Dec 2043 12:00:00 GMT";
    

    您可以使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。

    document.cookie = "username=zhangsan; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";
    

    6.4.3、Cookie读取

    JavaScript 中,读取 cookie 如下所示:

    document.cookie 将以字符串的方式返回所有的 cookie,类型格式: cookie1=value; cookie2=value; cookie3=value;

    document.cookie = "username=zhangsan";
    var cookies = document.cookie;
    console.log(cookies);
    

    image-20201023124113003

    6.4.4、Cookie修改

    JavaScript 中,修改 cookie 如下所示:

    使用 document.cookie 将旧的 cookie 将被覆盖就是修改。

    document.cookie = "username=zhangsan";
    document.cookie = "username=lisi";
    var cookies = document.cookie;
    console.log(cookies);
    

    image-20201023124645689

    6.4.5、Cookie删除

    JavaScript 中,删除 cookie 如下所示:

    删除 cookie 非常简单,您只需要设置 expires 参数为以前的时间即可,如下所示,设置为 Thu, 01 Jan 1970 00:00:00 GMT:

    document.cookie = "username=zhangsan";
    document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
    var cookies = document.cookie;
    console.log(cookies);
    

    image-20201023124936436

    6.4.6、Cookie值设置函数

    /**
     * Cookie值设置函数
     * @param cname     cookie名称
     * @param cvalue    cookie值
     * @param exdays    过期天数
     */
    function setCookie(cname, cvalue, exdays) {
        var d = new Date();
        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
        var expires = "expires=" + d.toGMTString();
        document.cookie = cname + "=" + cvalue + "; " + expires;
    }
    

    6.4.7、Cookie值获取函数

    /**
     * Cookie值获取函数
     * @param cname     cookie名称
     * @returns {string}
     */
    function getCookie(cname) {
        var name = cname + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i].trim();
            if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
        }
        return "";
    }
    

    6.5、WebStorage

    6.5.1、WebStorage概述

    WebStorage是HTML5中本地存储的解决方案之一,在HTML5的WebStorage概念引入之前除去IE User Data、Flash Cookie、Google Gears等看名字就不靠谱的解决方案,浏览器兼容的本地存储方案只有使用Cookie。有同学可能会问,既然有了Cookie本地存储,为什么还要引入WebStorage的概念?那就要说一说Cookie的缺陷了:

    1. 数据大小:作为存储容器,Cookie的大小限制在4KB左右这是非常坑爹的,尤其对于现在复杂的业务逻辑需求,4KB的容量除了存储一些配置字段还简单单值信息,对于绝大部分开发者来说真的不知指望什么了。
    2. 安全性问题:由于在HTTP请求中的Cookie是明文传递的(HTTPS不是),带来的安全性问题还是很大的。
    3. 网络负担:我们知道Cookie会被附加在每个HTTP请求中,在HttpRequest和HttpResponse的header中都是要被传输的,所以无形中增加了一些不必要的流量损失。

    虽然WebStorage是HTML5新增的本地存储解决方案之一,但并不是为了取代Cookie而制定的标准,Cookie作为HTTP协议的一部分用来处理客户端和服务器通信是不可或缺的,session正是依赖于实现的客户端状态保持。WebStorage的意图在于解决本来不应该Cookie做,却不得不用Cookie的本地存储的应用场景。

    6.5.2、WebStorage分类

    Web Storage又分为两种: sessionStorage 和localStorage ,即这两个是Storage的一个实例。从字面意思就可以很清楚的看出来,sessionStorage将数据保存在session中,浏览器关闭也就没了;而localStorage则一直将数据保存在客户端本地; 不管是sessionStorage,还是localStorage,使用的API都相同。

    localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理,低版本IE可以使用json2.js

    6.5.3、localStorage方法

    对象介绍:

    localStorage在本地永久性存储数据,除非显式将其删除或清空。

    常见方法:

    • 保存单个数据:localStorage.setItem(key,value);
    • 读取单个数据:localStorage.getItem(key);
    • 删除单个数据:localStorage.removeItem(key);
    • 删除所有数据:localStorage.clear();
    • 获取某个索引的key:localStorage.key(index);

    案例演示:

    // 保存数据
    localStorage.setItem("username", "zhangsan");
    
    // 读取单个数据
    console.log(localStorage.getItem("username"));
    console.log("===============");
    
    // 删除单个数据
    localStorage.removeItem("username");
    console.log(localStorage.getItem("username"));
    console.log("===============");
    
    // 保存两个数据
    localStorage.setItem("age", 18);
    localStorage.setItem("sex", "男");
    console.log("age=" + localStorage.getItem("age"));
    console.log("sex=" + localStorage.getItem("sex"));
    console.log("===============");
    
    // 使用for-in循环来迭代localStorage中的键值对、属性和方法:
    for (var key in localStorage) {
        console.log(key + "=" + localStorage[key]);
    }
    console.log("===============");
    
    // 使用for循环来迭代localStorage中的键值对:
    for (var i = 0; i < localStorage.length; i++) {
        var key = localStorage.key(i);
        var value = localStorage.getItem(key);
        console.log(key + "=" + value);
    }
    console.log("=====