和城乡建设厅官方网站,网站建设先进城市,投资做个app要多少钱,南宁 网站开发2 基本程序设计结构 摘要 对于学习JS的程序员来说#xff0c;一定是具备了一定的编程功底的#xff0c;故在下面的概述中#xff0c;我们不再提及一些简单的概念。 声明#xff1a;在使用本文的代码时#xff0c;为了避免文章冗长#xff0c;我只附上了script标签内的…2 基本程序设计结构 摘要 对于学习JS的程序员来说一定是具备了一定的编程功底的故在下面的概述中我们不再提及一些简单的概念。 声明在使用本文的代码时为了避免文章冗长我只附上了script标签内的代码供演示如有需要详细代码可以前往代码仓库获取。 作者来自ArimaMisaki创作 文章目录2 基本程序设计结构2.1 变量2.2 数据类型2.3 数据类型转换2.3.1 概述2.3.2 字符串转换2.3.3 字符串转数字型2.3.4 布尔型转换2.4 解释型语言和编译型语言2.5 运算符2.5.1 比较运算符2.5.2 逻辑运算符2.6 流程控制2.6.1 代码块2.6.2 条件判断语句2.6.3 循环控制2.6.4 跳转控制2.7 函数2.8 对象2.8.1 基本概念2.8.2 创建对象2.8.3 对象属性2.8.4 对象方法2.8.4.1 对象方法概念2.8.4.2 this对象2.8.5 对象构造器2.8.6 实例成员和静态成员2.9 作用域2.9.1 基本概念2.9.1.1 作用域及其分类2.9.1.2 变量作用域2.9.2 作用域链2.10 对象原型2.10.1 原型的提出2.10.2 构造函数原型对象2.10.3 对象原型2.10.4 原型构造函数2.10.5 构造函数、实例、原型对象2.10.6 原型链2.10.6.1 原型链2.10.6.2 原型链示意图2.10.7 扩展内置对象2.11 常用方法2.11.1 toString2.11.2 hasOwnProperty2.12 内置对象2.12.1 Array对象2.12.1.1 数组概述2.12.1.2 使用数组2.12.1.3 数组方法2.12.2 Math对象2.12.2.1 Math概述2.12.2.2 Math常用常量及方法2.12.3 Date对象2.12.3.1 Date概述2.12.3.2 Date常见方法以及格式化2.12.3.3 Date对象常见应用2.12.4 String对象2.12.5 RegExp对象2.12.5.1 正则表达式概述2.12.5.2 正则表达式的使用2.12.5.3 元字符2.12.5.4 量词符2.12.5.5 用户名验证2.12.5.6 设置匹配模式2.12.5.7 正则替换2.13 继承2.13.1 call方法2.13.2 原型链继承2.13.3 构造函数继承2.13.4 组合继承2.14 函数高级2.14.1 函数的定义2.14.2 函数的调用2.14.3 this指向问题2.14.4 call方法2.14.5 apply方法2.14.6 bind方法2.14.7 严格模式2.14.8 高阶函数2.15 预解析2.15.1 预解析概述2.15.2 变量提升和函数提升2.16 闭包2.16.1 闭包概念2.16.2 闭包的应用2.16.3 闭包的生命周期2.17 递归2.17.1 递归概述2.17.2 递归的应用2.18 内存问题2.1 变量
格式var 变量名1,变量名2,…
var是一个JS关键字用来声明变量。使用该关键字声明变量后计算机会自动为变量分配内存空间不需要程序员管理。变量名可以用来访问内存中分配的空间。变量名要赋初始值否则会提示undefined。
命名
由字母、数字或下划线美元符号组成严格区分大小写不能以数字开头不能是关键字、保留字变量名需要有意义遵守驼峰命名法 2.2 数据类型
说明与Java和C等强类型语言不同JavaScript是一种弱类型或者说动态类型语言这意味着无需声明变量的类型在程序运行过程中使用var系统会自动确定数据类型。
对于Js来说其数据类型分为简单数据类型基本数据类型或值类型和复杂数据类型引用数据类型。
值类型变量存储的是值本身故又名值类型。如number,boolean,undefined,null,string。
引用数据类型变量存储的仅仅是地址通过new关键字创建的对象如Object、Array、Date等。
scriptvar a 1var b truevar c hellovar dvar e null// 如果需要查看一个变量的数据类型可以使用typeof 数据的方式来检查console.log(a,typeof a);console.log(b,typeof b);console.log(c,typeof c);console.log(d,typeof d);// 如果使用typeof检查null变量则其返回的不是null这个数据类型而是一个Objectconsole.log(e,typeof e);// null代表空值即什么都没有。需要注意的是undefined值实际上是由null值衍生出来的所以如果比较undefined和null是否相等会返回trueconsole.log(d e);// 如果要判断一个值是否为数字可以使用isNaN(数据)的方式来检查其返回一个布尔值console.log(a,isNaN(a));// JS中的字符串型可以使用单引号也可以使用双引号一般来说推荐单引号// 字符串可以进行嵌套其遵循外双内单外面双引号里面单引号准则var str1 hellovar str2 world// 多个字符串可以使用进行拼接多个数据类型拼接只要一个含有字符串则其他数据类型与其拼接时最终结果也是字符串console.log(str1 str2);console.log(str1 1);// 如果需要判断字符串的长度可以使用.length的方式查看其长度。使用小数点调用是属性调用的一种方式console.log(str1.length);/script2.3 数据类型转换
2.3.1 概述
引入使用表单、prompt获取过来的数据默认是字符串类型的此时就不能直接简单的进行加法运算了而需要转换变量的数据类型。
说明通俗来说就是把数据类型的变量转换为另外一种数据类型。通常我们会涉及三种方式转换
转换为字符串类型转换为数字型转换为布尔型 2.3.2 字符串转换
script// 字符串的转换// 1. toString()可以将某些数据类型转为字符串var a 1console.log(a, typeof a)var str a.toString()console.log(str, typeof str)// 2.String(变量或字面量)可以将其他数据类型强转字符串var num1 1var str1 String(num1)console.log(str1, typeof str1)// 3.字符串拼接var str2 1var str3 console.log(str2 str3,typeof (str2str3))/script2.3.3 字符串转数字型
方式说明案例parseInt(String)将字符串类型转为整数数字型parseInt(‘78’)parseFloat(String)将字符串类型转为浮点数数字型parseFloat(‘78.21’)Number(变量或字面量)将String强转数值型Number(‘12’)js隐式转换利用算数运算隐式转换为数值型‘12’-0
scriptstr1 78;str2 78.01str3 78px// 1.将字符串类型转为整数数字型console.log(parseInt(str1), typeof parseInt(str1));// 如果使用parseInt将小数字符串转为整数则小数点后的数字会被截断console.log(parseInt(str2), typeof parseInt(str2));// 如果使用parseInt将数字单位格式的字符串转为整数则单位会被去掉console.log(parseInt(str3), typeof parseInt(str3));// 2.将字符串类型转为浮点数数字型console.log(parseFloat(str2),typeof parseFloat(str2));// 3.将String强转数值型console.log(Number(str1),typeof(Number(str1)));// 4.隐式转换console.log(str1-2);/script2.3.4 布尔型转换
说明使用Boolean()可以实现强转布尔型其中代表空和否定的值会被转换为false而其他值则会变为true
scriptvar a 1var b 12var c 0var d // 没有初始化值为undefinedconsole.log(Boolean(a),typeof Boolean(a));console.log(Boolean(b),typeof Boolean(b));console.log(Boolean(c),typeof Boolean(c));console.log(Boolean(d),typeof Boolean(d));/script2.4 解释型语言和编译型语言
说明计算机只能理解机器语言故编程语言都得通过翻译器翻译为机器语言才可执行。翻译的两种方式是编译和解释。编译是代码执行前先进行编译生成中间代码文件典型代表为Java而解释器是边运行边解释并立即执行典型代表为JavaScriptpython。 2.5 运算符
2.5.1 比较运算符
script//比较运算符运算的结果是一个布尔值console.log(12);console.log(12);console.log(12);console.log(12);console.log(1 1);//JS中的会转型要求值和数据类型可以不一致console.log(1 ! 2);console.log(1 1);//全等要求值和数据类型都一致/script2.5.2 逻辑运算符
scriptconsole.log(2 1 2 3);//逻辑与一假必假console.log(2 1 || 2 3);//逻辑或一真必真console.log(!(2 1));//逻辑非/script2.6 流程控制
2.6.1 代码块
JS的语句和Java一样都是以分号结尾。在书写流程控制时我们难免在执行体中需要书写多条语句。JS沿袭了C和Java的风格使用了代码块即使用花括号大括号将所有语句括起代码块的作用是将所有的语句视为一条语句。 2.6.2 条件判断语句
条件判断语句中的if、if-else、if-else if和switch都与Java相同故这里不再赘述。 2.6.3 循环控制
循环控制中的while、do…while、for语法都与Java相同故这里不再赘述。 2.6.4 跳转控制
跳转控制中的break和continue都与Java相同故这里不再赘述。 2.7 函数
script//1. 函数定义function myfn() {console.log(定义的函数被调用);}// 函数调用myfn()//2. 函数表达式var myfn2 function () {console.log(函数表达式被调用);}myfn2()//3. 有参函数var add function (a, b) {return a b;}console.log(add函数执行的结果是add(1,2));//4. 当我们不确定函数的参数有多少个时可以使用arguments来获取console.log(myfn2.arguments);console.log(add.arguments);//5. 嵌套函数 与高级编程语言不同的是JS允许函数的定义存在于另一个函数定义的内部。function outfn(){function innerfn(){console.log(我是内层函数);}innerfn()console.log(我是外层函数);}outfn()/script2.8 对象
2.8.1 基本概念
对象在JavaScript中万物皆是对象故所有事物都可以传给var变量。Object类型我们就叫做对象类型。前面提到过基本数据类型都属于Object类型。
原始值原始值指的是没有属性或方法的值。也就是我们前面提到的五种基本数据类型。 2.8.2 创建对象
script//第一种方式利用Object自带的构造器创建对象后添加属性var person new Object();person.name ArimaMisaki ;//利用对象.属性的方式可以添加、修改和访问属性person.age 18;console.log(person);console.log(person.name);//利用对象.属性 来读取对象中的属性console.log(person.school);//如果对象中没有该属性而去读取则会显示无定义undefined//第二种方式利用对象字面量创建对象var person {name: ArimaMisaki,age: 18};console.log(person);//第三种方式利用构造器生成对象function Person(aname, aage, asex) {this.name aname;this.age aage;this.sex asex;}new Person(刘德华, 18, 男);//利用instanceof可以查看某对象是否属于某个构造函数console.log(person instanceof Person);;/script2.8.3 对象属性
scriptvar person {uname:ArimaMisaki,age:22}console.log(person);//1. 访问属性// 方式1 利用对象.属性console.log(person.uname);// 方式2 利用对象.[属性]console.log(person[uname]);//2. 修改属性访问并修改即可person.uname AMconsole.log(person.uname);//3. 添加属性直接对象.属性即可person.sex 男console.log(person.sex);console.log(person);//4. 删除属性delete 对象.属性delete person.sexconsole.log(person);//5. 利用增强for遍历对象中的属性for(var a in person){console.log(a);}/script2.8.4 对象方法
2.8.4.1 对象方法概念
对象方法JS中的方法是用于存储对象属性的函数
访问对象方法对象.方法名() 2.8.4.2 this对象
this实际上可以看做是一个指针其作用和Java中的this类似。当在一个构造器中使用this指针时this指代的是通过构造器new出来的对象。也就是说this.name aname;如果存在于Person构造函数中则通过new Person()生成的对象自带一个name属性。
this在函数定义的时候是无法确定的只有函数执行的时候才能确定this到底指向谁一般情况下this的最终指向是那个调用它的对象。
scriptfunction Person(aname,aage,asex){this.name aname;this.age aage;this.sex asex;this.Select function(){console.log(this.name);console.log(this.age);console.log(this.sex);};}var person new Person(ArimaMisaki,18,男);person.Select();
/script2.8.5 对象构造器
script//构造函数是一种特殊的函数用于创建对象function Person(aname, asex) {this.name aname;this.sex asex;}//使用new关键字来创建对象这个过程叫实例化无变量接收的为匿名对象console.log(new Person(ArimaMisaki,fale));;/script注构造函数名最好大写这符合高级编程语言的习惯。 2.8.6 实例成员和静态成员
script//实例成员就是构造函数内部通过this添加的成员如name sex就实例成员 function Person(name, sex) {this.aname name;this.asex sex;}//实例成员只能通过对象来访问var person new Person(ArimaMisaki,fale);console.log(person.aname);console.log(Person.aname);//静态成员就是构造函数上的添加的成员Person.aage 13;//静态成员只能通过构造函数来访问console.log(Person.aage);var person1 new Person(person2,fale);console.log(person1.aage);/script2.9 作用域
2.9.1 基本概念
2.9.1.1 作用域及其分类
作用域代码名字在某个范围内起作用和效果。其目的是为了提高程序的可靠性更重要的是减少命名冲突。JS作用域的划分分为全局作用域和局部作用域函数作用域全局作用域整个script标签或者是一个单独的js文件局部作用域代码只在函数内部起效果 2.9.1.2 变量作用域
说明根据作用域的划分可以分为全部变量和局部变量。
全局变量的特殊情况如果一个变量在没有声明var的情况下被赋值了且处于函数内部那么它也是全局变量。不建议使用局部变量的特殊情况如果一个变量此前没有任何声明但是出现在了函数的形参列表中那么它也是局部变量。
全局变量只有在浏览器关闭的时候才会销毁比较占用资源局部变量函数执行完毕就会销毁比较节约资源。 2.9.2 作用域链
查找一个变量时是由内而外查找如果找到最外面还未找到变量则报ReferenceError异常。
function f1() {var num 123;function f2() {console.log(num);}f2;}var num 456;f1();
//结果输出因为123因为num离123近。2.10 对象原型
2.10.1 原型的提出
使用构造函数创建对象会出现的一个问题即每个对象属性不一样但方法一样。若通过构造函数创建1000个对象则内存中有1000个相同的方法。为此我们将构造函数中的方法抽离使其作为全局函数该全局函数我们会在构造函数中使用。
scriptfunction Person(name,age){this.name name;this.age age;this.sayName sayName;}function sayName(){console.log(this.name);}var person1 new Person(同学A,18);var person2 new Person(同学B,18);person1.sayName();person2.sayName();/script注这么做虽然不失为一种好方法但是容易出现不同构造函数的同名方法容易污染全局作用域的命名空间。为此我们需要使用到原型来解决这个问题。 2.10.2 构造函数原型对象
script//原型对象prototypefunction Person(name, sex) {this.aname name;this.asex sex;}console.log(Person.prototype);//公共变量为静态变量想要使用静态变量方式声明//静态变量也可以使用原型对象声明但是无法通过构造函数调用了Person.prototype.aage 13;var person new Person(ArimaMisaki,fale);console.log(person.aage);//添加公共方法Person.prototype.run function () {console.log(人会走路);}console.log(person.run());/script注
每次创建函数对象解析器都会向函数中添加一个prototype原型对象。构造函数通过原型分配的函数是所有对象所共享的。把不变的方法直接定义在prototype上所有对象的实例就可以共享这些方法以达到节省内存的效果。当访问对象方法时它会在对象自身中寻找如果有则直接使用否则会去原型对象中寻找直至找到并使用。构造器定义好后是无法直接往构造器中添加新方法但是我们可以往它的原型中添加。以后创建构造函数可以将对象共有的属性和方法统一添加到构造函数的原型对象中。而无需每个对象一个一个去添加。这样做的好处既避免了污染全局作用域又使得对象具有独立性。一般来说原型对象上面只存方法不存属性。如果构造函数的属性都一样了构造函数就失去意义了。 2.10.3 对象原型
scriptfunction Person(name, sex) {this.aname name;this.asex sex;}var person new Person(ArimaMisaki, fale);//对象中隐含属性__proto__记录原型对象prototype的地址console.log(person.__proto__);console.log(person.__proto__ Person.prototype);//方法查找规则先在自身寻找找不到再去原型对象上找Person.prototype.aage 13;console.log(person.aage);/script2.10.4 原型构造函数
scriptfunction Person(name, sex) {this.aname name;this.asex sex;}var person new Person(ArimaMisaki, fale);//constructor用于指明某对象原型的构造函数console.log(Person.prototype.constructor);console.log(person.__proto__.constructor);console.log(person.constructor);//用法手动指回构造函数function Star(uname,age){this.uname uname;this.age age;}//(1)原型对象被覆盖了没有用.的方式来添加Star.prototype {//(2)需要用constructor指回原对象constructor:Star,sing:function(){console.log(我会唱歌);},movie:function(){console.log(我会演电影);}}//声明对象var ldh new Star(刘德华,18);console.log(ldh.__proto__);/script2.10.5 构造函数、实例、原型对象 2.10.6 原型链
2.10.6.1 原型链
script//原型链function Star(uname,age){this.uname uname;this.age age;}Star.prototype.sing function() {console.log(我会唱歌);}var ldh new Star(刘德华,18);//1 只要有对象就有__proto__原型指向构造函数中的原型对象console.log(Star.prototype);//prototype为原型对象其本质也是对象其中也存在__proto__指向Object对象的prototypeconsole.log(Star.prototype.__proto__ Object.prototype);//2 Object原型对象的__proto__为空console.log(Object.prototype.__proto__);//3 对象成员规则按照原型链来寻找Object.prototype.jump function() {console.log(我会跳舞);}ldh.jump();//ldh找不到去Star构造函数中的原型对象找找不到去Object的原型对象找找到了调用。/script2.10.6.2 原型链示意图 2.10.7 扩展内置对象
script//原型对象的应用扩展内置对象方法//1 查看Array的原型对象console.log(Array.prototype);//2 为原先的Array添加内置方法Array.prototype.sum function() {var sum 0;for (var i 0; i this.length; i) {sum this[i];}return sum;}var arr [1,2,3];//3 调用新添加到Array的sum方法console.log(arr.sum());/script2.11 常用方法
2.11.1 toString
说明toString函数用于将对象以字符串的形式返回。该方法属于Object所有对象都继承自Object故所有对象都可调用该方法。 2.11.2 hasOwnProperty
说明如需判断当前对象是否包含指定的属性或方法可以使用属性 in 对象的方式来检查。
前面我们谈论过属性和方法的查找从对象本身开始找至原型对象。所以如果想要仅仅检查自身对象而不检查原型对象则可以使用hasOwnProperty方法。同样地该方法属于Object对象中的原型对象的原型对象。 2.12 内置对象
JS对象分为三种自定义对象、内置对象、浏览器对象ECMAScript。这一小节中主要讲解内置对象。内置对象就是JS语言自带的一些对象这些对象供开发者使用并提供了一些常用的或是最基本而必要的功能。
学会利用中文手册查阅内置对象是一件十分有必要的事。常用的中文手册有
W3C:HTML5 浏览器支持 (w3school.com.cn)MDN:MDN Web Docs (mozilla.org) 2.12.1 Array对象
2.12.1.1 数组概述 数组需要通过构造函数来创建对象。 JavaScript支持数组中可以有不同类型的元素这跟JavaScript的弱类型有关我们大多数时候都是相同类型元素的集合。 数组内的各个值被称作元素每一个元素都可以通过索引下标来快速读取索引是从零开始的整数。
2.12.1.2 使用数组
script// 1. 创建数组// 1构造函数法利用构造函数var arr1 new Array()console.log(arr1);// (2) 引用类型利用数组字面量var arr2 [1,2,3,4]console.log(arr2);// 2. 数组中可以有不同类型的元素var arr3 [1,1,true,null]console.log(arr3);// 3. 访问数组元素// (1) 使用索引访问元素 数组元素从0开始console.log(arr2[0]);// (2) 使用for循环来打印数组元素for (var i 0; i arr2.length; i) {console.log(arr2[i]);}// (3) 使用增强for循环来打印数组for(var a in arr2){console.log(a);}//4. 数组常用属性//(1) 打印数组的长度console.log(arr3.length);//(2) 打印数组的原型console.log(arr3.constructor);/script2.12.1.3 数组方法
scriptvar arr1 [1, 2, 3]var arr2 [1]var arr3 [2]var arr4 [5, 4, 2, 1, 8]// 1.使用push方法可以向数组末尾添加元素arr1.push(4);console.log(arr1);// 2.使用pop方法可以删除数组的最后一个元素,并且将删除的元素作为返回值返回console.log(arr1.pop());console.log(arr1);// 3.使用unshift方法可以向数组开头添加元素arr1.unshift(0);console.log(arr1);// 4.使用shift方法可以删除数组的第一个元素并且将删除的元素作为返回值返回console.log(arr1.shift());console.log(arr1);// 5.使用forEach方法可以遍历数组arr1.forEach(function (value, index, array) {console.log(数组元素为 value);console.log(数组索引为: index);console.log(来自数组 array);})// 6.使用slice(起始位置终止位置)方法可以读取数组元素并将读取后的元素装到一个新数组中返回。console.log(arr1.slice(0, 2));// 7.使用concat方法合并两个数组并将合并后的新数组返回。arr arr2.concat(arr3);console.log(arr);// 8.使用join(“分隔符”)方法可以将数组转换为字符串。其中分隔符的指定不是刚需如没有指定分隔符则默认使用逗号。var str arr1.join(-);console.log(str);// 9.使用reverse方法可以用于反转数组console.log(arr1.reverse());// 10.使用sort方法可以用于数组排序console.log(arr4.sort());// 如果想要指定排序规则可以使用回调函数具体实现为arr.sort(function (a,b)){return a-b}。如果升序则返回a-b如果降序则返回b-a。console.log(arr4.sort(function (a, b) {return b - a;}));// 11.使用filter可以筛选数组并且返回一个新数组var filterStr arr1.filter(function (value, index) {// 筛选数组中大于等于2的元素并作为一个数组返回return value 2})console.log(filterStr);// 12.使用some可以查找数组中是否有满足条件的元素并返回布尔值。当找到符合条件的第一个元素后便不再查找console.log(arr1.some(function (value, index) {// 查找数组中是否有大于等于2的元素存在return value 2}));/script2.12.2 Math对象
2.12.2.1 Math概述
Math是一个内置对象它具有数学常数和函数的属性和方法不是一个函数对象
与其他全局对象不同的是Math不是一个构造器Math的所有属性和方法都是静态的通过小数点的方式即可调用。 2.12.2.2 Math常用常量及方法
Script/*常用数学常量*/console.log(Math.PI);//圆周率console.log(Math.E);//欧拉常数econsole.log(Math.LN2);//以2为底自然对数console.log(Math.LN10);//以10为底自然对数console.log(Math.SQRT1_2);//二分之一的平方根console.log(Math.SQRT2);//2的平方根/*常用方法*/console.log(Math.abs(-2));//返回绝对值console.log(Math.floor(2.3));//向下取整console.log(Math.ceil(2.3));//向上取整console.log(Math.round(3.6));//四舍五入console.log(Math.min(1,99,3));//求最小值console.log(Math.max(1,99,3));//求最大值console.log(Math.random());//0-1左闭右开随机数通过运算符可以扩大其随机数范围/Script2.12.3 Date对象
2.12.3.1 Date概述
创建Date实例用来处理日期和时间。Date对象基于1970年1月1日起的毫秒数。
必须使用构造函数创造对象。 2.12.3.2 Date常见方法以及格式化
script/*构造方式1如果是无参构造器则返回当前时间*/var date1 new Date();console.log(date1);/*构造方式2如果是有参构造器如2022-7-12则返回字符串对应的时间*/var date2 new Date(2022-7-12);console.log(date2);/*date对象常用方法*/console.log(date1.getFullYear());//获取当年console.log(date1.getMonth());//获取当月console.log(date1.getDate());//获取当天console.log(date1.getDay());//获取星期几console.log(date1.getHours());//获取当前时console.log(date1.getMinutes());//获取当前分console.log(date1.getSeconds());//获取当前秒/*日期格式化*/var date3 new Date();var year date3.getFullYear();var month date3.getMonth();var day date3.getDate();var dayOfWeek date3.getDay();var arr [星期日,星期一1,星期二,星期三,星期四,星期五,星期六];function gettime() {var h date1.getHours();var m date1.getMinutes();var s date1.getSeconds();return h:m:s;}console.log(今天是year年month月day日arr[dayOfWeek]gettime());/script2.12.3.3 Date对象常见应用
script/*获得1970.1.1距今为止过了多少毫秒*/var date1 new Date();var date2 new Date();console.log(date1.valueOf()); console.log(date1.getTime());console.log(date2);//最常用写法console.log(Date.now());/*倒计时*///使用输入未来时间和现在时间毫秒时间戳来对减所得毫秒再转换为时间即可function countDown(time) {var nowTime new Date();//返回的是当前时间总的毫秒数var inputTime new Date(time);//返回的是用户输入时间总的毫秒数var times (inputTime-nowTime)/1000;//time是剩余时间总的秒数d d10?0d:d;var d parseInt(times/60/60/24);//计算天数h h10?0h:h;var h parseInt(times/60/60%24);//计算小时m m10?0m:m;var m parseInt(times/60%60);//计算分数s s10?0s:s;var s parseInt(times%60);//计算秒数return d天h时m分s秒;}console.log(countDown(2022-7-20 18:00:00));/script2.12.4 String对象
常用方法说明charAt()可以返回字符串中指定位置的字符charCodeAt()可以返回字符串中指定位置字符的Unicode编码formCharCode()可以根据字符编码获取字符该方法为静态方法concat()可以连接多个字符串作用等同于加号indexOf(‘要查找的字符’,开始查找的位置)可以检索一个字符串中是否含有指定内容有就返回索引没有就返回-1lastIndexOf(‘要查找的字符’,开始查找的位置)和indexOf用法相同 但该方法是从后往前找slice(起始索引,结束索引)截取子串但左闭右开。但参数可以有负值substring(索引1,索引2)截取子串但左闭右开。但参数不能有负值。索引1若大于索引2则自动交换toUpperCase()将一个字符串转换为大写并返回toLowerCase()将一个字符串转换为小写并返回2.12.5 RegExp对象
2.12.5.1 正则表达式概述
说明正则表达式Regular Expression是用于匹配字符串中字符组合的模式。在Js中正则表达式也是对象。
应用场景验证表单过滤敏感词 2.12.5.2 正则表达式的使用
script// / 正则表达式内容 /// 1.通过RegExp对象的构造函数创建var regexp new RegExp(/123/);console.log(regexp);// 2.通过字面量创建正则表达式var rg /123/;// 测试正则表达式 regexpobject.test(teststr)console.log(rg.test(456));//false因为正则表达式要求str为123console.log(rg.test(123));//true/script2.12.5.3 元字符
元字符说明^写在开头表示要求行首具有表达式内容写在范围符[]内部表示取反$要求行尾具有表达式内容[]字符类表示[]中的字符满足其中一个即可-范围符需搭配字符类使用
script// 0.正则表达式不需要加引号 无论是数字还是字符var rg1 /abc/ //只要有abc这个字符串返回的都是trueconsole.log(rg1.test(abcd));//trueconsole.log(rg1.test(abcde));//trueconsole.log(----------);// 1.要求行首具有表达式内容var rg2 /^abc/console.log(rg2.test(abcd));//trueconsole.log(rg2.test(aabcd));//falseconsole.log(----------);// 2.要求行尾具有表达式内容 var rg3 /abc$/console.log(rg3.test(abcd));//falseconsole.log(rg3.test(aabc));//trueconsole.log(----------);// 3.^和$搭配实现精确匹配要求必须是指定的字符串var rg4 /^abc$/console.log(rg4.test(abcd));//falseconsole.log(rg4.test(abcabc));//falseconsole.log(rg4.test(abc));//trueconsole.log(----------);// 4.字符类[]var rg5 /[abc]/ //只要包含a或者b或者c任意字母即可console.log(rg5.test(a));//trueconsole.log(rg5.test(ab));//trueconsole.log(rg5.test(5));//falsevar rg6 /^[abc]$/ // 只能三选一,即只能匹配a,b,c即使是aa也是错的console.log(rg6.test(ab));//falseconsole.log(----------);// 5.范围符-var rg7 /^[a-z]$/ //只能输出26个字母任意一个console.log(rg7.test(5));//falseconsole.log(rg7.test(a));//trueconsole.log(rg7.test(abc));//falseconsole.log(----------);var rg8 /[a-zA-Z0-9]/ //可以输出大小写字母和数字任意字符console.log(rg8.test(8));//trueconsole.log(rg8.test(a));//trueconsole.log(rg8.test(aA5));//trueconsole.log(----------);// 6.取反^var rg9 /^[^a-z]$/ //可以输出除了小写字母以外的任意字符console.log(rg9.test(1));//trueconsole.log(rg9.test(A));//trueconsole.log(rg9.test(a));//false/script2.12.5.4 量词符
说明用于设定某个模式出现的次数
量词说明*可以出现0次或者很多次可以出现1次或多次?可以出现1次或0次{n}重复n次{n,}出现大于等于n次{min,max}出现次数大于等于min次且小于等于max次。需要注意花括号内不要有空格。
script// 1.* 可以出现0次或多次var rg1 /^a*$/ //表示a可以出现0次到多次console.log(rg1.test(aaabb));//falseconsole.log(rg1.test(aaaa));//trueconsole.log(rg1.test());//trueconsole.log(rg1.test(1));//falseconsole.log(----------);// 2. 可以出现1次或多次var rg2 /^a$/ //表示a可以出现1次或多次console.log(rg2.test());//trueconsole.log(rg2.test(aa));//trueconsole.log(rg2.test(aabb));//falseconsole.log(----------);// 3.? 可以出现1次或0次var rg3 /^a?$/ //表示a出现0次或一次console.log(rg3.test());//trueconsole.log(rg3.test(a));//trueconsole.log(rg3.test(aa));//fasleconsole.log(----------);// 4.{} 重复n次var rg4 /^a{3}$/ //要求a重复3次console.log(rg4.test());console.log(rg4.test(aa));console.log(rg4.test(aaa));console.log(----------);// 5.{n,} 出现大于等于n次var rg5 /^a{3,}$/ //要求a出现大于等于3次console.log(rg5.test());//falseconsole.log(rg5.test(aaa));//trueconsole.log(rg5.test(aaaa));//trueconsole.log(----------);// 6.{min,max} 出现次数大于等于min次且小于等于max次var rg6 /^a{3,5}$/ //要求a出现3次以上5次以下 左闭右闭console.log(rg6.test());//falseconsole.log(rg6.test(a));//falseconsole.log(rg6.test(aaaa));//trueconsole.log(rg6.test(aaaaaaaa));//fasle/script2.12.5.5 用户名验证
!DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestylediv{background-color: skyblue;height: 50px;width: 70px;}/style
/head
bodyinput typetext class uname placeholder请输入用户名brspan输入用户名字数在6-16之间,且只能是大小写字母或数字可以有下划线和横杠/spanscriptvar uname document.querySelector(.uname)// 指定正则表达式var reg /^[a-zA-Z0-9_-]{6,16}$///表单失去焦点时开始验证uname.onblur function(){if(reg.test(this.value)){alert(用户名可以使用)}else{alert(用户名格式有误)}}/script
/body
/html2.12.5.6 设置匹配模式
RegExp构造器设置匹配模式new RegExp(/正则表达式/,“匹配模式”)
字面量设置匹配模式var reg /正则表达式/[匹配模式]
匹配模式的值
i忽略大小写g全局匹配模式一段文本中若有多处匹配内容正则表达式可以选取所有的匹配内容ig忽略大小写且全局匹配模式 2.12.5.7 正则替换
说明str.replace(“正则表达式”,“替换内容”)可以传入两个参数第一个为正则表达式他能将符合的内容替换为第二个参数中的替换内容。以下的案例中所写代码只能替换一个敏感词若要替换全局敏感词请设置匹配模式g。
!-- 设定一个留言框当数据提交后采用正则将数据中的敏感词汇替换 --textarea name idmessage/textareabutton提交/buttonscriptvar text document.querySelector(textarea)var sub_btn document.querySelector(button)// 这里设定激情为敏感词并将其替换为**sub_btn.onclick function () {var str text.value.replace(/激情/,**)alert(str)}/script2.13 继承
面向对象语言都有三大特性继承、封装和多态且多数含有类和对象的概念。在ES6之前的ES5版本中没有提供extend来继承也没有class来体现出类的概念顾我们需要另辟蹊径。
JS继承有六种但常用的只有三种 原型链继承 借用构造函数继承 组合继承 原型式继承 寄生式继承 寄生组合式继承 2.13.1 call方法
格式fn.call(thisArg,arg1,arg2…)
说明call用于修改this的指向thisArg是什么对象this就指向什么对象。
script//call作用1调用函数function fn(x,y){console.log(喝咖啡);console.log(this);console.log(xy);}// fn();fn.call();var o {name:andy};//call作用2修改this指向ofn.call(o,1,2)/script2.13.2 原型链继承
基本思想子的原型为父的实例对象。通过原型链来搭建继承关系。
优点父类方法可以复用
缺点
父类所有的引用类型数据会被类共享更改一个子类的数据其他子类都会受到影响跟着改变子类实例不能给父类构造函数传参继承单一
script//父类型的构造函数function SupperType() {this.supProp Supper property;}//子类型的构造函数function SubType() {this.subProp Sub property;}//父类型的方法SupperType.prototype.showSupperProp function() {console.log(this.supProp);};//父类型的对象就是子类型的原型SubType.prototype new SupperType();SubType.prototype.constructor SubType;//子类型的方法SubType.prototype.showSubProp function() {console.log(this.subProp);};//调试创建子类型对象调用父类型的方法var sub new SubType();sub.showSupperProp();sub.showSubProp();/script2.13.3 构造函数继承
基本思想用.call()和.apply()将父类构造函数引入子类函数。
优点
只继承了父类构造函数的属性没有继承父类原型的属性解决了原型链继承缺点可以继承多个构造函数属性在子实例中可向父实例传参
缺点
只能继承父类构造函数的属性无法实现构造函数的复用每个新实例都有父类构造函数的副本显得代码臃肿
scriptfunction Person(){this.name xiaomingthis.colors [red,blue,green]}Person.prototype.getName function(){console.log(this.name);}function Child(age){Person.call(this)this.age age}var child1 new Child(23);var child2 new Child(12);child1.colors.push(yellow)console.log(child1.name);//xiaomingconsole.log(child1.colors);//(4) [red, blue, green, yellow]console.log(child2.colors);//(3) [red, blue, green]/script2.13.4 组合继承
基本思想结合了前两种继承方式的优点。
优点
可以继承父类原型上的属性可以传参可复用每个新实例引入的构造函数属性是私有的
缺点调用了两次父类构造函数子类的构造函数会代替原型上的那个父类构造函数
script//1 准备两个构造函数function Father(uname, age) {this.uname uname;this.age age;}function Son(uname, age, score) {Father.call(this,uname,age);//使用call改变父构造的指向达到继承效果this.score score;//可定制子构造的属性}//2 子对象属性的使用var son new Son(ArimaMisaki,13,100);console.log(son);//3 子对象方法的使用Son.prototype new Father();//儿子的原型对象是父亲的构造器Son.prototype.constructor Son;//直接覆改原型对象记得用constructor指回原来的构造函数Father.prototype.money function(){console.log(10000);};Son.prototype.exam function(){console.log(要考试);};var son2 new Son(ArimaMisaki,14,99)son2.exam();son2.money();/script2.14 函数高级
2.14.1 函数的定义
script// 1 直接定义function fn() {};// 2 函数表达式var fun function() {};// 3 构造函数形式,利用new Function(参数1,参数2...函数体);var f new Function(x,y,console.log(xy));f(1,2);// 4 所有函数都是Function构造函数的实例console.log(f instanceof Function);/script2.14.2 函数的调用
scriptfunction fn() {console.log(函数被调用);}// 1 普通调用 fn();// 2 call方法调用fn.call();// 3 对象方法调用var o {sayHi:function(){console.log(方法里的函数被调用);}}o.sayHi();// 4 构造函数调用function Star(){};new Star();// 5 绑定事件函数后面DOM会学到// btn.onclick function(){}// 6 定时器函数后面BOM会学到// btn.setInterval(function(){},10000);// 7 立即执行函数(function() {console.log(立即执行函数被调用);})();/script2.14.3 this指向问题
script// 1 普通函数thisfunction fn() {console.log(this);//this指向window}fn();//本质上是window.fn()// 2 对象方法thisvar o {sayHi:function(){console.log(this);//this指向o}}o.sayHi();// 3 构造函数thisfunction Star(){console.log(this);};var star new Star();//this指向star// 4 绑定事件函数btn.onclick function(){console.log(this);//指向btn对象}// 5 定时器函数btn.setInterval(function(){console.log(this);//指向window},10000);// 6 立即执行函数(function() {console.log(this);//指向window})();/script2.14.4 call方法
详见2.13.1。 2.14.5 apply方法
说明
apply方法的参数列表必须以数组形式传入apply意为应用可以将某个方法应用在某个数据上
scriptvar o {name: andy};function fn(x,y) {console.log(this);console.log(xy);}//apply调用函数// 1 和call相同第一参数可以改变指向传参使用数组的形式fn.apply(o,[1,2]);// 2 使用apply借助内置对象var arr [1,66,3,99,4];// 3.虽然此时apply不改变指向但是我们还是写上调用者而不是写null防止出问题var maxNumber Math.max.apply(Math,arr);console.log(maxNumber);/script2.14.6 bind方法
说明
bind不会调用原来的函数且可以改变原来函数内部的this指向返回的原函数是改变this之后产生的新函数
script//call作用1调用函数function fn(x,y){console.log(喝咖啡);console.log(this);console.log(xy);}// fn();fn.call();var o {name:andy};//bind作用2意为绑定用于修改this指向var f fn.bind(o,1,2);f();/script2.14.7 严格模式
说明JS除了正常模式之外还提供了严格模式。ES5的严格模式是采用限制性的JS变体即在严格的条件下运行JS代码。
开启方式
在script的第一行写入use strict即可全局开启严格模式。可以在第一行中写入立即执行函数在函数中写入use strict即可全局开启严格模式。可以在普通函数中第一行写入use strict意为只在该函数内部开启严格模式
严格模式的规范内容
变量规定。不加var的变量直接赋值不可使用且不能通过delete来清除定义好的变量的内存。this指向问题。原先的this默认指向window在严格模式中this默认指向undefined。构造函数调用。在利用构造函数生成对象时可以按普通函数调用但在严格模式下必须用new生成对象。BOM对象的this仍然指向window。函数参数问题。同一个函数中不能写入同名参数。函数作用域问题。函数可以声明或定义在一个函数的作用域内部但不能存在于其他作用域内部如if作用域for作用域。 2.14.8 高阶函数
说明高阶函数指的是参数列表中使用其他函数为参数最典型的为callback回调函数。 2.15 预解析
2.15.1 预解析概述
引入JavaScript代码时由浏览器中的JavaScript解析器来执行的JavaScript解析器在运行JavaScript代码的时候分为两步预解析和代码执行。
预解析js引擎会把js里面所有的var还有function提升到当前作用域的最前面。其分为变量预解析变量提升以及函数预解析函数提升。
代码执行按照代码书写的顺序从上往下执行 2.15.2 变量提升和函数提升
变量提升把所有变量声明提升到其作用域的最前面。
函数(声明)提升相当于C里面的函数声明。
script// 1.变量提升a的变量声明提到最前面但是没有包括赋值操作console.log(a); //undefinedvar a 3// 相当于以下代码// var a// console.log(a);// a 3// 2.函数表达式的变量提升fn1() //报错因为没有定义fn1,相当于undefinedvar fn1 function(){console.log(调用了fn1);}// 3.函数提升fn2先声明相当于C里面的函数声明fn2()function fn2() {console.log(调用了fn2);}/script2.16 闭包
2.16.1 闭包概念
说明在一个作用域中可以访问另外一个函数内部的局部变量。
作用延伸了变量的作用范围。
script// 第一种写法function fn(){var age 11function innerfn(){console.log(age);}innerfn()}fn()// 第二种写法function fn1(){var name ArimaMisakifunction fn2(){console.log(name);}return fn2;}var f fn1();f();/script2.16.2 闭包的应用
说明我们打算点击li获取li的索引号。这是一道面试题。
divulli榴莲/lili臭豆腐/lili鲱鱼罐头/lili大猪蹄子/li/ul/divscript// 利用闭包的方式得到当前小li的索引号var list document.querySelector(ul).querySelectorAll(li)for (var i 0; i list.length; i) {// 立即执行函数也称为小闭包(function(i){list[i].onclick function(){// 这里的i用的是外面函数的iconsole.log(i);}})(i);}/script2.16.3 闭包的生命周期 2.17 递归
2.17.1 递归概述
说明一个函数可以在内部调用自身那么其为递归函数。递归函数的效果和循环一样。同理循环会死循环递归也会发生栈溢出我们的函数都是存储在栈中如果多次调用而不释放栈的内存不够用就会发生上述情况。为了防止栈溢出确定边界条件是至关重要的。 2.17.2 递归的应用
目标求解n的阶乘
scriptfunction fn(n){if(n 1) return 1 return n*fn(n-1)}console.log(fn(3));/script2.18 内存问题
堆由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构的栈
堆存储复杂类型的一般由程序员分配释放若程序员不释放则由垃圾回收机制回收
说明JavaScript并没有堆栈概念但是却蕴含了这些概念。如果我们写出var arr new Array()。那么arr存放在栈new Array()存放在堆new Array()将其在堆的十六进制地址提供给arr。