ES6的类和对象

ES6 类

  1. 创建类 class Star { constructor(uname){ this.uname = uname} }
  2. 利用类创建对象 var ldh = new Star('')
  3. constructor 函数只要new生成实例时,就会调用这个函数
  4. 类里面的所有函数不需要写function(),多个函数方法之间不需要添加

类的继承

  1. 语法 class father{ } class son extends father{}
  2. 继承父类的一些属性和方法
  3. super()关键字调用父类的构造函数

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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(x,y);
}
}
var Son = new son(1,2)
Son.sum();

super关键字

  1. 关键字调用父类的构造函数
  2. 关键字可以调用普通函数
  3. 继承属性或者方法查找原则就近原则
  4. 子类构造函数调用父类函数时,super关键词必须写到 字类this之前调用

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
class father{
say(){
return 'didi'
}
}
class son extends father{
say(){
console.log(super.say());
}
}
var oo = new son()
oo.say()

ES6类和对象要注意的问题

  1. 必须先定义类,才能通过类实例化对象
  2. 类里面共有的属性和方法一定要加this使用
  3. 注意this的指向问题,constructor里面的this 指向的时创建的实例化对象,方法种的this指向的调用这个方法的实例化对象 重点

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
class star{
constructor(uname,age){
this.name = uname
this.age = age;
// this.sing() 可以调用函数,但是必须加this
// 如果添加一些事件后在执行要注意 this.sing; 函数后面不加小括号,如果加上小括号表示直接调用
}
sing(){
console.log(this.name);
}
}
var iu = new star('iu')

面向对象案例

  1. 使用es6新特性添加元素 insertAdjacentHTML(position,ele)
  2. e.stopPropagation() // 阻止冒泡事件
  3. 双击禁用选定文字 window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

查看案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
body{
background-color: rgb(180, 175, 175);
}
h4{
margin: 50px auto;
width: 200px;
height: 100px;
font-weight: 600;
line-height: 100px;
text-align: center;
}
li{
list-style: none;
}
.box{
width: 800px;
height: 400px;
border: 2px solid #ccc;
margin: 0 auto;
border-radius: 10px;
box-shadow: 0px -5px 10px #888;
}
#box ul .clickcss{
border-bottom: none;
}
.nav{
width: 100%;
height: 50px;
}
.nav ul {
height: 100%;
float: left;
}
.nav .addTab{
float: right;
}
.nav ul li{
position: relative;
width: 85px;
float: left;
border-bottom: 2px solid #ccc;
border-right: 2px solid #ccc;
height: 100%;
padding-top: 18px;
text-align: center;
}
.nav ul li p{
position: absolute;
right: 0;
top: 2px;
width: 15px;
height: 15px;
border-radius: 4px;
font-size: 12px;
font-weight: 600;
background-color: bisque;
}
.addTab{
height: 100%;
width: 50px;
font-size: 30px;
font-weight: 600;
line-height: 50px;
text-align: center;
border-left: 2px solid #ccc;
border-bottom: 2px solid #ccc;
}
section{
padding: 10px;
}
section p{
display: none;
}
.blockcss{
display: block;
}
span{
width: 100%;
}
span input{
width: 100%;
}
</style>
<body>
<h4>es6 js面向对象的动态</h4>
<div class="box" id="box">
<div class="nav">
<ul>
<li class="clickcss"><span>你好世界</span><p>x</p></li>
<li><span>你好世界</span><p>x</p></li>
<li><span>你好世界</span><p>x</p></li>
</ul>
<div class="addTab">+</div>
</div>
<section>
<p class="blockcss">你好世界a</p>
<p class="">你好世界b</p>
<p class="">你好世界c</p>
</section>

</div>
<script>
window.addEventListener('DOMContentLoaded', function () {
var that;
class Tab{
// 获取元素
constructor(id){
that = this;
this.main = document.querySelector(id);
this.add = this.main.querySelector('.addTab')
this.fitem = this.main.querySelector('section')
this.ul = this.main.querySelector('.nav ul:first-child')
this.init();
}
// 获取所有的li 和 items
updateTAb(){
this.lis = this.main.querySelectorAll('li');
this.remove = this.main.querySelectorAll('ul li p')
this.items = this.main.querySelectorAll('section p');
this.spans = this.main.querySelectorAll('ul li span')
}
init(){
// 初始化
this.updateTAb();
this.add.onclick = this.addTab;
for(var i = 0; i< this.lis.length;i++){
this.lis[i].index = i;
this.lis[i].onclick = this.toggleTab;
this.remove[i].onclick = this.removeTab;
this.spans[i].ondblclick = this.exit;
this.items[i].ondblclick = this.exit;
}
}
// 切换功能
toggleTab(){
// console.log(this.index);
that.clearClass();
this.className = 'clickcss'
that.items[this.index].className = 'blockcss'
}
clearClass(){
for(var i=0;i<this.lis.length;i++){
this.lis[i].className = ''
this.items[i].className = ''
}
}
addTab(){
// 调用之前将之前的样式清除
that.clearClass()
// 创建元素 and 追加元素
var random = Math.random()
// 使用新的函数insertAdjacentHTML(position,ele)
var li = '<li class="clickcss"><span>新标签</span><p>x</p></li>'
var item1 = '<p class="blockcss">你好世界b'+random+'</p>'
// 把元素追加到父元素内孩子的最后面
that.ul.insertAdjacentHTML('beforeend',li)
that.fitem.insertAdjacentHTML('beforeend',item1)
that.init();
}
removeTab(e){
e.stopPropagation() // 阻止冒泡事件
var index = this.parentNode.index
console.log(index);
// this.remove() 可以删除元素
that.lis[index].remove();
that.items[index].remove();
that.init()
// 当页面中有下面这个小li时,返回return,不执行下面的
if(document.querySelector('.clickcss')) return;
index--;
// 自动调用鼠标点击事件
that.lis[index] && that.lis[index].click();
}
exit(){
var str = this.innerHTML;
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
this.innerHTML = '<input type="text">'
var input = this.children[0]
input.value = str;
input.select();
input.onblur = function(){
this.parentNode.innerHTML = this.value
}
input.onkeyup = function(e){
if(e.keyCode === 13){
this.blur();
}
}
}
}
new Tab('#box')
})
</script>
</body>
</html>

构造函数的缺点

  1. 使用构造函数的方法时使用函数的方法 多个对象使用复杂数据类型会浪费内存
  2. 使用新特性prototype只能函数.prototype.方法共享方法,通过原型(对象)分配,公共的方法放到原型对象身上
  3. 静态成员在构造函数本身身上添加成员,函数.属性/方法,静态成员只能通过构造函数来访问
  4. __proto__指向我们构造函数的原型对象,和prototype是等价的,它是非标准属性,一条路线,都存在一个constructor函数

constructor 构造函数

  1. 在使用prototype对象时要注意.= 的区别,如果使用等号时会将原来的constructor覆盖无法指向原来的函数,必须使用constructor函数重新手动指向原来的函数
  2. .是添加一个属性或者方法, =是将原来的constructor覆盖,如果修改了原来的原型对象,给原型对象赋值的是对象必须使用constructor函数重新指向原来的原型对象

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Star(name, age){
this.uname = name;
this.age = age;
}
var dd = new Star('你好')
// Star.prototype.title = '世界'
// console.log(dd.title);
// 使用 = 将函数原来的constructor覆盖,必须使用construtor指向原来的函数
Star.prototype = {
constructor: Star,
title: function(){
console.log('世界');
}
}
console.log(Star.prototype.constructor);
console.log(dd.__proto__.constructor)
// = 和 . 有区别
  1. 记录引用了哪个函数
  2. 只要是对象就有__proto__
  3. object原型对象为null

原型链

  1. js的查找机制根据原型链查找
  2. 并且遵循就近原则

查看实例

1
2
3
4
5
// js查找机制就近原则,按照原型链的方法
dd.sex = 'nv'
Object.prototype.sex = 'bianxingren'
Star.prototype.sex = 'nan'
console.log(dd.sex)

构造函数与实例化对象还有原型对象的关系

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function Star(name, age) {
this.uname = name;
this.age = age;
}
var dd = new Star('ni',18)
// Star.prototype.title = '世界'
// console.log(dd.title);
// 使用 = 将函数原来的prototype覆盖,必须使用construtor指向原来的函数
Star.prototype = {
constructor: Star,
title: function () {
console.log('世界');
}
}
// 指向原型对象
console.log("函数原型对象所使用的函数为:"+Star.prototype.constructor);
// 指向原型对象
console.log("Star函数的原型对象:"+Star.prototype);
console.log(Star);
console.log(dd);
console.log('判断函数的原型对象的与实例化对象指向所用的函数的关系'+Star.prototype.constructor === dd.__proto__.constructor);
// 原型对象指向的是Object的原型
console.log("判断函数原型对象的指向与对象的原型对象的关系:"+(Star.prototype.__proto__ === Object.prototype));
// 指向原型对象
console.log("实例化对象的指向为"+dd.__proto__);
// 指向Object
console.log("函数原型对象的指向使用的函数为:"+Star.prototype.__proto__.constructor);
console.log("Object的指向为:"+Object.__proto__);
// Object原型对象的指向为null
console.log("Object的原型对象的指向为:"+Object.prototype.__proto__);
// = 和 . 有区别

this指向

  1. 在构造函数中里面的this指向的是对象实例
  2. 原型对象函数里面的this指向的是实例对象

扩展内置对象

  1. 数组和字符串内置对象不能给原型对象覆盖操作Array.prototype = {} ,只能是Array.prototype.xxx = function(){}的方式
  2. 可以使用原型对象里面的扩展对象,页可以自定义扩展方法

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
console.log(Array.prototype);
Array.prototype.sum = function(){
// console.log(this.length);
// console.log(this);
var sum = 0;
for(var i= 0;i<this.length;i++){
sum += this[i];
// console.log(this[i]);
}
return sum
}
var arr = new Array(1,2,3,4)
console.log(arr.length);
console.log(arr.sum());

call()

  1. 作用:调用这个函数,可以修改调用函数的this的指向
  2. 格式: 函数.call() 函数不加括号 fn.call()
  3. call(实例化对象) 可以改变函数的this指向,并且不传递

查看实例

1
2
3
4
5
6
7
8
9
function sun(x,y){
console.log(this);
console.log(x+y);
}
sun()
var no = {
name: 'jjj'
}
sun.call(no,1,2)

借用构造函数继承父类属性

查看实例

1
2
3
4
5
6
7
8
9
function Father(uname,age){
this.uname = uname;
this.age = age
}
function Son(uname,age){
Father.call(this,uname,age)
}
var dd = new Son('dd',18)
console.log(dd);

借用构造函数继承父类方法

  1. 在使用对象的形式修改了原型对象时,使用constructor来指向原来的构造函数

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function Father(uname,age){
this.uname =uname
this.age = age
}
function Son(uname,age){
Father.call(this,uname,age)
}
Son.prototype.exam = function(){
console.log(10);
}
// Father.prototype = Son.prototype
// 利用对象的形式修改了原型对象,记得使用constructor来指向原来的构造函数
Son.prototype = new Father()
// 构造函数的原型对象始终都是指向本身
Son.prototype.constructor = Son
Father.prototype.money = function(){
console.log(11);
}
var son =new Son('dd',17)
console.log(son);
console.log(Father.prototype);
console.log(Son.prototype.constructor);

ES5新增方法

  1. 数组方法 map() every()
  • forEach() 遍历方法,有一个回调函数里面有3个参数 value,index,array,分别表示每个元素的值,每个元素的索引号,元素本身
  • 迭代 filter() 筛选的作用 ,返回一个新的数组 return 迭代遍历
  • some() 查找元素中是否有满足条件的元素, 返回的是布尔值,找到第一个满足条件的元素终止循环
  • every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
  • map() 方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
  1. forEachfilter里面遇到return true 不会终止迭代 ,在some里面遇到return true 停止迭代

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}

table {
border: 1px solid #ccc;
border-bottom: 0;
border-right: 0;
margin: 50px auto;
width: 450px;
}

tbody {
text-align: center;
}

thead {
border-bottom: 1px solid #ccc;
}

td,
th {
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}

h4 {
display: inline-block;
margin-right: 5px;
}

.search {
text-align: center;
margin: 10px auto;
}

input {
width: 40px;
}

input,
button {
outline-style: none;
}

button {
margin-left: 5px;
}
</style>
<div class="search">
<h4>按照价格查询</h4><input class="start" type="text">-<input class="end" type="text"><button
class="search-price">搜索</button>
<h4>按照产品名称查询</h4><input class="chanp" type="text"><button class="search-name">搜索</button>
</div>


<table cellspacing='0'>
<thead>
<tr>
<th>id</th>
<th>产品名称</th>
<th>价格</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
var data = [{
id: 1,
pname: '小米',
price: 999
},
{
id: 2,
pname: '华为',
price: 1933
},
{
id: 3,
pname: 'iPhone',
price: 2999
},
{
id: 4,
pname: 'oppo',
price: 3999
}]
var tbody = document.querySelector('tbody')
// 首先通过遍历数组获取数组中的元素,然后创建新的元素,将获取到的值添加到元素的中
setData(data)
// 封装一个函数使得搜索的时候能重复调用
function setData(mydata) {
tbody.innerHTML = ''
mydata.forEach(function (value) {
var tr = document.createElement('tr')
tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>'
tbody.appendChild(tr)
})
}
// 使用filter()方法 遍历迭代数组,找出满足条件的,返回一个新的数组
var searchPrice = document.querySelector('.search-price')
var start = document.querySelector('.start')
var end = document.querySelector('.end')
searchPrice.addEventListener('click', function () {
var newData = data.filter(function (value) {
return value.price >= start.value && value.price <= end.value
})
console.log(newData);
setData(newData)
})
// // 通过产品的名称搜索 使用filter方法
var chanp = document.querySelector('.chanp')
var searchName = document.querySelector('.search-name')
// searchName.addEventListener('click',function(){
// var newdata1 = data.filter(function(value){
// return value.pname == chanp.value
// })
// setData(newdata1)
// })

// 通过some来遍历 效率更高
searchName = document.addEventListener('click',function(){
var arr = []
data.some(function(value){
if(value.pname == chanp.value){
arr.push(value)
return true;
}
})
setData(arr)
})

</script>
</body>

</html>

字符串方法

trim() 方法 去除字符串的两侧的空格

对象方法

  1. 用于获取对象自身所有的属性 Object.keys(obj)
  2. Object.defineProperty(对象,属性,descriptor 对象的格式{ value: ''})定义对象中的属性或者修改原有的属性
  • descriptor中的属性值:value表示所修改或者新增的值,默认为undefined,writable:false 不允许修改属性值
  • enumerable;表示目标属性是否可以被遍历,默认值为false
  • configurable:表示目标属性是否可以被修改或者删除,或者再次修改新特性 默认为false

函数的定义方法

  1. 命名函数,匿名函数
  2. 利用var fn = new function(‘参数’,’参数‘,’函数体‘)必须以字符串的格式编写
  3. 所有的函数都是Function的实例对象,函数也属于对象

函数的调用方式

  1. 普通函数的调用

    1
    2
    3
    4
    function fn(){
    console.log(11);
    }
    fn(); fn.call()
  2. 对象的方法调用

    1
    2
    3
    4
    5
    6
    var o = {
    fn:function(){
    console.log(11);
    }
    }
    o.fn();
  3. 构造函数的调用方法

    1
    2
    3
    4
    function Fn(){
    console.log(11);
    }
    new Fn();
  4. 绑定事件函数

    1
    2
    3
    obj.onclick = function(){
    console.log(11);
    }
  5. 定时器函数的调用

    1
    2
    3
    setInterval(function(){
    console.log(11)
    },1000)
  6. 立即执行函数

    1
    2
    3
    4
    5
    6
    7
    (function(){
    console.log('立即执行函数'+11);
    })()
    //第二种
    (function(){
    console.log('立即执行函数'+11);
    }())

    改变函数内部的this的指向

  7. call(arr,'','')arr为对象,后面可以传递参数;调用函数;改变函数内的this指向;主要作用可以实现继承

  8. apply(thisarr,[''])方法 也是调用函数可以改变函数内部的this指向,但是传递参数时必须以数组的形式传递(伪数组)

  • 调用数学内置对象 比如:Math.max.apply(Math,arr),arr必须为数组的形式
  1. bind(thisarr,’’,’’)方法 不会调用函数,也能改变指向, 但是返回的是原函数改变this之后产生的函数

查看实例

1
2
3
4
5
6
7
8
// 使用bind方法来改变函数内部的this指向
var btn = document.querySelector('button')
btn.onclick = function(){
this.disabled = 1
setTimeout(function(){
this.disabled = 0
}.bind(this),3000)
}

严格模式

  1. 'use strict';为整个脚本开启严格模式
  2. 可以为某个函数开启严格模式
  3. 不能随意删除已经定义好的变量
  4. 严格模式下的全局变量的this是undefined
  5. 严格模式下调用构造函数必须加new
  6. 函数名不允许有重名的情况
  7. 不允许在非函数里声明函数

高阶函数

  1. 对其他函数进行操作的函数,接受函数作为参数或者将函数作为返回值输出
  2. 函数也是一种数据类型
  3. 回调函数–高阶函数

闭包(Closure)

  1. 函数,有权访问另一个函数作用域中变量的函数,被访问函数变量

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(function(){
'use strict';
function fn(){
var num = 10
// function fun(){
// console.log(num);
// }
// 使用return 高级函数 可以从一个作用域访问另一个函数的局部变量,相当于继承
return function(){
console.log(num);
}
}
// fn.apply() 执行后return 一个函数
console.log(fn.apply());
// 定义函数后在调用,可以实现全局调用
var f = fn()
f();
}())
  1. 主要作用:延伸了变量的作用范围

案例获取元素索引号,打印元素的内容类似

查看案例使用闭包获取元素索引号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 第一种使用动态添加属性来获取某个索引号
var lis = document.querySelectorAll('ul li')
// console.log(lis);
for(var i =0;i<lis.length;i++){
lis[i].index = i
lis[i].onclick =function(){
console.log(this.index);
}
}
// 第二种使用闭包的方法获取某个点击元素的索引号
for(var i = 0;i<lis.length;i++){
(function(i){
lis[i].onclick = function(){
console.log(i);
}
})(i)
}

案例打车价格

查看案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// <!-- 使用闭包来实现 打车的收费,定义起步价;10  超过3公里 按/公里 5 ,如果有拥堵的情况多收10 -->
var car = (function(){
var start = 10
var total = 0
return {
price:function(n){
n<=3 ? total = start : total = start + (n-3)*5
return total
},
yd:function(flag){
return flag ? total+10 :total
}
}
})()
console.log(car.price(parseFloat(prompt('请输入公里数:'))));
console.log(car.yd(1));

闭包思考重点

  1. 匿名函数中的this指向为window,立即执行函数封装功能不污染全局变量
  2. 判断this的指向 这里的this指向的是函数的调用者,对象,使用了局部变量 闭包使用

    查看实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 匿名函数中的this指向为window,立即执行函数封装功能不污染全局变量
    var name = 'the window'
    var obj = {
    name: 'world',
    sun: function(){
    return function(){
    return this.name
    }
    }
    }
    console.log(obj.sun()());
    // 判断this的指向 这里的this指向的是函数的调用者,对象,使用了局部变量 闭包使用
    var uname = 'tt'
    var objs = {
    uname:'kk',
    ff:function(){
    var that = this
    return function(){
    return that.uname;
    }
    }
    }
    // 立即执行函数
    console.log(objs.ff()());

递归函数

  1. 在函数的内部自己调用自己
  2. 递归函数中必须加退出语句

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// var num = 1;
// function fn() {
// console.log(6);
// if (num == 6) {
// return;
// } num++;
// fn();
// }
// fn();
// 使用递归函数求阶乘
function sun(n){
if(n==1){
return 1;
}
return n * sun(n-1)
}
sun(3);
console.log(sun(3));
// 使用递归函数求斐波那契数列(兔子序列)
function fb(n){
if(n==1 || n==2){
return 1;
}
return fb(n-1) +fb(n-2)
}
console.log(fb(6));
// 使用递归查找对象属性值,深度查找
var obj = [{
id: 1,
name: 'd',
foods: [{
id: 11,
name: 'w'
}, {
id: 12,
name: 'u'
}]
},
{
id: 2,
name: 's'
}]
// 开始遍历
function getId(json, id) {
json.forEach(function (item) {
if (item.id == id) {
console.log(item);
} else if (item.foods && item.foods.length != 0) {
getId(item.foods, id)
}
})
}
getId(obj, 1)
getId(obj, 11)
getId(obj, 2)

浅拷贝和深拷贝

  1. assign(目标对象,源对象),浅拷贝
  2. 深拷贝 使用递归函数

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 浅拷贝只拷贝地址,会影响原来的数据,不会新建一个对象
var obj ={
id:1,
name:'s',
msg:{
sex:'nan',
age:18
},
color:['red','green']
}
var o = []
// for (var k in obj){
// o[k] = obj[k]
// }
// console.log(o);
// o.msg.sex = 2
// console.log(o);
// console.log(obj);
// 使用assign方法,类似与浅拷贝
// Object.assign(o,obj)
// o.msg.sex = 17
// console.log(o);
// console.log(obj);


// 深拷贝
function Deepcopy(newobj,oldobj){
for(var k in oldobj){
// 判断属性值属于哪种数据类型
var item = oldobj[k]
// 判断属性值是否为数组,数组也属于对象,注意顺序
if(item instanceof Array){
newobj[k] = []
Deepcopy(newobj[k],item)
}else if(item instanceof Object){
newobj[k] = {}
Deepcopy(newobj[k],item)
}
else{
newobj[k] = item;
}
// 判断属性值是否为对象
// 判断属性值是否为简单数据类型
}
}
Deepcopy(o,obj)
// 深拷贝对源对象无影响
o.msg.sex = '1'
console.log(o);
console.log(obj);

正则表达式

  1. 对象 用于匹配字符串中字符组合的模式
  2. 匹配,替换,提取
  3. 不需要加引号

创建正则表达式

  1. 使用RegExp对象来创建 格式var 变量名 = new RegExp(/ /)
  2. 利用字面量创建 格式 var rg = /123/

测试是否符合规范

  1. test() 正则对象方法 表达式.test(str) 返回true/false

特殊字符

  1. 元字符 ^ + - / * 等等
  2. 边界符 ^ $ 开头或者结尾
  3. 字符类:[] 表示有一系列字符可供选择,匹配一个即可 -表示范围
  4. 如果中括号里面有^表示取反
  5. 量词符 设置模式出现的次数
  6. 量词,中间不要有空格 ,注意如果是 /^abc{3}$/ 表示的是将c重复三次 ,如果加了小括号(abc)按前面的三个重复执行三次

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
var ld = /111/
//(1) /11/ 表示只要字符串中含有这些相连字符,都满足条件
console.log(ld.test(11)); //false
// 开头
var ldd = /^11/
console.log(ldd.test(111)); //true
// 满足结尾条件
var ldd = /11$/
console.log(ldd.test(11)); //true
// 满足指定条件
var ldd = /^11$/
console.log(ldd.test(11)); //true
console.log('我是分割线----------------------');
// (2) 字符类 [] 表示只要有满足条件的即可,无序
var ld1 = /[abc]/
console.log(ld1.test('ansc')); // true
console.log(ld1.test('cse')); // true
// 表示所匹配的字符必须为 a/b/c 才行
var ld2 = /^[abc]$/
console.log(ld2.test('cba')); //false
// a-z 表示 26个英文字母 - 表示范围 ,表示从以下条件中任意一个字符如果满足为true/false 中括号内的^表示的是取反 ^[]$ 表示任意一个字符
var ld3 = /^[^a-zA-Z0-9_-]$/
console.log(ld3.test('zzz')); //false
console.log(ld3.test('=')); //true
console.log('------------------------');
// (3) 量词符 重复次数 * 表示0||n ; + 表示>=0; ? 表示 1||0; {3,} 表示>=3;{4,16} >=4 <=16
var reg = /^a*$/
console.log(reg.test('')); // true
console.log(reg.test('a')); // true
console.log(reg.test('aa'));// true
var reg1 = /^a+$/
console.log(reg1.test('')); // false
console.log(reg1.test('a'));//true
var reg2 = /^a?$/
console.log(reg2.test('')); // true
console.log(reg2.test('a')); // true
console.log(reg2.test('aa')); // false
var reg3 = /^a{4,}$/
console.log(reg3.test('aaaa')); //true
var reg4 = /^a{4,16}$/
console.log(reg4.test('aaaaaaaaa')); //true

表单验证案例

查看案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<style>
.right{
color:#064406
}
.error{
color: #580808;
}
</style>
<input type="text" name="" id=""> <span>请输入6-16位的字符</span>
<script>
var reg = /^[a-zA-Z0-9]{3,16}$/
var input = document.querySelector('input')
var span = document.querySelector('span')
input.onblur = function(){
if(reg.test(this.value)){
console.log('输入正确!!');
span.className = 'right'
span.innerHTML = '您输入的格式正确'
}else{
console.log('输入错误');
span.className = 'error'
span.innerHTML = '您输入的格式有误'
}
}
</script>

预定义类

  1. \d \D 分别匹配所有数字和匹配所有的非数字
  2. \w 匹配任意的字母,数字和下划线,相当于 [^a-zA-Z0-9_] 大写W 表示非数字非字母,非下划线
  3. \ s 匹配空格 大写表示非
  4. 正则里面的或者用符号 | 表示

表单注册案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
<title>Document</title>
</head>

<body>
<style>
body {
background-color: #ccc;
}

* {
padding: 0;
margin: 0;
box-sizing: border-box;
}

input {
width: 170px;
padding: 5px;
border-radius: 5px;
outline: none;
border: 1px solid #888;
margin-left: 10px;
}


.fa-exclamation-circle {
color: #0099ff;
font-size: 12px;
}

.fa-times-circle {
color: red;
font-size: 12px;
}

.fa-check-circle {
color: green;
font-size: 12px;
}

.box {
width: 600px;
height: 300px;
margin: 50px auto;
border: 2px solid #888;
border-radius: 10px;
padding: 10px;
}

.w {
margin: 10px;
}
</style>
<div class="box">
<div class="w">手机号<input type="text" placeholder="请输入手机号码" class="phone">
<i class="fa"></i>
</div>
<div class="w">QQ<input type="text" placeholder="请输入QQ号码" class="qq">
<i class="fa"></i>
</div>
<div class="w">用户名<input type="text" name="" id="" placeholder="请输入密码" value="" class="user">
<i class="fa"></i>
</div>
<div class="w">密码<input type="password" name="" id="" placeholder="请输入密码" value="" class="secret">
<i class="fa"></i>
</div>
<div class="w">确认密码<input type="password" name="" id="" placeholder="请输入密码" value="" class="suresecret">
<i class="fa"></i>
</div>
</div>

<!-- <span class="fa fa-times-circle">fa fa-check-circle密码较短</span></div> -->
<script>
// 第一种不使用正则使用if判断条件
// 知识回顾 兄弟节点 nextSibling属性与nextElementSibling属性的差别:
// nextSibling属性返回元素节点之后的兄弟节点(包括文本节点、注释节点即回车、换行、空格、文本等等);
// nextElementSibling属性只返回元素节点之后的兄弟元素节点(不包括文本节点、注释节点);
var secret = document.querySelector('.secret');
var is = document.querySelectorAll('i');
// 密码的设置 使用普通方法
secret.onfocus = function () {
this.nextElementSibling.className = 'fa fa-exclamation-circle';
this.nextElementSibling.innerHTML = '请输入6-16位字符的密码';
}
secret.onblur = function () {
var inputli = this.nextElementSibling
var inputli = this.nextElementSibling
if (this.value == '') {
inputli.innerHTML = ''
inputli.className = '';
} else if (secret.value.length < 6 || secret.value.length > 16) {
inputli.className = 'fa fa-times-circle';
inputli.nextElementSibling.innerHTML = '您输入的密码不符合要求,请输入6-16位字符'
}
else {
inputli.className = 'fa fa-check-circle';
inputli.innerHTML = '您输入的格式正确!!'
}
}
// 第二种使用正则判断, 首先获取元素,手机号案例
var phone = document.querySelector('.phone')
var pnum = /^1[3|4|5|8|9]\d{9}$/
// 然后是给元素添加事件,获取焦点和失去焦点
phone.onfocus = function () {
this.nextElementSibling.className = 'fa fa-exclamation-circle';
this.nextElementSibling.innerHTML = '请输入1-11位字符的手机号码';
}
phone.onblur = function () {
var inputli = this.nextElementSibling
if (this.value == '') {
inputli.innerHTML = ''
inputli.className = '';
} else if (pnum.test(this.value)) {
inputli.className = 'fa fa-check-circle';
inputli.innerHTML = '您输入的格式正确!!'
} else {
inputli.className = 'fa fa-times-circle';
inputli.innerHTML = '您输入的手机号格式有误,请输入1-11位的手机号码'
}
}
// 第三种 封装一个函数,如果需要判断的表单过多
var qq = document.querySelector('.qq')
var qqreg = /^[1-9]\d{4,9}$/
// 函数格式 input表示所要判断嗯等元素对象,i表示获得焦点时所呈现的条件,reg为每个表单的正则判断,errorend表示失去焦点后如果不满足正则条件所返回的内容 这里还用到了闭包
function Judge(input, i, reg, errorend) {
input.onfocus = function () {
this.nextElementSibling.className = 'fa fa-exclamation-circle';
this.nextElementSibling.innerHTML = i
}
input.onblur = function () {
var inputli = this.nextElementSibling
if (this.value == '') {
inputli.innerHTML = ''
inputli.className = '';
} else if (reg.test(this.value)) {
inputli.className = 'fa fa-check-circle';
inputli.innerHTML = '您输入的格式正确!!'
} else {
inputli.className = 'fa fa-times-circle';
inputli.innerHTML = errorend
}
}
}
var qq = Judge(qq, '请输入5-10位的号码', qqreg, '您输入的格式错误,请输入5-10位的号码')
// 编写昵称的正则表达式,获取元素,格式要求为中文字符
var user = document.querySelector('.user')
var userreg = /^[\u4e00-\u9fa5]{3,5}$/
Judge(user, '请输入3-5位的中文字符', userreg, '你输入的格式有误,请重新输入3-5位的中文字符')
// 获取确认密码
var suresecret = document.querySelector('.suresecret')
suresecret.onfocus = function () {
if (this.value == '') {
this.nextElementSibling.className = ''
this.nextElementSibling.innerHTML = ''
}
}
suresecret.onblur = function () {
var inputli = this.nextElementSibling
if (this.value == secret.value && this.value != '') {
inputli.className = 'fa fa-check-circle';
inputli.innerHTML = '两次密码一致!!'
} else {
inputli.className = 'fa fa-times-circle';
inputli.innerHTML = '两次密码不一致请重新输入!!!'
}
}
</script>
</body>

</html>

正则表达式替换

  1. stringObject.repalce('被替换的字符/正则表达式',' 要替换的字符') 使用repalce来实现字符串的替换
  2. /表达式/[switch] swith参数 也称为i修饰符
  • g 全局匹配 //g
  • i 忽略大小写

ES6声明变量的关键字

ECMAScript 脚本语言

let关键字

  1. let 声明变量
  • 块级作用域 {}
  • 块级作用域 在大括号中使用let关键词才具有块级作用域
  • 防止循环变量变成全局变量
  • 使用let关键字的变量没有变量提升 先声明在提升
  • 使用let关键词声明的变量具有暂时性死区 与所在的{}绑定

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 经典面试题 使用var 定义变量  这里时执行完for循环才会执行函数,所以获取到的数据始终都是全局变量下的数
var arr = []
for(var i = 0;i<2;i++){
arr[i] = function() {
console.log(i);
}
}
arr[0]()
arr[1]()
console.log('----------------------');
// 使用let关键字 使用块级作用域效果
let arr1 = []
for(let i = 0;i<2;i++){
arr1[i] = function(){
console.log(i);
}
}
arr1[0]()
arr1[1]()

const关键字

  1. 声明常量,不能变化的量,变量无法提升
  2. const常量的初始值必须赋值
  3. 常量声明后值不可更改,复杂数据类型中的值可以更改,直接赋值不允许

解构赋值

  1. 允许从数组中按照一一对应的关系提取值,并将值赋给变量
  2. 格式 let [a,b,c] = [1,2,3] 变量与值相对,如果不对应 输出的值为undefined
  3. 对象解构,与数组类似let {},允许使用变量的名字匹配对象的属性

    查看答案

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 第一种获取属性值的方法 对象解构
    let per = {name:'ww',sex:'nan'}
    let {name,sex} = per
    console.log(name);
    console.log(sex);
    // const 对象解构第二种获取属性值的方法/
    let perpon = {name:'mm',age:18}
    let {name:myname,age:ages} = perpon
    console.log(myname);
    console.log(ages);
    // 数组解构
    let re = [1,2,3]
    let [a,c,b] = re
    console.log(b);

箭头函数

  1. 简化函数定义语法 格式: () => {}
  2. 形参只有一个可以省略外侧的小括号
  3. 箭头函数不绑定this关键字
  4. say方法的箭头函数中的this指向的是定义这个方法的,对象是无法产生作用域的,所以这里的say中的this指向的是window,所以返回的值是undefined

    查看答案

    1
    2
    3
    4
    5
    6
    7
    8
    var age = 100
    var obj = {
    name: 'mm',
    age:15,
    say:() =>{
    console.log(this.name);
    }
    }

剩余参数

  1. 将不定量的参数表示一个数组

    查看答案

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 剩余参数 ...args
    const sum = (...args) => {
    // 这里只能使用let,和var 定义变量 不能使用const, 为定值无法改变
    let total = 0;
    // 遍历传入数组的值
    args.forEach(items => total += items)
    return total
    }
    console.log(sum(1,2,3))
    console.log(sum(1,2))

扩展运算符

  1. 可以将数组拆分成以分隔的参数序列 在控制器中为空格分隔符
  2. 可以合并数组
  3. 将伪数组转换为真正的数组 [...ary] ary为获取元素所定义的属性

    合并数组的两种方法

    1
    2
    3
    4
    5
    6
    7
    8
    // 方法一
    let arr = [1, 2, 3]
    let a = [4, 5, 6]
    let c = [...a, ...arr]
    console.log(c);
    // 方法二使用push方法
    arr.push(...a)
    console.log(arr);
  4. array.from() 也可以将伪数组转换为真正的数组

    查看答案

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 使用from的方法将伪数组转换为数组
    let obj = {
    '0':'a',
    '1':'b',
    '2':'c',
    length:3
    }
    console.log(obj);
    console.log(Array.from(obj));

find()和findIndex()方法 includes(),startsWith,endsWith()

  1. 找出第一个符合条件的成员 find((,) => {})
  2. findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引
  3. includes() 判断数组中是否包含某个值 括号内为判断的数组内容 返回值为true或者false
  4. 将某个字符串重复输出n次 repeat(n)

模板字符串

  1. ${变量名}, 注意必须加 ``反引号
  2. 可以调用函数
  3. 模板字符串可以换行

Set数据结构

  1. 类似于数组,成员的值都是唯一的,没有重复的值
  2. 本身是一个构造函数
  3. 可以使用set()方法来实现数组去重
  4. 使用add方法向set()中添加值

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 伪数组
let obj = {
'0': 1,
'1': 2,
'2': 'a',
length: 3
}
console.log(obj);
// 使用Array.from()的方法将伪数组转化为真正的数组
console.log(Array.from(obj));

// 使用find()方法 判断数组中是否存在某个元素并返回满足条件的第一个值,如果没有满足条件的则返回的值为undefined
// let a = [1,2,3]
let a = [{
id: 1,
name: 'm'
},
{
id: 2,
name: 'a'
}]
console.log(a.find(item => item.id == 3));

// 使用findIndex()方法来判断数组或者对象中的值是否存在,如果存在则返回的值为该元素的索引号,不存在则返回-1
console.log(a.findIndex(item => item.id == 3));

// 使用includes() 方法用于判断字符串或者数组是否包含指定的子字符串,返回布尔值
let b = [1, 2, 3]
console.log(b.includes(1))

// 模板字符串 使用格式 `${变量名}` 必须加``反引号 符号,模板字符串可以换行
let name = 'world'
let uname = `hello ${name} wo`
console.log(uname);
console.log('startsWith()'+uname.startsWith('hello'));
console.log('endsWith()'+uname.endsWith('wo'));
console.log(`你好世界 ${name}`);
console.log(uname.repeat(4)) // 使用repeat()方法 将字符串重复n次
// 模板字符串可以调用函数 `$(fn())`

// Set() 方法

const ol = new Set(['a','b','c' ,'a']) // 将重复的值过滤掉
console.log(ol);
console.log(ol.size);
// 利用set()方法 实现数组去重
console.log([...ol]);

// 使用add方法
let n = new Set()
n.add('a').add('b') // 向set结构中添加值
n.delete('a')
console.log([...n]); //将set结构中的值删除
console.log(n.has('a')); // 使用has方法来判断set结构中是否存在某个值
n.clear() // 可以将set结构中的值清除
console.log([...n]);