目录

一、面向对象编程介绍

1.1 两大编程思想

1.2 面向过程编程(POP)

1. 3面向对象编程(OOP)

面向对象的特性:

1.4 面向过程和面向对象的对比

二、ES6中的类和对象

面向对象

2.1 对象

对象是由属性和方法组成的:

2.2 类class

面向对象的思维特点:

2.3 创建类

2.4 类constructor构造函数

语法

创建实例:

2.5 类添加方法

语法

创建实例

三、类的继承

3.1 继承

语法

实例

3.2 super关键字

语法

super关键字调用父类普通函数

案例

语法

子类继承父类方法并扩展自己的方法

三个注意点:

四、面向对象案例

【面向对象版 tab 栏切换】

【面向对象版 tab 栏切换 添加功能】

【面向对象版 tab 栏切换 删除功能】

【 面向对象版 tab 栏切换 编辑功能】

【完整代码】

五、构造函数和原型

5.1 概述

创建对象可以通过以下三种方式:

5.2 构造函数

new 在执行时会做四件事情:

静态成员  VS  实例成员

5.3 构造函数的问题

5.4 构造函数原型prototype

5.5 对象原型 _proto_

5.6 constructor 构造函数

5.7 构造函数 、 实例、原型对象三者之间的关系

5.8 原型链

5.9 JavaScript 的成员查找机制--逐层向上找(规则)

5.10 原型对象this指向

5.11 扩展内置对象

六、继承

6.1 call()

6.2 借用构造函数继承父类属性--【Father.call(this,score,sex)】

6.3 借用原型对象继承父类型方法

注意点:

七、ES5的新增方法

7.1 ES5新增方法概述

7.2 数组方法

遍历数组:array.forEach(function(数组当前项的值,数组当前项的索引,数组对象本身))

筛选数组【返回新的数组】: array.filter(function(数组当前的值,数组当前项的索引,数组对象本身))

筛选数组【返回的是布尔值】:array. some(function(数组当前的值,数组当前项的索引,数组对象本身))

some、filter和forEach的区别

【查询商品案例】

【渲染页面数据】

【根据价格筛选商品】

【根据商品名称筛选商品】

7.3 字符串方法--trim() 【从一个字符串的两端删除空白字符,返回新的字符串】

7.4 对象方法

1.  Object.keys() 【类似于for...in】用于获取对象自身所有的属性--返回数组

2.  Object.defineProperty(目标对象,想要进行修改的属性名字,所要进行修改的属性值【是以对象的形式】) 定义对象中新属性或修改原有的属性。(了解)

八、函数的定义和调用

8.1 函数的定义方式

1. 函数声明方式 function 关键字 (命名函数)

2. 函数表达式 (匿名函数)

3. new Function()  【里面的参数都是字符串】

8.2 函数的调用方式

1. 普通函数

2. 对象的方法

3. 构造函数

4. 绑定事件函数

5. 定时器函数

6. 立即执行函数

九、this

9.1 函数内this的指向

9.2 改变函数内部this指向

call(在fun函数运行时指定的this值,传递其他参数)--(1)可以调用函数  (2)可以改变函数内的this指向

apply(在fun函数运行时指定的this值,数组【伪数组】)--(1)可以调用函数  (2)可以改变函数内的this指向

bind(在fun函数运行时指定的this值,传递其他参数)--(1)不调用函数  (2)可以改变函数内的this指向

【自定义bind函数】

9.2 call apply bind 总结

十、严格模式

10.1 什么是严格模式

10.2 开启严格模式

(1)为脚本开启严格模式---在所有语句之前放一个“use strict”;(或‘use strict’;)

(2)为函数开启严格模式---把“use strict”;  (或 'use strict'; ) 声明放在函数体所有语句之前

10.3 严格模式 中的变化

(1)变量规定

(2)严格模式下this指向问题

(3)函数变化

十一、高阶函数

十二、闭包

12.1 变量作用域

12.2 什么是闭包(被访问的函数才是闭包函数)

12.3 在 chrome 中调试闭包

12.4 闭包的作用--延伸了变量的作用范围【使用return】

12.5 闭包案例

1. 循环注册点击事件。

2. 循环中的 setTimeout()。

3. 计算打车价格。

12.6 闭包总结

十三、递归

13.1 什么是递归

13.2 利用递归求数学题

【利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..n】

【斐波那契数列】

13.3  利用递归求:根据id返回对应的数据对象

13.4 浅拷贝(只拷贝地址【所以一个修改,改变两个】)

13.5 和深拷贝(拷贝数据【所以一个修改,另一个不影响】)

十四、正则表达式

1.正则表达式概述

1.1 什么是正则表达式

1.2 正则表达式的特点

2.正则表达式在JavaScript中的使用

2.1 创建正则表达式

2.2 测试正则表达式test

3.正则表达式中的特殊字符

3.1 正则表达式的组成

3.2 边界符--如果 ^ 和 $ 在一起,表示必须是精确匹配

3.3 字符类

3.4 量词符

【案例:用户名验证】

3.4 括号总结

3.5 预定义类

【座机号码验证】

【 案例:表单验证】

4.正则表达式中的替换

4.1 replace替换(被替换的字符串,替换为的字符串)

4.2 正则表达式参数

【 案例:敏感词过滤】


一、面向对象编程介绍

1.1 两大编程思想

  • 面向对象
  • 面向过程

1.2 面向过程编程(POP)

1. 3面向对象编程(OOP)

面向对象的特性:

  1. 封装
  2. 继承
  3. 多态

1.4 面向过程和面向对象的对比

二、ES6中的类和对象

面向对象

2.1 对象

对象是由属性和方法组成的:

l属性:事物的特征,在对象中用属性来表示(常用名词)
l方法:事物的行为,在对象中用方法来表示(常用动词)
    <script>// 1. 创建类 class  创建一个 明星类class Star {constructor(uname, age) {this.uname = uname;this.age = age;}}// 2. 利用类创建对象 newvar ldh = new Star('刘德华', 18);var zxy = new Star('张学友', 20);console.log(ldh);console.log(zxy);//(1) 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写//(2) 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象//(3) constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数//(4) 生成实例 new 不能省略//(5) 最后注意语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function</script>

2.2 类class

类抽象了对象的公共部分,它泛指某一大类(class)

对象特指某一个,通过类实例化一个具体的对象  

面向对象的思维特点:

1.抽取(抽象)对象共用的属性和行为组织(封装)成一个类(模板)
2.对类进行实例化, 获取类的对象

2.3 创建类

class name {// class body
}

2.4 类constructor构造函数

constructor() 方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过 new 命令生成对象实例时,自动调用该方法。如果没有显示定义, 类内部会自动给我们创建一个constructor()  

语法

class Person {constructor(name,age) {   // constructor 构造方法或者构造函数this.name = name;this.age = age;}
}

创建实例:

var ldh = new Person('刘德华', 18);
console.log(ldh.name)

2.5 类添加方法

语法

class Person {constructor(name,age) {   // constructor 构造器或者构造函数this.name = name;this.age = age;}say() {console.log(this.name + '你好');}
}

创建实例

var ldh = new Person('刘德华', 18);
ldh.say()

注意: 方法之间不能加逗号分隔,同时方法不需要添加 function 关键字。

    <script>// 1. 创建类 class  创建一个 明星类class Star {// 类的共有属性放到 constructor 里面constructor(uname, age) {this.uname = uname;this.age = age;}sing(song) {// console.log('我唱歌');console.log(this.uname + song);}}// 2. 利用类创建对象 newvar ldh = new Star('刘德华', 18);var zxy = new Star('张学友', 20);console.log(ldh);console.log(zxy);// (1) 我们类里面所有的函数不需要写function //(2) 多个函数方法之间不需要添加逗号分隔ldh.sing('冰雨');zxy.sing('李香兰');</script>

三、类的继承

3.1 继承

语法

class Father{   // 父类
}
class  Son extends Father {  // 子类继承父类
}

实例

class Father {constructor(surname) {this.surname= surname;}say() {console.log('你的姓是' + this.surname);}
}
class Son extends Father{  // 这样子类就继承了父类的属性和方法}
var damao= new Son('刘');
damao.say();
    <script>// 1. 类的继承// class Father {//     constructor() {//     }//     money() {//         console.log(100);//     }// }// class Son extends Father {// }// var son = new Son();// son.money();class Father {constructor(x, y) {this.x = x;this.y = y;}sum() {//这个this.x和this.y是分别指向父类的console.log(this.x + this.y);}}class Son extends Father {constructor(x, y) {//如果使用下面这两句则出错   // 因为此时this.x=x是指向孩子自己的  跟父亲的sum不一样// this.x=x;// this.y=y;super(x, y); //调用了父类中的构造函数}}var son = new Son(1, 2);var son1 = new Son(11, 22);son.sum();//3son1.sum();//33</script>

3.2 super关键字

super 关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数

语法

class Person {   // 父类constructor(surname){this.surname = surname;}
}
class  Student extends Person {       // 子类继承父类constructor(surname,firstname){super(surname);             // 调用父类的constructor(surname)this.firstname = firstname; // 定义子类独有的属性}
}

 注意: 子类在构造函数中使用super, 必须放到 this 前面  (必须先调用父类的构造方法,在使用子类构造方法)

super关键字调用父类普通函数

<script>class Father {constructor() {}say() {// console.log('this is father'); xxxxxxxreturn 'this is father'}}class Son extends Father {constructor() {super()}say() {console.log(super.say() + ' this is son'); //在console代码中打印某函数的结果时,应该采用return的方式返回数据,而不应该在原函数中打印,这是错误的编程方式}}var son = new Son()son.say()// 若父类和子类含有相同的函数,则会应用就近原则,优先调用子类的函数
</script>

案例

    <script>// super 关键字调用父类普通函数class Father {say() {return '我是爸爸';}}class Son extends Father {say() {// console.log('我是儿子');console.log(super.say() + '的儿子');// super.say() 就是调用父类中的普通函数 say()}}var son = new Son();son.say();// 继承中的属性或者方法查找原则: 就近原则// 1. 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的// 2. 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)</script>

super关键字 用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数。

语法

class Father {say() {return '我是爸爸';}
}
class Son extends Father { // 这样子类就继承了父类的属性和方法say() {// super.say()  super 调用父类的方法return super.say() + '的儿子';}
}
var damao = new Son();
console.log(damao.say());

子类继承父类方法并扩展自己的方法

    <script>// 父类有加法方法class Father {constructor(x, y) {this.x = x;this.y = y;}sum() {console.log(this.x + this.y);}}// 子类继承父类加法方法 同时 扩展减法方法class Son extends Father {constructor(x, y) {// 利用super 调用父类的构造函数// super 必须在子类this之前调用super(x, y);this.x = x;this.y = y;}subtract() {console.log(this.x - this.y);}}var son = new Son(5, 3);son.subtract();son.sum();</script>

三个注意点:

  1. 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象.
  2. 类里面的共有属性和方法一定要加this使用.
  3. 类里面的this指向问题.
  4. constructor 里面的this指向实例对象, 方法里面的this 指向这个方法的调用者
<body><button>点击</button><script>var that;var _that;class Star {constructor(uname, age) {// constructor 里面的this 指向的是 创建的实例对象that = this;console.log(this);this.uname = uname;this.age = age;// this.sing();this.btn = document.querySelector('button');this.btn.onclick = this.sing;}sing() {// 这个sing方法里面的this 指向的是 btn 这个按钮,因为这个按钮调用了这个函数console.log(this);//undefined---【btn】//上面是---that(全局变量) = this;   所以存储的是constructor中的内容console.log(that.uname); // that里面存储的是constructor里面的this}dance() {// 这个dance里面的this 指向的是实例对象 ldh 因为ldh 调用了这个函数_that = this;console.log(this);}}var ldh = new Star('刘德华');console.log(that === ldh);//trueldh.dance();console.log(_that === ldh);//true// 1. 在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象// 2. 类里面的共有的属性和方法一定要加this使用.</script>
</body>

四、面向对象案例

面向对象版 tab 栏切换】

【面向对象版 tab 栏切换 添加功能】

    //1.切换功能toggleTab(){//切换时候 要将前一个删除样式// this.clearClass();//错误 因为此时this是指向lis[i]  应该要指向调用的对象that.clearClass();// console.log(this.index);//这里的this指的是lis[i]//点击的时候 给“测试”下面除去短横线this.className='liactive';//这里的this指的是lis[i]//点击“测试”切换下面的文本框//在constructor里面才有这个属性--所以声明一个全局变量// this.sections[this.index].className='conactive';//报错 因为lis[i]里面没有section这个属性that.sections[this.index].className='conactive';}//2.添加功能addTab(){//在添加之前要先将其他的删除that.clearClass();// alert('111')var random=Math.random();//(1)创建li元素和section元素var li='<li class="liactive"><span>测试'+ random +'</span><span class="iconfont icon-guanbi"></span></li>';var section='<section class="conactive">测试'+random+'</section>';//(2)把这两个元素追加到对应的父元素里面// insertAdjacentHTML  可以直接将字符串放入//beforeend--在父元素的最后追加// this.ul.insertAdjacentHTML('beforeend',li);//错误 因为调用addTab是【this.add.onclick=this.addTab;】 所以要换成实例对象that.ul.insertAdjacentHTML('beforeend', li);that.fsection.insertAdjacentHTML('beforeend', section);//因为新添加选项 所以要重新初始化一下(重新获取一下新的li和section)that.init();}

面向对象版 tab 栏切换 删除功能】

    //3.删除功能removeTab(e){//因为删除按钮的时候 下面的横线总是跟着跑// 阻止冒泡 防止触发li 的切换点击事件e.stopPropagation(); //先获取索引号 但是自己没有 只能通过父亲(lis)获取var index=this.parentNode.index;console.log(index);//根据索引号删除对应的li 和 section  remove()方法可以直接删除指定的元素that.lis[index].remove();that.sections[index].remove();that.init();//当我们删除的不是原来选中状态的li  原来的选中状态的li不变if(document.querySelector('.liactive'))return;//当我们删除选中状态的这个li 的时候 ,让它的前一个小li 处于选定状态(等价于让前一个小li处于点击状态)index--;//手动调用我们的点击事件 不需要鼠标触发//&& 如果 that.lis[index]==true 才执行&&后面的【使用if判断也是可以的】that.lis[index] && that.lis[index].click();}

【 面向对象版 tab 栏切换 编辑功能】

    //4.修改功能editTab(){//先获取原来文本框中的内容var str=this.innerHTML;//this--指向span// alert('111')//双击禁止选中文字window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();//双击后 获取一个文本框this.innerHTML = '<input type="text" />';//拿到input文本框var input=this.children[0];//将原来文本框中的内容添加进来input.value=str;input.select();//文本框里面的文字处于选定状态//当我们离开(onblur)文本框就把文本款里面的值给spaninput.onbulr=function(){//this.innerHTML中的this是指向input 但是input的父亲才是span 所以是this.parentNodethis.parentNode.innerHTML=this.value;};//按下回车也可以将文本框里面的值给spaninput.onkeyup=function(e){//判断按下的是否是回车键if(e.keyCode===13){//e.key=='Enter'//手动调用表单失去焦点事件  不需要鼠标离开操作this.blur();//等价于   this.parentNode.innerHTML=this.value}}}

 【完整代码】

//声明一个全局变量 记录constructor的this
var that;//创建一个Tab对象
class Tab{constructor(id){//获取元素that=this;this.main=document.querySelector(id);//添加按钮this.add=this.main.querySelector('.tabadd');//li的父元素---firstnav中的第一个ul// li的父元素this.ul = this.main.querySelector('.fisrstnav ul:first-child');// section 父元素this.fsection = this.main.querySelector('.tabscon');//因为要页面打开自动 所以最好在constuctor里面调用init()//因为当创建一个实例对象的时候 自动调用constructor//记得加上thisthis.init();}//初始化 当打开页面的时候 自动添加相关的功能init(){//获取所有的li和sectionthis.updateNode();//init初始化操作让相关的元素绑定事件//添加功能this.add.onclick=this.addTab;for(var i=0;i<this.lis.length;i++){//添加一个自定义属性 index记住索引号this.lis[i].index=i;//给每一个lis添加点击事件// this.lis[i].onclick=function(){//     console.log(this.index);// }//记得这里不用toggleTab() 因为是点击后才调用this.lis[i].onclick=this.toggleTab;//点击删除按钮的时候 实现删除功能//要先获取要删除的索引号this.remove[i].onclick = this.removeTab;//给每一个文本框添加点击事件//要双击才出现文本框  所以是ondblclickthis.spans[i].ondblclick = this.editTab;//编辑下面的文本框this.sections[i].ondblclick = this.editTab;}}//获取所有的小li 和  section//因为上面添加功能的时候 点击“测试”下面的横线不切换 是因为前面获取的li和后面的不一样updateNode(){//分别获取上面的标题和下面文本框中的内容this.lis=this.main.querySelectorAll('li');//记得是this.mainthis.sections=this.main.querySelectorAll('section');//获取删除按钮this.remove = this.main.querySelectorAll('.icon-guanbi');//获取文本框this.spans = this.main.querySelectorAll('.fisrstnav li span:first-child');}//1.切换功能toggleTab(){//切换时候 要将前一个删除样式// this.clearClass();//错误 因为此时this是指向lis[i]  应该要指向调用的对象that.clearClass();// console.log(this.index);//这里的this指的是lis[i]//点击的时候 给“测试”下面除去短横线this.className='liactive';//这里的this指的是lis[i]//点击“测试”切换下面的文本框//在constructor里面才有这个属性--所以声明一个全局变量// this.sections[this.index].className='conactive';//报错 因为lis[i]里面没有section这个属性that.sections[this.index].className='conactive';}//清除样式clearClass(){for(var i=0;i<this.lis.length;i++){this.lis[i].className='';this.lis[i].sections='';}}//2.添加功能addTab(){//在添加之前要先将其他的删除that.clearClass();// alert('111')var random=Math.random();//(1)创建li元素和section元素var li='<li class="liactive"><span>测试'+ random +'</span><span class="iconfont icon-guanbi"></span></li>';var section='<section class="conactive">测试'+random+'</section>';//(2)把这两个元素追加到对应的父元素里面// insertAdjacentHTML  可以直接将字符串放入//beforeend--在父元素的最后追加// this.ul.insertAdjacentHTML('beforeend',li);//错误 因为调用addTab是【this.add.onclick=this.addTab;】 所以要换成实例对象that.ul.insertAdjacentHTML('beforeend', li);that.fsection.insertAdjacentHTML('beforeend', section);//因为新添加选项 所以要重新初始化一下(重新获取一下新的li和section)that.init();}//3.删除功能removeTab(e){//因为删除按钮的时候 下面的横线总是跟着跑// 阻止冒泡 防止触发li 的切换点击事件e.stopPropagation(); //先获取索引号 但是自己没有 只能通过父亲(lis)获取var index=this.parentNode.index;console.log(index);//根据索引号删除对应的li 和 section  remove()方法可以直接删除指定的元素that.lis[index].remove();that.sections[index].remove();that.init();//当我们删除的不是原来选中状态的li  原来的选中状态的li不变if(document.querySelector('.liactive'))return;//当我们删除选中状态的这个li 的时候 ,让它的前一个小li 处于选定状态(等价于让前一个小li处于点击状态)index--;//手动调用我们的点击事件 不需要鼠标触发//&& 如果 that.lis[index]==true 才执行&&后面的【使用if判断也是可以的】that.lis[index] && that.lis[index].click();}//4.修改功能editTab(){//先获取原来文本框中的内容var str=this.innerHTML;//this--指向span// alert('111')//双击禁止选中文字window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();//双击后 获取一个文本框this.innerHTML = '<input type="text" />';//拿到input文本框var input=this.children[0];//将原来文本框中的内容添加进来input.value=str;input.select();//文本框里面的文字处于选定状态//当我们离开(onblur)文本框就把文本款里面的值给spaninput.onbulr=function(){//this.innerHTML中的this是指向input 但是input的父亲才是span 所以是this.parentNodethis.parentNode.innerHTML=this.value;};//按下回车也可以将文本框里面的值给spaninput.onkeyup=function(e){//判断按下的是否是回车键if(e.keyCode===13){//e.key=='Enter'//手动调用表单失去焦点事件  不需要鼠标离开操作this.blur();//等价于   this.parentNode.innerHTML=this.value}}}}new Tab('#tab');

五、构造函数和原型

5.1 概述

创建对象可以通过以下三种方式:

1. 对象字面量

2. new Object()

3. 自定义构造函数

    <script>// 1. 利用 new Object() 创建对象var obj1 = new Object();// 2. 利用 对象字面量创建对象var obj2 = {};// 3. 利用构造函数创建对象function Star(uname, age) {this.uname = uname;this.age = age;this.sing = function() {console.log('我会唱歌');}}var ldh = new Star('刘德华', 18);var zxy = new Star('张学友', 19);console.log(ldh);ldh.sing();zxy.sing();</script>

5.2 构造函数

new 在执行时会做四件事情

①在内存中创建一个新的空对象。
②让 this 指向这个新的对象。
③执行构造函数里面的代码,给这个新对象添加属性和方法。
④返回这个新对象(所以构造函数里面不需要 return )。

静态成员  VS  实例成员

    <script>// 构造函数中的属性和方法我们称为成员, 成员可以添加function Star(uname, age) {this.uname = uname;this.age = age;this.sing = function() {console.log('我会唱歌');}}var ldh = new Star('刘德华', 18);// 1.实例成员就是构造函数内部通过this添加的成员 uname age sing 就是实例成员// 实例成员只能通过实例化的对象来访问console.log(ldh.uname);ldh.sing();// console.log(Star.uname); // 错误--不可以通过构造函数来访问实例成员// 2. 静态成员 在构造函数本身上添加的成员  sex 就是静态成员Star.sex = '男';// 静态成员只能通过构造函数来访问console.log(Star.sex);console.log(ldh.sex); // 错误---不能通过对象来访问</script>

5.3 构造函数的问题

5.4 构造函数原型prototype

    <script>// 1. 构造函数的问题. function Star(uname, age) {this.uname = uname;this.age = age;this.sing = function() {console.log('我会唱歌');}}var ldh = new Star('刘德华', 18);var zxy = new Star('张学友', 19);//两者的地址不一样console.log(ldh.sing === zxy.sing);//false//在原型对象上追加方法【这个方法是共用的】Star.prototype.dance = function() {console.log('我会唱歌');}// console.dir(Star);//prototype--原型对象console.log(ldh.dance=== zxy.dance);//trueldh.sing();zxy.sing();// 2. 一般情况下,我们的公共属性定义到构造函数里面, 公共的方法我们放到原型对象身上</script>

5.5 对象原型 _proto_

对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 __proto__ 原型的存在。

l__proto__对象原型和原型对象 prototype 是等价的
l__proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象 prototype

    <script>function Star(uname, age) {this.uname = uname;this.age = age;}Star.prototype.sing = function() {console.log('我会唱歌');}var ldh = new Star('刘德华', 18);var zxy = new Star('张学友', 19);ldh.sing();console.log(ldh); // 对象身上系统自己添加一个 __proto__ 指向我们构造函数的原型对象 prototypeconsole.log(ldh.__proto__ === Star.prototype);//true// 方法的查找规则: 首先先看ldh 对象身上是否有 sing 方法,如果有就执行这个对象上的sing// 如果么有sing 这个方法,因为有__proto__ 的存在,就去构造函数原型对象prototype身上去查找sing这个方法</script>

5.6 constructor 构造函数

对象原型( __proto__)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。

constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。

一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor  就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。

    <script>function Star(uname, age) {this.uname = uname;this.age = age;}// 很多情况下,我们需要手动的利用constructor 这个属性指回 原来的构造函数// Star.prototype.sing = function() {//     console.log('我会唱歌');// };// Star.prototype.movie = function() {//     console.log('我会演电影');// }//如果要进行添加的太多 可以使用添加对象来实现Star.prototype = {//因为如果直接这样写 会将原来的constrcuor给覆盖了 所以要写上constructor// 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数constructor: Star,sing: function() {console.log('我会唱歌');},movie: function() {console.log('我会演电影');}}var ldh = new Star('刘德华', 18);var zxy = new Star('张学友', 19);console.log(Star.prototype);console.log(ldh.__proto__);// constructor  主要记录该对象引用哪一个构造函数console.log(Star.prototype.constructor);console.log(ldh.__proto__.constructor);</script>

5.7 构造函数 、 实例、原型对象三者之间的关系

5.8 原型链

    <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);console.log(Star.prototype.__proto__ === Object.prototype);//true// 2.我们Star原型对象里面的__proto__原型指向的是 Object.prototypeconsole.log(Object.prototype.__proto__);//nuill// 3. 我们Object.prototype原型对象里面的__proto__原型  指向为 null</script>

5.9 JavaScript 的成员查找机制--逐层向上找(规则)

    <script>//原型链成员查找规则:如果在实例对象(ldh)上查找不到 则到原型对象(Star)上找 找不到到Object上找  在没有就输出undefinedfunction Star(uname, age) {this.uname = uname;this.age = age;}Star.prototype.sing = function() {console.log('我会唱歌');}Star.prototype.sex = '女';// Object.prototype.sex = '男';var ldh = new Star('刘德华', 18);ldh.sex = '男';console.log(ldh.sex);console.log(Object.prototype);//有toString方法console.log(ldh);//没有toString方法console.log(Star.prototype);//没有toString方法console.log(ldh.toString());//可以继承Object的toString方法</script>

5.10 原型对象this指向

 原型对象里面放的是方法,  这个方法里面的this 指向的是 这个方法的调用者, 也就是这个实例对象.

    <script>function Star(uname, age) {this.uname = uname;this.age = age;}var that;Star.prototype.sing = function() {console.log('我会唱歌');that = this;}var ldh = new Star('刘德华', 18);// 1. 在构造函数中,里面this指向的是对象实例 ldhldh.sing();console.log(that === ldh);//true// 2.原型对象函数里面的this 指向的是 实例对象 ldh</script>

5.11 扩展内置对象

可以通过原型对象,对原来的内置对象进行扩展自定义的方法。比如给数组增加自定义求偶数和的功能。

注意:数组和字符串内置对象不能给原型对象覆盖操作 Array.prototype = {} ,只能是 Array.prototype.xxx = function(){} 的方式

    <script>// 原型对象的应用 扩展内置对象方法Array.prototype.sum = function() {var sum = 0;for (var i = 0; i < this.length; i++) {//this--指向实例对象sum += this[i];}return sum;};//数组和字符串内置对象不能给原型对象覆盖操作 Array.prototype = {} ,// 只能是 Array.prototype.xxx = function(){} 的方式//如果采用数组的方式对原型进行操作 则会将原来的原型里面的操作进行覆盖了// 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];//等价于   var arr1 = new Array(11, 22, 33);console.log(arr.sum());console.log(Array.prototype);//里面包含sum()var arr1 = new Array(11, 22, 33);console.log(arr1.sum());</script>

六、继承

E S6之前并没有给我们提供 extends 继承。我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承

6.1 call()

调用这个函数, 并且修改函数运行时的 this 指向  

fun.call(当前调用函数 this 的指向对象,普通参数, 普通参数, ...)

    <script>// call 方法function fn(x, y) {console.log('我想喝手磨咖啡');console.log(this);//windowconsole.log(x + y);}//创建一个对象  要让上面的this指向o这个对象var o = {name: 'andy'};// fn();// 1. call() 可以调用函数// fn.call();// 2. call() 可以改变这个函数的this指向 此时这个函数的this 就指向了o这个对象fn.call(o);//指向了ofn.call(o, 1, 2);</script>

6.2 借用构造函数继承父类属性--【Father.call(this,score,sex)】

    <script>// 借用父构造函数继承属性// 1. 父构造函数function Father(uname, age) {// this 指向父构造函数的对象实例this.uname = uname;this.age = age;}// 2 .子构造函数 function Son(uname, age, score) {// this 指向子构造函数的对象实例//将父构造函数调用进来 让将父构造函数的this修改为子构造函数的this// Father.call(this);Father.call(this, uname, age);this.score = score;//自己的属性}var son = new Son('刘德华', 18, 100);console.log(son);</script>

6.3 借用原型对象继承父类型方法

    <script>// 借用父构造函数继承属性// 1. 父构造函数function Father(uname, age) {// this 指向父构造函数的对象实例this.uname = uname;this.age = age;}//父原型对象的原型Father.prototype.money = function() {console.log(100000);};// 2 .子构造函数 function Son(uname, age, score) {// this 指向子构造函数的对象实例Father.call(this, uname, age);//这个只是使用了父构造函数 并没有继承原型对象this.score = score;}// Son.prototype = Father.prototype;  这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化Son.prototype = new Father();//创建一个实例对象  此时子原型对象指向的是Father// 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数Son.prototype.constructor = Son;// 这个是子构造函数专门的方法Son.prototype.exam = function() {console.log('孩子要考试');}var son = new Son('刘德华', 18, 100);console.log(son);console.log(Father.prototype);console.log(Son.prototype.constructor);</script>

注意点:

1. class本质还是function.

2. 类的所有方法都定义在类的prototype属性上

3. 类创建的实例,里面也有__proto__ 指向类的prototype原型对象

4.所以ES6的类它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

5.所以ES6的类其实就是语法糖.

6. 语法糖:语法糖就是一种便捷写法.   简单理解, 有两种方法可以实现同样的功能, 但是一种写法更加清晰、方便,那么这个方法就是语法糖

    <script>// ES6 之前通过 构造函数+ 原型实现面向对象 编程// (1) 构造函数有原型对象prototype // (2) 构造函数原型对象prototype 里面有constructor 指向构造函数本身// (3) 构造函数可以通过原型对象添加方法// (4) 构造函数创建的实例对象有__proto__ 原型指向 构造函数的原型对象// ES6 通过 类 实现面向对象编程 class Star {}console.log(typeof Star);//function// 1. 类的本质其实还是一个函数 我们也可以简单的认为 类就是 构造函数的另外一种写法// (1) 类有原型对象prototype console.log(Star.prototype);//类的原型对象// (2) 类原型对象prototype 里面有constructor 指向类本身console.log(Star.prototype.constructor);// (3)类可以通过原型对象添加方法Star.prototype.sing = function() {console.log('冰雨');}var ldh = new Star();console.dir(ldh);// (4) 类创建的实例对象有__proto__ 原型指向 类的原型对象console.log(ldh.__proto__ === Star.prototype);//truei = i + 1;i++</script>

七、ES5的新增方法

7.1 ES5新增方法概述

7.2 数组方法

 迭代(遍历)方法:forEach()、map()、filter()、some()、every();

遍历数组:array.forEach(function(数组当前项的值,数组当前项的索引,数组对象本身))

array.forEach(function(currentValue, index, arr))

    <script>// forEach 迭代(遍历) 数组var arr = [1, 2, 3];var sum = 0;arr.forEach(function(value, index, array) {console.log('每个数组元素' + value);console.log('每个数组元素的索引号' + index);console.log('数组本身' + array);sum += value;})console.log(sum);//6</script>

筛选数组【返回新的数组】: array.filter(function(数组当前的值,数组当前项的索引,数组对象本身))

array.filter(function(currentValue, index, arr))

    <script>// filter 筛选数组var arr = [12, 66, 4, 88, 3, 7];var newArr = arr.filter(function(value, index) {// return value >= 20;return value % 2 === 0;});console.log(newArr);</script>

筛选数组【返回的是布尔值】:array. some(function(数组当前的值,数组当前项的索引,数组对象本身))

array.some(function(currentValue, index, arr))

    <script>// some 查找数组中是否有满足条件的元素 // var arr = [10, 30, 4];// var flag = arr.some(function(value) {//     // return value >= 20;//     return value < 3;// });// console.log(flag);//falsevar arr1 = ['red', 'pink', 'blue'];var flag1 = arr1.some(function(value) {return value == 'pink';});console.log(flag1);//true// 1. filter 也是查找满足条件的元素 返回的是一个数组 而且是把所有满足条件的元素返回回来// 2. some 也是查找满足条件的元素是否存在  返回的是一个布尔值 如果查找到第一个满足条件的元素就终止循环</script>

some、filter和forEach的区别

在forEach 里面 return 不会终止迭代

在some 里面 遇到 return true 就是终止遍历 迭代效率更高

filter 里面 return 不会终止迭代

    <script>var arr = ['red', 'green', 'blue', 'pink'];// 1. forEach迭代 遍历// arr.forEach(function(value) {//     if (value == 'green') {//         console.log('找到了该元素');//         return true; // 在forEach 里面 return 不会终止迭代//     }//     console.log(11);// })// 如果查询数组中唯一的元素, 用some方法更合适,arr.some(function(value) {if (value == 'green') {console.log('找到了该元素');return true; //  在some 里面 遇到 return true 就是终止遍历 迭代效率更高}console.log(11);});// arr.filter(function(value) {//     if (value == 'green') {//         console.log('找到了该元素');//         return true; //  // filter 里面 return 不会终止迭代//     }//     console.log(11);// });</script>

查询商品案例】

【渲染页面数据】

    <script>// 利用新增数组方法操作数据var data = [{id: 1,pname: '小米',price: 3999}, {id: 2,pname: 'oppo',price: 999}, {id: 3,pname: '荣耀',price: 1299}, {id: 4,pname: '华为',price: 1999}, ];// 1. 获取相应的元素var tbody = document.querySelector('tbody');// 2. 把数据渲染到页面中data.forEach(function(value) {// console.log(value);var tr = document.createElement('tr');tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>';tbody.appendChild(tr);});</script>

【根据价格筛选商品】

    <script>// 利用新增数组方法操作数据var data = [{id: 1,pname: '小米',price: 3999}, {id: 2,pname: 'oppo',price: 999}, {id: 3,pname: '荣耀',price: 1299}, {id: 4,pname: '华为',price: 1999}, ];// 1. 获取相应的元素var tbody = document.querySelector('tbody');//获取点击按钮var search_price=document.querySelector('.search-price');//获取左右两个表单var start=document.querySelector('.start');var end=document.querySelector('.end');//当第一次进入页面的时候 也要有数据setDate(data);// 2. 把数据渲染到页面中function setDate(mydata){//先清空tbody里面的数据tbody.innerHTML = '';mydata.forEach(function(value) {// console.log(value);var tr = document.createElement('tr');tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>';tbody.appendChild(tr);});}//3.根据价格查询商品//当我们点击了按钮 就可以根据我们的商品价格区筛选数组里面的对象search_price.addEventListener('click',function(){var newDate=data.filter(function(value){return value.price>=start.value && value.price<=end.value;});console.log(newDate);//把筛选完之后的对象渲染到页面中setDate(newDate);})</script>

【根据商品名称筛选商品】

<body><div class="search">按照价格查询: <input type="text" class="start"> - <input type="text" class="end"> <button class="search-price">搜索</button> 按照商品名称查询: <input type="text" class="product"> <button class="search-pro">查询</button></div><table><thead><tr><th>id</th><th>产品名称</th><th>价格</th></tr></thead><tbody></tbody></table><script>// 利用新增数组方法操作数据var data = [{id: 1,pname: '小米',price: 3999}, {id: 2,pname: 'oppo',price: 999}, {id: 3,pname: '荣耀',price: 1299}, {id: 4,pname: '华为',price: 1999}, ];// 1. 获取相应的元素var tbody = document.querySelector('tbody');//获取点击按钮var search_price=document.querySelector('.search-price');//获取左右两个表单var start=document.querySelector('.start');var end=document.querySelector('.end');//获取商品名称的表单var product=document.querySelector('.product');var search_pro=document.querySelector('.search-pro');//当第一次进入页面的时候 也要有数据setDate(data);// 2. 把数据渲染到页面中function setDate(mydata){//先清空tbody里面的数据tbody.innerHTML = '';mydata.forEach(function(value) {// console.log(value);var tr = document.createElement('tr');tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>';tbody.appendChild(tr);});}//3.根据价格查询商品//当我们点击了按钮 就可以根据我们的商品价格区筛选数组里面的对象search_price.addEventListener('click',function(){var newDate=data.filter(function(value){return value.price>=start.value && value.price<=end.value;});console.log(newDate);//把筛选完之后的对象渲染到页面中setDate(newDate);});//4.根据商品名称查找商品//如果查询数组中唯一的元素 用some方法更合适(返回的是布尔值)  因为它找到这个元素 就不再进行循环 效率更高search_pro.addEventListener('click',function(){//创建一个新的数组 用于存放新产生的数据var arr=[];data.some(function(value){if(value.pname===product.value){arr.push(value);//如果符号条件 则将数值存放入数组中return true;//return 后面必须写true}});//把拿到的数据渲染到页面中setDate(arr);})</script>
</body>

7.3 字符串方法--trim() 从一个字符串的两端删除空白字符,返回新的字符串】

str.trim()

trim() 方法并不影响原字符串本身,它返回的是一个新的字符串。

<body><input type="text"> <button>点击</button><div></div><script>// trim 方法去除字符串两侧空格var str = '   an  dy   ';console.log(str);//   an  dy   var str1 = str.trim();console.log(str1);//an dyvar input = document.querySelector('input');var btn = document.querySelector('button');var div = document.querySelector('div');btn.onclick = function() {var str = input.value.trim();if (str === '') {//input.calue.trim()===''alert('请输入内容');} else {console.log(str);console.log(str.length);div.innerHTML = str;}}</script>
</body>

7.4 对象方法

1.  Object.keys() 【类似于for...in】用于获取对象自身所有的属性--返回数组

    <script>// 用于获取对象自身所有的属性--返回数组var obj = {id: 1,pname: '小米',price: 1999,num: 2000};var arr = Object.keys(obj);console.log(arr);arr.forEach(function(value) {console.log(value);})</script>

2.  Object.defineProperty(目标对象,想要进行修改的属性名字,所要进行修改的属性值【是以对象的形式】) 定义对象中新属性或修改原有的属性。(了解)

    <script>// Object.defineProperty() 定义新属性或修改原有的属性var obj = {id: 1,pname: '小米',price: 1999};// 1. 以前的对象添加和修改属性的方式// obj.num = 1000;// obj.price = 99;// console.log(obj);// 2. Object.defineProperty() 定义新属性或修改原有的属性Object.defineProperty(obj, 'num', {value: 1000,enumerable: true});console.log(obj);Object.defineProperty(obj, 'price', {value: 9.9});console.log(obj);Object.defineProperty(obj, 'id', {// 如果值为false 不允许修改这个属性值 默认值也是falsewritable: false,});obj.id = 2;//不能被修改【上面writable: false,】console.log(obj);Object.defineProperty(obj, 'address', {value: '中国山东蓝翔技校xx单元',// 如果只为false 不允许修改这个属性值 默认值也是falsewritable: false,// enumerable 如果值为false 则不允许遍历, 默认的值是 falseenumerable: false,// configurable 如果为false 则不允许删除这个属性 不允许在修改第三个参数里面的特性 默认为falseconfigurable: false});console.log(obj);console.log(Object.keys(obj));delete obj.address;//不能被删除console.log(obj);delete obj.pname;console.log(obj);//上面configurable: false 已经被声明不能被修改Object.defineProperty(obj, 'address', {value: '中国山东蓝翔技校xx单元',// 如果值为false 不允许修改这个属性值 默认值也是falsewritable: true,// enumerable 如果值为false 则不允许遍历, 默认的值是 falseenumerable: true,// configurable 如果为false 则不允许删除这个属性 默认为falseconfigurable: true});console.log(obj.address);//错误</script>

八、函数的定义和调用

8.1 函数的定义方式

1. 函数声明方式 function 关键字 (命名函数)

2. 函数表达式 (匿名函数)

3. new Function()  【里面的参数都是字符串】

var fn = new Function('参数1','参数2'..., '函数体')

    <script>//  函数的定义方式// 1. 自定义函数(命名函数) function fn() {};// 2. 函数表达式 (匿名函数)var fun = function() {};// 3. 利用 new Function('参数1','参数2', '函数体');var f = new Function('a', 'b', 'console.log(a + b)');f(1, 2);// 4. 所有函数都是 Function 的实例(对象)console.dir(f);// 5. 函数也属于对象console.log(f instanceof Object);//true</script>

8.2 函数的调用方式

1. 普通函数

2. 对象的方法

3. 构造函数

4. 绑定事件函数

5. 定时器函数

6. 立即执行函数

    <script>// 函数的调用方式// 1. 普通函数function fn() {console.log('人生的巅峰');}// fn();   fn.call()// 2. 对象的方法var o = {sayHi: function() {console.log('人生的巅峰');}}o.sayHi();// 3. 构造函数function Star() {};new Star();// 4. 绑定事件函数btn.onclick = function() {};   // 点击了按钮就可以调用这个函数// 5. 定时器函数setInterval(function() {}, 1000);  //这个函数是定时器自动1秒钟调用一次// 6. 立即执行函数  ()()(function() {console.log('人生的巅峰');})();// 立即执行函数是自动调用</script>

九、this

9.1 函数内this的指向

这些 this 的指向,是当我们调用函数的时候确定的。 调用方式的不同决定了this 的指向不同

一般指向我们的调用者.

<body><button>点击</button><script>// 函数的不同调用方式决定了this 的指向不同// 1. 普通函数 this 指向windowfunction fn() {console.log('普通函数的this' + this);}window.fn();//window// 2. 对象的方法 this指向的是对象 ovar o = {sayHi: function() {console.log('对象方法的this:' + this);}}o.sayHi();//o// 3. 构造函数 this 指向 ldh 这个实例对象 原型对象里面的this 指向的也是 ldh这个实例对象function Star() {};Star.prototype.sing = function() {}var ldh = new Star();// 4. 绑定事件函数 this 指向的是函数的调用者 btn这个按钮对象var btn = document.querySelector('button');btn.onclick = function() {console.log('绑定时间函数的this:' + this);};// 5. 定时器函数 this 指向的也是windowwindow.setTimeout(function() {console.log('定时器的this:' + this);}, 1000);// 6. 立即执行函数 this还是指向window(function() {console.log('立即执行函数的this' + this);})();</script>
</body>

9.2 改变函数内部this指向

call(在fun函数运行时指定的this值,传递其他参数)--(1)可以调用函数  (2)可以改变函数内的this指向

    <script>// 改变函数内this指向  js提供了三种方法  call()  apply()  bind()// 1. call()var o = {name: 'andy'}function fn(a, b) {console.log(this);console.log(a + b);};fn.call(o, 1, 2);// call 第一个可以调用函数 第二个可以改变函数内的this 指向// call 的主要作用可以实现继承function Father(uname, age, sex) {this.uname = uname;this.age = age;this.sex = sex;}function Son(uname, age, sex) {//修改Son中的thisFather.call(this, uname, age, sex);}var son = new Son('刘德华', 18, '男');console.log(son);</script>

apply(在fun函数运行时指定的this值,数组【伪数组】)--(1)可以调用函数  (2)可以改变函数内的this指向

    <script>// 改变函数内this指向  js提供了三种方法  call()  apply()  bind()// 2. apply()  应用 运用的意思var o = {name: 'andy'};function fn(arr) {console.log(this);console.log(arr); // 'pink'};fn.apply(o);//将fn中的this修改为ofn.apply(o, ['pink']);// 1. 也是调用函数 第二个可以改变函数内部的this指向// 2. 但是他的参数必须是数组(伪数组)// 3. apply 的主要应用 比如说我们可以利用 apply 借助于数学内置对象求数组最大值 // Math.max();var arr = [1, 66, 3, 99, 4];var arr1 = ['red', 'pink'];// var max = Math.max.apply(null, arr);//null---表示不需要修改对象var max = Math.max.apply(Math, arr);var min = Math.min.apply(Math, arr);console.log(max, min);</script>

bind(在fun函数运行时指定的this值,传递其他参数)--(1)不调用函数  (2)可以改变函数内的this指向

<body><button>点击</button><button>点击</button><button>点击</button><script>// 改变函数内this指向  js提供了三种方法  call()  apply()  bind()// 3. bind()  绑定 捆绑的意思var o = {name: 'andy'};function fn(a, b) {console.log(this);console.log(a + b);};fn.bind(o);//只是绑定 不会调用var f = fn.bind(o, 1, 2);f();// 1. 不会调用原来的函数   可以改变原来函数内部的this 指向// 2. 返回的是原函数改变this之后产生的新函数// 3. 如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind// 4. 我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮// var btns = document.querySelectorAll('button');// for (var i = 0; i < btns.length; i++) {//     btns[i].onclick = function() {//         //禁用按钮//         this.disabled = true;//此时this指向btn//         setTimeout(function() {//             // this.disabled = false;//此时this指向window//             btn.disabled=false;//         }, 2000);//     }// }// var btn1 = document.querySelector('button');// btn1.onclick = function() {//     this.disabled = true; // 这个this 指向的是 btn 这个按钮//     // var that = this;//     setTimeout(function() {//         // that.disabled = false; // 定时器函数里面的this 指向的是window//         this.disabled = false; // 此时定时器函数里面的this 指向的是btn//     }.bind(this), 3000); // 这个this 指向的是btn1 这个对象// }var btns = document.querySelectorAll('button');for (var i = 0; i < btns.length; i++) {btns[i].onclick = function() {//禁用按钮this.disabled = true;//此时this指向btnsetTimeout(function() {this.disabled = false;}, bind(this),2000);//如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind}}</script>
</body>

【自定义bind函数】

Function.prototype.bind2 = function () {var that = this;// 获取一个参数var context = [].shift.call(arguments);// 获取后面的参数var args = [].slice.call(arguments);return function () {that.apply(context, args);};
};
var name = "liu";
var o = {name: "xiao",
};
function fn() {console.log(this.name);
}
var fn2 = fn.bind2(o);
fn2(); //liu

9.2 call apply bind 总结

call,apply,bind相同点:
都能改变函数中this的指向不同点:
1.call和bind传递的参数是arg1,arg2的形式,而apply传递的是数组的形式
2.call和apply会立即调用函数,而bind不会调用函数,只会返回一个新的函数实际应用场景:
call:实现属性的继承
apply:常跟数组有关系,可以借助数学对象Math查找数组的最大值最小值
bind:
应用1:单纯想改变this指向的情况。比如改变定时器中this的指向
应用2:绑定点击事件,通过传递参数将全局变量window传入到函数内部

十、严格模式

10.1 什么是严格模式

10.2 开启严格模式

严格模式可以应用到整个脚本或个别函数中。因此在使用时,我们可以将严格模式分为为脚本开启严格模式和为函数开启严格模式两种情况。

(1)为脚本开启严格模式---在所有语句之前放一个“use strict”;(或‘use strict’;)

    <!-- 为整个脚本(script标签)开启严格模式 --><script>'use strict';//   下面的js 代码就会按照严格模式执行代码</script><script>(function() {'use strict';})();</script>

(2)为函数开启严格模式---把“use strict”;  (或 'use strict'; ) 声明放在函数体所有语句之前

    <!-- 为某个函数开启严格模式 --><script>// 此时只是给fn函数开启严格模式function fn() {'use strict';// 下面的代码按照严格模式执行}function fun() {// 里面的还是按照普通模式执行}</script>

10.3 严格模式 中的变化

(1)变量规定

(2)严格模式下this指向问题

(3)函数变化

更多严格模式要求参考:https://developer.mozilla.org/zhCN/docs/Web/JavaScript/Reference/Strict_mode

    <script>'use strict';// 1. 我们的变量名必须先声明再使用// num = 10;// console.log(num);var num = 10;console.log(num);// 2.我们不能随意删除已经声明好的变量// delete num;// 3. 严格模式下全局作用域中函数中的 this 是 undefined。// function fn() {//     console.log(this); // undefined。// }// fn();// 4. 严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.// function Star() {//     this.sex = '男';// }// // Star();// console.log(ldh.sex);//报错// var ldh = new Star();// console.log(ldh.sex);//正确// 5. 定时器 this 还是指向 window // setTimeout(function() {//     console.log(this);// }, 2000);// a = 1;// a = 2;// 6. 严格模式下函数里面的参数不允许有重名// function fn(a, a) {//     console.log(a + a);// };// fn(1, 2);function fn() {}</script>

十一、高阶函数

高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出

<body><div></div><script>// 高阶函数- 函数可以作为参数传递function fn(a, b, callback) {console.log(a + b);//等上面的执行完 在执行最后回调函数callback && callback();}fn(1, 2, function() {console.log('我是最后调用的');});$("div").animate({left: 500}, function() {$("div").css("backgroundColor", "purple");})</script>
</body>

十二、闭包

12.1 变量作用域

12.2 什么是闭包(被访问的函数才是闭包函数)

闭包(closure)指有权访问另一个函数作用域中变量的函数  -----  JavaScript 高级程序设计

简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量。

    <script>// 闭包(closure)指有权访问另一个函数作用域中变量的函数。// 被访问的函数才是闭包函数// 闭包: 我们fun 这个函数作用域 访问了另外一个函数 fn 里面的局部变量 numfunction fn() {var num = 10;function fun() {console.log(num);//10}fun();}fn();</script>

12.3 在 chrome 中调试闭包

12.4 闭包的作用--延伸了变量的作用范围【使用return】

    <script>// 闭包(closure)指有权访问另一个函数作用域中变量的函数。// 一个作用域可以访问另外一个函数的局部变量 // 我们fn 外面的作用域可以访问fn 内部的局部变量// 闭包的主要作用: 延伸了变量的作用范围function fn() {var num = 10;// function fun() {//     console.log(num);// }// return fun;return function() {console.log(num);}}var f = fn();//f实质是一个函数f();// 类似于// var f = function() {//         console.log(num);//     }// var f =  function fun() {//         console.log(num);//     }</script>

12.5 闭包案例

1. 循环注册点击事件。

<body><ul class="nav"><li>榴莲</li><li>臭豆腐</li><li>鲱鱼罐头</li><li>大猪蹄子</li></ul><script>// 闭包应用-点击li输出当前li的索引号// 1. 我们可以利用动态添加属性的方式var lis = document.querySelector('.nav').querySelectorAll('li');//如果是这样 全部输出都是4// for(var i=0;i<lis.length;i++){//     lis[i].onclick=function(){//         console.log(i);//     }// }for (var i = 0; i < lis.length; i++) {lis[i].index = i;//动态添加属性lis[i].onclick = function() {// console.log(i);console.log(this.index);}}// 2. 利用闭包的方式得到当前小li 的索引号for (var i = 0; i < lis.length; i++) {//立即执行函数  ()(i)//i是传递参数// 利用for循环创建了4个立即执行函数// 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量(function(i) {// console.log(i);lis[i].onclick = function() {console.log(i);}})(i);}</script>
</body>

2. 循环中的 setTimeout()。

<body><ul class="nav"><li>榴莲</li><li>臭豆腐</li><li>鲱鱼罐头</li><li>大猪蹄子</li></ul><script>// 闭包应用-3秒钟之后,打印所有li元素的内容var lis = document.querySelector('.nav').querySelectorAll('li');for (var i = 0; i < lis.length; i++) {//4次循环生成4个定时器,所以同时打印(function(i) {// setTimeout--是一个异步任务  只有到时间才执行 即使0秒 也是要等同步任务执行完才可以setTimeout(function() {console.log(lis[i].innerHTML);}, 3000)})(i);}</script>
</body>

3. 计算打车价格。

    <script>// 闭包应用-计算打车价格 // 打车起步价13(3公里内),  之后每多一公里增加 5块钱.  用户输入公里数就可以计算打车价格// 如果有拥堵情况,总价格多收取10块钱拥堵费// function fn() {};// fn();var car = (function() {var start = 13; // 起步价  局部变量var total = 0; // 总价  局部变量return {// 正常的总价price: function(n) {if (n <= 3) {total = start;} else {total = start + (n - 3) * 5}return total;},// 拥堵之后的费用yd: function(flag) {return flag ? total + 10 : total;}}})();console.log(car.price(5)); // 23console.log(car.yd(true)); // 33console.log(car.price(1)); // 13console.log(car.yd(false)); // 13</script>

12.6 闭包总结

    <script>// 思考题 1:无闭包产生var name = "The Window";var object = {name: "My Object",getNameFunc: function() {return function() {return this.name;};}};console.log(object.getNameFunc()());//The Windowvar f = object.getNameFunc();// 类似于var f = function() {return this.name;}f();// function(){this}()--此时this指向window// 思考题 2:var name = "The Window";var object = {name: "My Object",getNameFunc: function() {//此时this指向调用这个函数的对象var that = this;return function() {return that.name;};}};console.log(object.getNameFunc()());//My Object//等价于var f=object.getNameFunc();var f=function() {return that.name;};f();</script>

十三、递归

13.1 什么是递归

    <script>// 递归函数 : 函数内部自己调用自己, 这个函数就是递归函数var num = 1;function fn() {console.log('我要打印6句话');if (num == 6) {return; // 递归里面必须加退出条件}num++;fn();}fn();</script>

13.2 利用递归求数学题

【利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..n】

    <script>// 利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..nfunction fn(n) {if (n == 1) {return 1;}return n * fn(n - 1);}console.log(fn(3));console.log(fn(4));// 详细思路 假如用户输入的是3//return  3 * fn(2)//return  3 * (2 * fn(1))//return  3 * (2 * 1)//return  3 * (2)//return  6</script>

【斐波那契数列】

    <script>// 利用递归函数求斐波那契数列(兔子序列)  1、1、2、3、5、8、13、21...// 用户输入一个数字 n 就可以求出 这个数字对应的兔子序列值// 我们只需要知道用户输入的n 的前面两项(n-1 n-2)就可以计算出n 对应的序列值function fb(n) {if (n === 1 || n === 2) {return 1;}return fb(n - 1) + fb(n - 2);}console.log(fb(3));console.log(fb(6));</script>

13.3  利用递归:根据id返回对应的数据对象

    <script>var data = [{id: 1,name: '家电',goods: [{id: 11,gname: '冰箱',goods: [{id: 111,gname: '海尔'}, {id: 112,gname: '美的'}, ]}, {id: 12,gname: '洗衣机'}]}, {id: 2,name: '服饰'}];// 我们想要做输入id号,就可以返回的数据对象// 1. 利用 forEach 去遍历里面的每一个对象function getID(json, id) {var o = {};json.forEach(function(item) {// console.log(item); // 2个数组元素if (item.id == id) {// console.log(item);o = item;// 2. 我们想要得里层的数据 11 12 可以利用递归函数// 里面应该有goods这个数组并且数组的长度不为 0 } else if (item.goods && item.goods.length > 0) {o = getID(item.goods, id);}});return o;}console.log(getID(data, 1));console.log(getID(data, 2));console.log(getID(data, 11));console.log(getID(data, 12));console.log(getID(data, 111));</script>

13.4 浅拷贝(只拷贝地址【所以一个修改,改变两个】

    <script>// 浅拷贝只是拷贝一层, 更深层次对象级别的只拷贝引用.// 深拷贝拷贝多层, 每一级别的数据都会拷贝.var obj = {id: 1,name: 'andy',msg: {age: 18}};var o = {};for (var k in obj) {// k 是属性名   obj[k] 属性值o[k] = obj[k];}console.log(o);o.msg.age = 20;console.log(obj);console.log('-----ES6------');Object.assign(o, obj);//把obj拷贝给oconsole.log(o);o.msg.age = 20;console.log(obj);</script>

13.5 和深拷贝(拷贝数据【所以一个修改,另一个不影响】

    <script>// 深拷贝拷贝多层, 每一级别的数据都会拷贝.var obj = {id: 1,name: 'andy',msg: {age: 18},color: ['pink', 'red']};var o = {};// 封装函数 function deepCopy(newobj, oldobj) {for (var k in oldobj) {// 判断我们的属性值属于那种数据类型// 1. 获取属性值  oldobj[k]var item = oldobj[k];// 2. 判断这个值是否是数组if (item instanceof Array) {newobj[k] = [];deepCopy(newobj[k], item)} else if (item instanceof Object) {// 3. 判断这个值是否是对象newobj[k] = {};deepCopy(newobj[k], item)} else {// 4. 属于简单数据类型--直接赋值就可以newobj[k] = item;}}}deepCopy(o, obj);console.log(o);//重点:要先判断是否为数组 在判断是否为对象  因为数组是对象的一部分var arr = [];console.log(arr instanceof Object);//trueo.msg.age = 20;console.log(obj);//18   不变</script>

十四、正则表达式

1.正则表达式概述

1.1 什么是正则表达式

1.2 正则表达式的特点

1. 灵活性、逻辑性和功能性非常的强。

2. 可以迅速地用极简单的方式达到字符串的复杂控制。

3. 对于刚接触的人来说,比较晦涩难懂。比如: ^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

4. 实际开发,一般都是直接复制写好的正则表达式. 但是要求会使用正则表达式并且根据实际情况修改正则表达式.   比如用户名:    /^[a-z0-9_-]{3,16}$/

2.正则表达式在JavaScript中的使用

2.1 创建正则表达式

(1)通过调用 RegExp 对象的构造函数创建

   var 变量名 = new RegExp(/表达式/)

(2)通过字面量创建

var 变量名 = /表达式/;
// 注释中间放表达式就是正则字面量

2.2 测试正则表达式test

    <script>// 正则表达式在js中的使用// 1. 利用 RegExp对象来创建 正则表达式var regexp = new RegExp(/123/);console.log(regexp);// 2. 利用字面量创建 /正则表达式/var rg = /123/;// 3.test 方法用来检测字符串是否符合正则表达式要求的规范console.log(rg.test(123));//trueconsole.log(rg.test('abc'));//true</script>

3.正则表达式中的特殊字符

3.1 正则表达式的组成

一个正则表达式可以由简单的字符构成,比如 /abc/,也可以是简单和特殊字符的组合,比如 /ab*c/ 。其中特殊字符也被称为元字符,在正则表达式中是具有特殊意义的专用符号,如 ^ 、$ 、+ 等。

特殊字符非常多,可以参考:

lMDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions
ljQuery 手册:正则表达式部分
l正则测试工具: 在线正则表达式测试

3.2 边界符--如果 ^ 和 $ 在一起,表示必须是精确匹配

    <script>// 边界符 ^ $ var rg = /abc/; // 正则表达式里面不需要加引号 不管是数字型还是字符串型// /abc/ 只要包含有abc(必须连在一起)这个字符串返回的都是trueconsole.log(rg.test('abc'));//trueconsole.log(rg.test('abcd'));//trueconsole.log(rg.test('aabcd'));//trueconsole.log('---------------------------');var reg = /^abc/;console.log(reg.test('abc')); // trueconsole.log(reg.test('abcd')); // trueconsole.log(reg.test('aabcd')); // falseconsole.log('---------------------------');var reg1 = /^abc$/; // 精确匹配 要求必须是 abc字符串才符合规范console.log(reg1.test('abc')); // trueconsole.log(reg1.test('abcd')); // falseconsole.log(reg1.test('aabcd')); // falseconsole.log(reg1.test('abcabc')); // falseconsole.log('---------------------------');var reg2 = /^aaaabc$/; // 精确匹配 要求必须是 abc字符串才符合规范console.log(reg1.test('aaaabc')); // falseconsole.log(reg1.test('abcd')); // falseconsole.log(reg1.test('aabcd')); // falseconsole.log(reg1.test('abcabc')); // false</script>

3.3 字符类

字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内

        (1)[]方括号

        (2)[-]方括号内部范围符

      (3)[^]方括号内部 取反符^

        (4)字符组合

    <script>//var rg = /abc/;  只要包含abc就可以(必须连载一起) // 字符类: [] 表示有一系列字符可供选择,只要匹配其中一个就可以了var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为trueconsole.log(rg.test('andy'));//trueconsole.log(rg.test('baby'));//trueconsole.log(rg.test('color'));//trueconsole.log(rg.test('red'));//falsevar rg1 = /^[abc]$/; // 三选一 只有是a 或者是 b  或者是c 这三个字母才返回 trueconsole.log(rg1.test('aa'));//falseconsole.log(rg1.test('a'));//trueconsole.log(rg1.test('b'));//trueconsole.log(rg1.test('c'));//trueconsole.log(rg1.test('abc'));//falseconsole.log('------------------');var reg = /^[a-z]$/; // 26个英文字母任何一个字母返回 true  - 表示的是a 到z 的范围  console.log(reg.test('a'));//trueconsole.log(reg.test('z'));//trueconsole.log(reg.test(1));//falseconsole.log(reg.test('A'));//false// 字符组合/[A-z]var reg1 = /^[a-zA-Z0-9_-]$/; // 26个英文字母(大写和小写都可以)任何一个字母返回 true  console.log(reg1.test('a'));console.log(reg1.test('B'));console.log(reg1.test(8));console.log(reg1.test('-'));console.log(reg1.test('_'));console.log(reg1.test('!'));console.log('----------------');// 如果中括号里面有^ 表示取反的意思 千万和 我们边界符 ^ 别混淆var reg2 = /^[^a-zA-Z0-9_-]$/;console.log(reg2.test('a'));console.log(reg2.test('B'));console.log(reg2.test(8));console.log(reg2.test('-'));console.log(reg2.test('_'));console.log(reg2.test('!'));</script>

3.4 量词符

    <script>// 量词符: 用来设定某个模式出现的次数// 简单理解: 就是让下面的a这个字符重复多少次// var reg = /^a$/;//  * 相当于 >= 0 可以出现0次或者很多次  *在输入的是其他字符的情况下返回false var reg = /^a*$/;console.log(reg.test(''));//trueconsole.log(reg.test('a'));//trueconsole.log(reg.test('aaaa'));//true//  + 相当于 >= 1 可以出现1次或者很多次var reg = /^a+$/;console.log(reg.test('')); // falseconsole.log(reg.test('a')); // trueconsole.log(reg.test('aaaa')); // true//  ?  相当于 1 || 0var reg = /^a?$/;console.log(reg.test('')); // trueconsole.log(reg.test('a')); // trueconsole.log(reg.test('aaaa')); // false//  {3 } 就是重复3次var reg = /^a{3}$/;console.log(reg.test('')); // falseconsole.log(reg.test('a')); // falseconsole.log(reg.test('aaaa')); // falseconsole.log(reg.test('aaa')); // true// var reg = /^abc{3}$/; // 它只是让c重复三次   abccc//  {3, }  大于等于3var reg = /^a{3,}$/;console.log(reg.test('')); // falseconsole.log(reg.test('a')); // falseconsole.log(reg.test('aaaa')); // trueconsole.log(reg.test('aaa')); // true//  {3,16}  大于等于3 并且 小于等于16var reg = /^a{3,6}$/;console.log(reg.test('')); // falseconsole.log(reg.test('a')); // falseconsole.log(reg.test('aaaa')); // trueconsole.log(reg.test('aaa')); // trueconsole.log(reg.test('aaaaaaa')); // false</script>
//  量词是设定某个模式出现的次数var reg = /^[a-zA-Z0-9_-]{6,16}$/; // 这个模式用户只能输入英文字母 数字 下划线 短横线但是有边界符和[] 这就限定了只能多选1// {6,16}  中间不要有空格console.log(reg.test('a'));//trueconsole.log(reg.test('8'));//trueconsole.log(reg.test('18'));//falseconsole.log(reg.test('aa'));//falseconsole.log('-------------');var reg1 = /^[a-zA-Z0-9_-]{6,16}$/; console.log(reg1.test('andy-red'));//trueconsole.log(reg1.test('andy_red'));//trueconsole.log(reg1.test('andy007'));//trueconsole.log(reg1.test('andy!007'));//false

案例:用户名验证】

<body><input type="text" class="uname"> <span>请输入用户名</span><script>//  量词是设定某个模式出现的次数var reg = /^[a-zA-Z0-9_-]{6,16}$/; // 这个模式用户只能输入英文字母 数字 下划线 短横线但是有边界符和[] 这就限定了只能多选1var uname = document.querySelector('.uname');var span = document.querySelector('span');uname.onblur = function() {if (reg.test(this.value)) {console.log('正确的');span.className = 'right';span.innerHTML = '用户名格式输入正确';} else {console.log('错误的');span.className = 'wrong';span.innerHTML = '用户名格式输入不正确';}}</script>
</body>

3.4 括号总结

可以在线测试: 菜鸟工具 - 不止于工具

    <script>// 中括号 字符集合.匹配方括号中的任意字符. var reg = /^[abc]$/;// a 也可以 b 也可以 c 可以  a ||b || c// 大括号  量词符. 里面表示重复次数var reg1 = /^abc{3}$/; // 它只是让c重复三次   abcccconsole.log(reg1.test('abc'));//falseconsole.log(reg1.test('abcabcabc'));//falseconsole.log(reg1.test('abccc'));//true// 小括号 表示优先级var reg2 = /^(abc){3}$/; // 它是让abcc重复三次console.log(reg2.test('abc'));//falseconsole.log(reg2.test('abcabcabc'));//trueconsole.log(reg2.test('abccc'));//false</script>

3.5 预定义类

【座机号码验证】

    <script>// 座机号码验证:  全国座机号码  两种格式:   010-12345678  或者  0530-1234567// 正则里面的或者 符号  |  // var reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;var reg = /^\d{3,4}-\d{7,8}$/;</script>

【 案例:表单验证】

【手机号验证】

window.onload=function(){//表示只能匹配1开头的11位号码var regtel=/^1[3|4|5|7|8]\d{9}$/;//手机号的正则表达式var tel=document.querySelector('#tel');//获取表单//当表单失去焦点的时候tel.onblur=function(){if(regtel.test(this.value)){// console.log('正确的');this.nextElementSibling.className='success';this.nextElementSibling.innerHTML='<i class="success_icon"></i>您输入正确';}else{// console.log('错误的');this.nextElementSibling.className='error';this.nextElementSibling.innerHTML='<i class="error_icon"></i>您输入错误';}}
}
window.onload = function() {var regtel = /^1[3|4|5|7|8]\d{9}$/; // 手机号码的正则表达式var regqq = /^[1-9]\d{4,}$/; // 10000var regnc = /^[\u4e00-\u9fa5]{2,8}$/;var regmsg = /^\d{6}$/;var regpwd = /^[a-zA-Z0-9_-]{6,16}$/;var tel = document.querySelector('#tel');var qq = document.querySelector('#qq');var nc = document.querySelector('#nc');var msg = document.querySelector('#msg');var pwd = document.querySelector('#pwd');var surepwd = document.querySelector('#surepwd');regexp(tel, regtel); // 手机号码regexp(qq, regqq); // qq号码regexp(nc, regnc); // 昵称regexp(msg, regmsg); // 短信验证regexp(pwd, regpwd); // 密码框// 表单验证的函数function regexp(ele, reg) {ele.onblur = function() {if (reg.test(this.value)) {// console.log('正确的');this.nextElementSibling.className = 'success';this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您输入正确';} else {// console.log('不正确');this.nextElementSibling.className = 'error';this.nextElementSibling.innerHTML = '<i class="error_icon"></i> 格式不正确,请从新输入 ';}}};surepwd.onblur = function() {if (this.value == pwd.value) {this.nextElementSibling.className = 'success';this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您输入正确';} else {this.nextElementSibling.className = 'error';this.nextElementSibling.innerHTML = '<i class="error_icon"></i> 两次密码输入不一致';}}}

4.正则表达式中的替换

4.1 replace替换(被替换的字符串,替换为的字符串)

        // 替换 replacevar str = 'andy和red';// var newStr = str.replace('andy', 'baby');var newStr = str.replace(/andy/, 'baby');console.log(newStr);

4.2 正则表达式参数

案例:敏感词过滤】

<body><textarea name="" id="message"></textarea> <button>提交</button><div></div><script>// // 替换 replace// var str = 'andy和red';// // var newStr = str.replace('andy', 'baby');// var newStr = str.replace(/andy/, 'baby');// console.log(newStr);var text = document.querySelector('textarea');var btn = document.querySelector('button');var div = document.querySelector('div');btn.onclick = function() {div.innerHTML = text.value.replace(/激情|gay/g, '**');}</script>
</body>

JavaScript进阶【更新中】相关推荐

  1. tensorflow进阶(更新中...)

    文章目录 1. ConfigProto&GPU 2.embedding_lookup() 3.tf.nn.dropout 4.tf.tile() 5. tf.reshape() 6.tf.nn ...

  2. JavaScript 个人总结(持续更新中)

    目录 文章目录 前言 一.javaScript是什么? 二.js引入方式 1.行内式 2.内嵌式 3.外链式 三.js的输出方式 四.js数据类型 1.基本数据类型: 1.数据类型的转换: 2.运算符 ...

  3. 精通JavaScript(重点内容笔记)更新中...

    本书作者是jQuery之父John Resig的经典之作,是深入学习JavaScript技术的绝佳教材,涵盖了可重用代码.文档对象模型.Ajax.Web生产工具.AngularJs登内容.作者讲解了J ...

  4. Go语言开发学习笔记(持续更新中)

    Go语言开发学习笔记(持续更新中) 仅供自我学习 更好的文档请选择下方 https://studygolang.com/pkgdoc https://www.topgoer.com/go%E5%9F% ...

  5. JavaScript—进阶篇

    JavaScript-进阶(笔记) 第1章 系好安全带,准备启航 1-1 让你认识JS 第二章 你要懂的规则(JS基础语法) 2-1 什么是变量 2-2 给变量取个名字(变量命名) 2-3 确定你的存 ...

  6. javascript 进阶篇(集合)

    目录 第一章 系好安全带,准备启航 1-1 让你认识JS 任务 1-2 编程练习 任务 第二章 你要懂的规则(JS基础语法) 2-1 什么是变量 2-3 确定你的存在(变量声明) 任务 2-4 多样化 ...

  7. JavaScript 进阶篇的学习~

    ---恢复内容开始--- 让你认识JS 你知道吗,Web前端开发师需要掌握什么技术?也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HTML+CSS创建一个漂亮的页面, ...

  8. Web前端技术 Web学习资料 Web学习路线 Web入门宝典(不断更新中)

    (此文档于2019年3月停止再更新,后续更新移步至:https://github.com/liuyuqin1991/polaris) 学习路线 第一章 技术(核心单独列章节) 1.Node Node. ...

  9. JavaScript 进阶知识 - Ajax篇

    Ajax 前言 前面我们已经学习了js基础知识和一些简单的特效,基本上已经能够写出一个带有特效的静态页面了,为什么还要称之为静态页面呢?因为网页里的数据都是写死的,真正的工作中,我们是要通过Ajax技 ...

  10. JavaScript进阶必会的手写功能(二)

    JavaScript进阶必会的手写功能(一) 6. 手写浅拷贝 6.1 JavaScript数据类型分类 1. 简单数据类型: Number. String.Boolean.null.undefine ...

最新文章

  1. Nginx 403 Forbidden 排错记录汇总
  2. 2.05亿美元!马斯克Neuralink获脑机接口领域史上最大融资,公司正急招软件工程师...
  3. ZPhotoEngine超级算法库
  4. Linux下同步工具inotify+rsync使用详解
  5. mySQL教程 第5章 插入 更新与删除数据
  6. while循环打印*菱形
  7. inline内联函数的优缺点
  8. Python eval 函数 -Python零基础入门教程
  9. java模仿qq好友面板的布局(BoxLayout问题)
  10. 【Pytorch】tensorboardX==》数据可视化
  11. 从零学ELK系列(三):Centos安装Docker(超详细图文教程)
  12. 英特尔:5G将释放云的潜力,为垂直行业带来巨大商机
  13. input:hidden的作用
  14. bitnami redmine mysql_linux下bitnami一键安装redmine后无法远程访问mysql的问题
  15. 2006 年100 款最佳安全工具谱
  16. FISCO BCOS (六)———ubantu安装mysql5.7
  17. Oracle 19c 新特性:ANY_VALUE 函数和 LISTAGG 的增强
  18. 跟着老万学linux运维-vi编辑器中的大小写转换技巧
  19. 微信热搜榜、订阅热词API
  20. 获取textarea标签中的换行符和空格

热门文章

  1. 面试专题--linux面试题
  2. 关于策略组编辑器无法打开
  3. 最新伤感生活日志:十七岁、那么疼
  4. 在ubuntu16.04上使用源码安装caffe2
  5. java编程逻辑符号,太香了
  6. 实例变量与成员变量的区别
  7. 拼多多竞业协议亮相,太狠了!拼多多员工离职后居然被全互联网封杀!
  8. Android Studio自定义activity模板
  9. 2018最新Koa2实现微信公众号前后端开发视频教程
  10. python备份目录下文件夹_python实现备份目录的方法