长湖南营销型网站,现在网站开发模式,做教育集团的网站,常州工厂网站建设闭包闭包的基本概念闭包#xff08;closure#xff09;是JavaScript语言的一个难点#xff0c;也是JavaScript的一个特色#xff0c;很多高级的应用都要依靠闭包来实现。作用域在js中#xff0c;函数会形成函数作用域#xff0c;在函数内部可以直接访问全局变量var str …闭包闭包的基本概念闭包closure是JavaScript语言的一个难点也是JavaScript的一个特色很多高级的应用都要依靠闭包来实现。作用域在js中函数会形成函数作用域在函数内部可以直接访问全局变量var str zs; function fn(){ console.log(str);//访问全局变量 } fn();//zs在函数外部却无法访问函数内部的变量function fn(){ var str zs; } fn(); console.log(str);//报错 str is not defined问题我怎么才能获取到函数内部的变量作用域链在函数内部有一个函数那么函数内部的函数是可以访问到外部函数的变量的。解决方法function fn(){ var str zs; function f2(){ console.log(str); } f2(); } fn();在上述代码中fn中定义的所有变量对于f2函数都来都是可以访问的。但是现在f2在函数的内部我们如何在外部访问到f2这个函数呢function fn(){ var str zs; function f2(){ console.log(str); } return f2; } var result fn(); result();// zs闭包的概念闭包是函数和声明该函数的词法环境的组合。在JavaScript中在函数中可以嵌套定义另一个函数时如果内部的函数引用了外部的函数的变量产生闭包。闭包中包含了内部函数的代码以及所需外部函数中的变量的引用产生闭包的条件当内部函数访问了外部函数的变量的时候就会形成闭包。闭包的作用私有变量保护数据安全持久化维持数据!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body button按钮/button button按钮/button button按钮/button button按钮/button button按钮/button button按钮/button button按钮/button button按钮/button button按钮/button button按钮/button script // 需求 点击按钮获取当前按钮的下标 闭包来实现 // 核心点 代码朝着闭包的形成条件去写代码 var btns document.querySelectorAll(button); // 1. /*for (var i 0; i btns.length; i) { console.log(i); // 0 - 9 }*/ // 2. // 函数 /*for (var i 0; i btns.length; i) { function fn(){ // 循环一次执行一次fn函数打印i console.log(i); // 0 - 9 } fn(); }*/ // 3. // 函数来个局部变量 /*for (var i 0; i btns.length; i) { function fn(j){ // var j 实参 i; console.log(j); // 0 - 9 } fn(i); }*/ // 4. // 注册点击事件 函数嵌套函数 /*for (var i 0; i btns.length; i) { function fn(j){ // var j 实参 i; // console.log(j); // 0 - 9 // 每一个按钮注册click // btns[j] 每一个按钮 btns[j].onclick function () { console.log(j); } } fn(i); }*/ // 5. 简化写法 for (var i 0; i btns.length; i) { /*function fn(j){ btns[j].onclick function () { console.log(j); } } fn(i);*/ // 使用函数自调用去简化 (function (j) { // var j i; btns[j].onclick function () { console.log(j); } })(i) } // 闭包可以实现需求的原因 // for循环10次10分闭包的内存空间综合整体使用变量j存储了每次for循环的i的值。 // i 0; // 第一次循环 // i 1; // 第二次循环 /script /body /html闭包的应用计数器需求统计一个函数的调用次数var count 0; function fn(){ count; console.log(我被调用了调用次数是count); } fn(); fn(); fn();缺点count是全局变量不安全。使用闭包解决这个问题function outer(){ var count 0; // 私有变量, 将count保护起来了 function add(){ count; console.log(当前countcount); } return add; } var result outer(); result();继承现实生活中的继承子承父业, 如儿子继承了父辈的财产公司等程序中的继承一个对象可以使用另一个对象中的方法或属性继承的目的: 方便代码的复用var lw { skill: 翻墙, age: 28 } function Person(){} var xm new Person(); // 如何实现让xm可以使用到lw对象上的skill属性??? xm.skill; // 翻墙JS常见的几种继承模式原型链继承一个对象可以访问构造函数的原型中的属性和方法那么如果想要让一个对象增加某些属性和方法只需要把这些属性和方法放到原型对象中即可。这样就实现了继承, 称之为原型链继承直接给原型增加属性和方法原型替换注意constructor!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 实现继承的方式 // 1. 原型链继承实例对象可以直接去访问继承到了原型对象上的任意成员 // function Person(){ // } /*// 虽然这种写法是可以实现效果的但是添加的方法过多写法重复、麻烦 Person.prototype.sayHi function () { console.log(hi); } Person.prototype.running function () { console.log(running man); } Person.prototype.work function () { console.log(work); }*/ function Person(){} // 简化写法 原型替换 // 问题 constructor属性丢失了 // 解决方案 给新的原型对象添加constructor属性指向当前的构造函数 Person.prototype { // 手动补上的 constructor: Person, sayHi: function () { console.log(hello); }, work: function () { console.log(work); }, running: function () { console.log(running man); } } var p new Person(); // 沿着对象的原型链往上查找 // p对象的原型链 // p Person.prototype{xxxx} Object.prototype null; console.log(p.constructor); // Person /*console.log(p); p.sayHi() p.running()*/ // 小结 // 原型链继承 给原型对象添加的方法实例对象是可以直接继承到 // 写法 // 1. Person.prototype.sayHi function(){} 问题添加的方法比较多的时候写法重复 // 2. 原型替换 Person.prototype { xxx } 问题 造成了constructor属性丢失了 // 解决 手动给新的原型对象添加constructor属性 /script /body /html借用构造函数继承从构造函数中继承到构造函数中的成员function Person(name, age, gender){ this.name name; this.age age; this.gender gender; } function Chinese(name, age, gender, skin){ this.name name; this.age age; this.gender gender; // 以上代码重复在构造函数Person中已经给this添加 this.skin skin; } // 重写构造函数Chinese function Chinese(name, age, gender, skin){ // 借用Person构造函数继承到name、age、gender属性 Person.call(this, name, age, gender); this.skin skin; }!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 借用构造函数继承 function Person(name, age, gender){ this.name name; this.age age; this.gender gender; } function Chinese(name, age, gender, skin) { // 以下三个name, age, gender属性已经在构造函数Person内写过了 // 如何优化 借用构造函数Person来继承里面的属性 // 借用 call apply 作用一样区别传参 // Person.call(this, name, age, gender); Person.apply(this, [name, age, gender]); // 1. call可以调用函数Person被调用了 // Person函数内的this指向谁 // Person函数的三个形参的值是什么 // 2. Person函数内的this指向call的第一个参数, 指向了xm // 3. call除了第一个参数外其他所有的参数都是给Person函数传递实参的 /*this.name name; this.age age; this.gender gender;*/ this.skin skin; } var xm new Chinese(xm, 20, male, 黄); console.log(xm); /script /body /html组合继承借用构造函数 原型链继承组合在一起使用function Person(name, age, gender){ this.name name; this.age age; this.gender gender; } // Person原型上的sayHi方法 Person.prototype.sayHi function(){ console.log(hello, 我是 this.name); } function Chinese(name, age, gender, skin){ // 借用Person构造函数继承到name、age、gender属性 Person.call(this, name, age, gender); this.skin skin; } var xm new Chinese(xm, 20, male, 黄色); // xm有name/age/gender属性从Person构造函数中继承到的 // 那么如何让Chinese的实例对象xm去继承到Person原型上的sayHi方法??? xm.sayHi();!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 组合继承 // 1. 原型链继承 继承到Person的prototype上的方法 // 2. 借用构造函数继承 继承到Person构造函数内添加的属性 function Person(name, age, gender){ this.name name; this.age age; this.gender gender; } Person.prototype.sayHi function () { console.log(hello, 我是 this.name); } function Chinese(name, age, gender, skin) { // 借用构造函数继承 继承到name、age。gender属性 Person.apply(this, [name, age, gender]); this.skin skin; } // 原型链继承 原型替换写法 // Chinese.prototype Person.prototype; /*var p new Person(); // p 是Person的实例对象 Chinese.prototype p;*/ // 上面两行代码的简化写法 Chinese.prototype new Person();// p 是Person的实例对象 Chinese.prototype.color lime; // 本质上其实是修改了p // xm的原型链 // xm Chinese.prototype本质上实例对象p Person.prototype Object.prototype null; var xm new Chinese(xm, 20, male, 黄); console.log(xm); // 优化后的效果 // 1. xm还可以继续使用sayHi方法 // 2. 修改Chinese.prototype不会影响到Person.prototype // xm去使用sayHi方法沿着xm的原型链来找方法。 // 核心的点 让Person的prototype出现在xm的原型链上 // 把Chinese的prototype换成Person的prototype xm.sayHi(); /script /body /html类JavaScript 语言中生成实例对象的传统方法是通过构造函数构造函数的写法跟传统的面向对象语言比如 C 和 Java差异很大很容易让新学习js的程序员感到困惑。ES6 提供了更接近传统语言的写法引入了 Class类这个概念作为对象的模板。通过class关键字可以定义类。新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。ES5 创建对象function Person(name, age) { this.name name; this.age age; } Person.prototype.sayHi function () { console.log(hello, 我是 this.name); }; var p new Person(lw, 36); p.sayHi();ES6 创建对象class Person { constructor(name, age) { this.name name; this.age age; } sayHi() { console.log(hello, 我是 this.name); }; } var p new Person(lw, 36); p.sayHi();ES6-class实现继承Class 可以通过extends关键字实现继承这比 ES5 的通过修改原型链实现继承要清晰和方便很多。# 继承Person类中的sayHi方法 class Person { sayHi(){ console.log(hello); } } class Chinese extends Person {} # 继承Person类中的属性和方法 class Person { constructor(name, age, gender){ this.name name; this.age age; this.gender gender; } sayHi(){ console.log(hello); } } // 子类 class Chinese extends Person { constructor(name, age, gender, skin){ // 在子类中必须在constructor函数中首先调用super() super(name, age, gender); // 调用super之后才可以去写其他代码 this.skin skin; } } var xm new Chinese(xm, 20, male, 黄); console.log(xm); xm.sayHi();!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 继承 ES6 class类 类的继承很简单 /*function Person(){} var p new Person();*/ /*// 类的语法 class 类{} class Person{} // 通过类来创建实例对象 new 类() var p new Person(); console.log(p);*/ // 给类的实例对象添加属性 在类的内部通过constructor函数来进行添加 class Person{ constructor(name, age, gender){ this.name name; this.age age; this.gender gender; // 如此添加方法可以但是容易造成内存浪费问题 // 要添加方法需要给原型对象添加 /*this.sayHi function () { console.log(hi); }*/ } // 在类的{}里面写的方法是添加在原型对象上了 sayHi() { console.log(hello); } work(){ console.log(work save money); } } var p new Person(xm, 20, male); console.log(p); p.sayHi(); p.work(); // ES6 类 创建对象 // 定义class 类{} // 创建实例 new 类(); // 给类的实例添加属性 类的内部通过constructor函数来添加 // 给类的实例添加方法 给原型对象上添加把方法直接写在类的里面 /*class Chinese { constructor(){ // 实例添加属性 } // 给原型对象添加方法 sayHi(){//...} }*/ // 类 语法糖 // 类的本质还是构造函数 原型对象 /script /body /html!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 类的继承语法 // class 子类 extends 父类{} // 父类 class Person { constructor(name, age, gender) { this.name name; this.age age; this.gender gender; } sayHi() { console.log(hello); } } // 子类 // 子类是继承到父类上的属性和原型上的方法 class Chinese extends Person { // 处理skin属性 需要在constructor函数内来添加 /*constructor(name, age, gender, skin){ // 在子类的constructor函数中必须优先调用super(); // super函数表示的是父类的构造函数 super(name, age, gender); this.skin skin; }*/ constructor(name, age, gender, skin) { // 只要在子类中 写了constructor函数必须去做 在constructor函数内优先去调用super函数 super(name, age, gender); this.skin skin; } } // 实例化子类 var p new Chinese(xm, 20, male, 黄); console.log(p); p.sayHi(); // 小结 // 类的继承语法 class 子类 extends 父类 // 子类就已经继承到父类的属性和原型上的方法 // 子类中添加自己的属性写constructor构造函数 // 注意点 必须优先调用super函数父类的构造函数 // 然后在去添加自己的属性 /script /body /html正则表达式正则表达式用于匹配规律规则的表达式正则表达式最初是科学家对人类神经系统的工作原理的早期研究现在在编程语言中有广泛的应用经常用于表单校验高级搜索等。创建正则表达式【07-正则表达式的创建.html】构造函数的方式var regExp new RegExp(/\d/);正则字面量var regExp /\d/;正则的使用/\d/.test(aaa1);!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 创建正则表达式 // 1. 通过构造函数来创建 RegExp regular expression/ var reg new RegExp(/a/); // 正则 规律 匹配 a // test() 方法 测试字符串是否符合正则的规律, 符合返回true // 正则.test(字符串) console.log(reg.test(abc)); console.log(reg.test(bcdef)); // 2. 正则字面量写法 var reg2 /a/; console.log(reg2.test(12a3)); /script /body /html!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 正则的组成 普通字符 元字符组成的 // 普通字符: 没有实际含义写啥匹配啥 // 元字符: 在正则中是有特殊含义的 // 元字符 // 1. \d 匹配一个数字的 0-9 // 2. \D 匹配一个非数字的 // 3. \w 匹配一个单词字符 大小写字母(a-z A-Z) 数字 _ // 4. \W 匹配一个非单词字符 // 5. \s 匹配一个不可见字符 空格 换行\n 制表符 tab\t // 6. \S 匹配一个可见字符 // 7. . 匹配除了换行以外的所有字符 // 8. \. 对 . 进行转义, 就是用来匹配小数点 // \d // console.log(/\d/.test(abc)); // false // console.log(/\d/.test(123)); // true // console.log(/\d/.test(a1bc)); // true // \D // console.log(/\D/.test(abc)); // true // console.log(/\D/.test(123)); // false // console.log(/\D/.test(a1bc)); // true // // \w // console.log(/\w/.test(abc)); // true // console.log(/\w/.test(,,,,)); // false // console.log(/\w/.test($%_^*)); // true // console.log(/\w/.test(a12c)); // true // \W // console.log(/\W/.test(abc)); // false // console.log(/\W/.test(,,,,)); // true // console.log(/\W/.test($%_^*)); // true // console.log(/\W/.test(a12c)); // false // // \s // console.log(/\s/.test(ab c)); // true // console.log(/\s/.test(ab\nc)); // true // console.log(/\s/.test(ab\tc)); // true // console.log(/\s/.test(,,,,)); // false // \S // console.log(/\S/.test(ab c)); // true // console.log(/\S/.test(ab\nc)); // true // console.log(/\S/.test(ab\tc)); // true // console.log(/\S/.test(,,,,)); // true // . // console.log(/./.test(12.3)); // true // console.log(/./.test(\n)); // false // console.log(/./.test(ab\nc)); // true // \. console.log(/\./.test(12.3)); // true console.log(/\./.test(\n)); // false console.log(/\./.test(ab\nc)); // false /script /body /html!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 正则的优先级 // 1. 或 | 优先级最低 // 2. 分组 () 优先级最高 // 匹配a或b或c // console.log(/a|b|c/.test(a123)); // console.log(/a|b|c/.test(c123)); // console.log(/a|b|c/.test(1f23)); // 优先级最低 |的两边都是个单独的整体 // 匹配f 或者是 boot // console.log(/f|boot/.test(foo)); // true // console.log(/f|boot/.test(boot)); // true // console.log(/f|boot/.test(foot)); // true // console.log(/f|boot/.test(f)); // true // console.log(/f|boot/.test(oot)); // false // console.log(/f|boot/.test(boo)); //false // () 先算() 里面 () 里面结果是f 或 b // 后面组成 foot 或 boot console.log(/(f|b)oot/.test(boot)); // true console.log(/(f|b)oot/.test(foot)); // true console.log(/(f|b)oot/.test(foo)); // false console.log(/(f|b)oot/.test(f)); // false console.log(/(f|b)oot/.test(boo)); //false console.log(/(f|b)oot/.test(oot)); // false /script /body /html元字符正则表达式由一些普通字符和元字符组成普通字符包括大小写字母、数字等而元字符则具有特殊的含义。常见元字符|表示或优先级最低()优先级最高表示分组字符类的元字符[]在正则表达式中表示一个字符的位置[]里面写这个位置可以出现的字符。console.log(/[abc]/);//匹配a,b,c[^]在中扩号中的^表示非的意思。//^表示该位置不可以出现的字符 console.log(/[^abc]/);//匹配除了abc以外的其他字符[a-z][1-9]表示范围console.log(/[a-z]/.test(d));//小写字母 console.log(/[A-Z]/.test(d));//大写字母 console.log(/[0-9]/.test(8));//数字 console.log(/[a-zA-Z0-9]/);//所有的小写字母和大写字母以及数字!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 字符类元字符 [] // [] 表示一个字符 在[] 里面可以写能够出现的字符 // [] 自带或者的含义 // 在[]里面可以写- 表示范围, 范围可自定义但是注意范围不能反过来 // 在[]里面可以 ^ 表示非 // /[abc]/ 匹配a或者b或者c // /[a-z]/ 匹配a-z其中任意一个字符 // /[A-Z]/ 匹配A-Z其中任意一个字符 // /[0-9]/ 匹配0-9其中任意一个字符 // /[a-zA-Z0-9]/ 匹配a-z A-Z 0-9其中任意一个字符 // /[^abc]/ 非abc不能是abc其中任意一个 // console.log(/[abc]/.test(c12)); // console.log(/[abc]/.test(a12)); // console.log(/[abc]/.test(123b)); // console.log(/[h-z]/.test(ac)); // console.log(/[4-8]/.test(123)); // console.log(/[s-zA-Z6-9]/.test(hH3)); console.log(/[^0]/.test(0123)); // true console.log(/[^0]/.test(00)); // false console.log(/[^0]/.test(a.bcss)); // true // 小结 // [] 字符类元字符 // 1. 表示一个字符 // 2. [] 自带或者含义 // 3. [a-z] 范围 可自定义 不能反过来 // 4. [^] 非 /script /body /html边界类元字符我们前面学习的正则只要有满足的条件的就会返回true并不能做到精确的匹配。【12-正则边界.html】^表示开头[]里面的^表示取反$表示结尾console.log(/^chuan/.test(dachuan));//必须以chuan开头 console.log(/chuan$/.test(chuang));//必须以chuan结尾 console.log(/^chuan$/.test(chuan));//精确匹配chuan //精确匹配chuan,表示必须是这个 console.log(/^chuan$/.test(chuanchuan));//fasle!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 边界类元字符 // 开始 ^ [^] 非 // 结束 $ // // ^ // console.log(/^chuan/.test(chuang)); // true // console.log(/^chuan/.test(dachuan)); // false // console.log(/^chuan/.test(chuanchuan)); // true // // $ // console.log(/chuan$/.test(chuang)); // false // console.log(/chuan$/.test(dachuan)); // true // console.log(/chuan$/.test(chuanchuan)); // true // ^ 和 $一起使用 精确匹配 写啥匹配啥 // 通常用在表单校验中 console.log(/^chuan$/.test(chuang)); // false console.log(/^chuan$/.test(dachuan)); // false console.log(/^chuan$/.test(chuanchuan)); // false console.log(/^chuan$/.test(chuan)); // true /script /body /html量词类元字符量词用来控制出现的次数一般来说量词和边界会一起使用【13-正则量词.html】*表示能够出现0次或者更多次x0;表示能够出现1次或者多次x1?表示能够出现0次或者1次x0或者x1{n}表示能够出现n次{n,}表示能够出现n次或者n次以上{n,m}表示能够出现n-m次思考如何使用{}来表示*?!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 量词 // * 次数 0 {0,} // 次数 1 {1,} // ? 次数 0 | 1 {0,1} // {m} 次数 m次 // {m,} 次数 m次 // {m,n} 次数 m 到 n 包含m 和 n /*// * 0 匹配没有a或者是a只能是a不能有其他的 console.log(/^a*$/.test()); // true console.log(/^a*$/.test(a)); // true console.log(/^a*$/.test(aa)); // true console.log(/^a*$/.test(abc)); // false*/ // 1 // console.log(/^a$/.test()); // false // console.log(/^a$/.test(a)); // true // console.log(/^a$/.test(aa)); // true // console.log(/^a$/.test(abc)); // false // ? 0 | 1 // console.log(/^a?$/.test()); // true // console.log(/^a?$/.test(a)); // true // console.log(/^a?$/.test(aa)); // false // console.log(/^a?$/.test(abc)); // false // {} // 量词是就近修饰的 console.log(/^chuan{2}$/.test(chuanchuan)); // false console.log(/^(chuan){2}$/.test(chuanchuan)); // true console.log(/^chuan{2}$/.test(chuann)); // true /script /body /html正则的使用正则测试验证QQ只能是数字开头不能是0长度为5-11位var qqReg /^[1-9]\d{4,10}$/;验证手机11位数字组成号段13[0-9] 147 15[0-9] 17[0178] 18[0-9]var mobileReg /^(13[0-9]|147|15[0-9]|17[0178]|18[0-9])\d{8}$/;验证邮箱前面是字母或者数字必须有后面是字母或者数字必须有..后面是字母或者数字var emailReg /^\w\w(\.\w)$/;验证姓名只能是汉字长度2-6位之间汉字范围[\u4e00-\u9fa5]var nameReg /^[\u4e00-\u9fa5]{2,6}$/;!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 表单校验的 一定需要精确匹配 (^ $) // 验证QQ // 规律 // 不能以0开头的数字 // 5-12为长度 // 纯数字 // 正则去验证QQ // var reg /^[^0]\d{4,11}$/; // var reg /^[1-9]\d{4,11}$/; // console.log(reg.test(1587028985)); // console.log(reg.test(0587028985)); // console.log(reg.test(a587028985)); // 验证手机 // 规律 // 11位数字 // 1开头 // 第二位不能是 0 1 2 // var reg /^1[3-9]\d{9}$/; // console.log(reg.test(18868888880)); // console.log(reg.test(12868888880)); // console.log(reg.test(10868888880)); // 验证邮箱 // 规律 // litaotaoitcast.cn // 大小写字母 数字 _ 大小写字母 数字 _ . 小写字母 /*var reg /^\w\w(\.[a-z])$/; console.log(reg.test(litaotaoitcast.cn)); console.log(reg.test(litaotao163qq.cn)); console.log(reg.test(litaotao163qq.com.cn));*/ // 验证中文姓名 // 规律 // 1. 2-4位 // 2. 纯中文 汉字范围[\u4e00-\u9fa5] var reg /^[\u4e00-\u9fa5]{2,4}$/; console.log(reg.test(大飞哥)); console.log(reg.test(飞哥.约翰)); console.log(reg.test(flyman)); /script /body /html正则替换var str 123AD asadf asadfasf adf ; 1 替换掉字符串中的所有空白 2. 将所有的ad/AD替换成xx!DOCTYPE html html langen head meta charsetUTF-8 titleDocument/title /head body script // 正则替换 /*var str abc; // 字符串 replace 替换 // replace 第一个参数可以写正则表达式 // var str2 str.replace(a, x); var str2 str.replace(/a/, y); console.log(str2);*/ var str 123AD asadf asadfasf adf ; // 1 替换掉字符串中的所有空白 // 修饰符 g global 全局匹配搜索 // var str2 str.replace(/\s/g, ); // console.log(str2); // 2. 将所有的ad / AD替换成xx // var str2 str.replace(/ad|AD/g, xx); // i ignore 忽略大小写 var str2 str.replace(/ad/gi, xx); console.log(str2); // test()方法是正则的 /script /body /html