JavaScript-JS高级
1、创建类和对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// (1)通过class关键字创建类,类名首字母大写
// (2)类里面有个constructor函数,可以接受传递进来的参数,同时返回实例对象
// (3)constructor函数只要new生成实例时,就会自动调用这个函数,不写这个函数,类也会自动生这个函数
// (4)生成实例new不能省略
// (5)注意语法规范,创建类 类名后面不能加小括号,生成实例 类名后面加小括号,构造函数不需要加function
// 1、创建类class 创建一个明星类
class Star{
constructor(uname,age) {
this.uname = uname;
this.age = age;
}
}
// 2、利用类创建对象new
let ldh = new Star('刘德华',18);
let zxy = new Star('张学友',20);
console.log(ldh);
console.log(zxy);
</script>
</body>
</html>
2、类中添加方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
class Star{
constructor(uname,age) {
this.uname = uname;
this.age = age;
}
sing(song){
console.log(this.uname + song);
}
}
let ldh = new Star('刘德华',18);
let zxy = new Star('张学友',20);
// 类里面的函数不需要写function
// 多个函数方法之间不需要添加逗号分隔
ldh.sing("冰雨");
zxy.sing("李香兰");
</script>
</body>
</html>
3、super关键字
4、构造函数原型prototype
5、对象原型_ proto _
6、constructor构造函数
7、原型链
8、扩展内置对象方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
Array.prototype.sum = function(){
let sum = 0;
for (let i = 0;i < this.length;i++){
sum += this[i];
}
return sum;
}
let arr = [1,2,4,6,20,35];
console.log(arr.sum());
</script>
</body>
</html>
9、call()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
function f() {
console.log("原始调用");
console.log(this);
}
function fn() {
console.log("call方法")
console.log("我是刘德华");
console.log(this);
}
let ldh = {
name:'刘德华'
}
// 1、call() 可以调用函数
// fn.call()
// 2、call() 可以改变这个函数的this指向
f();
fn.call(ldh,408,903);
</script>
</body>
</html>
10、借用父构造函数继承属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// 1、父构造函数
function Father(uname,age) {
this.uname = uname;
this.age = age;
}
// 2、子构造函数
function Son(uname,age,scroce) {
Father.call(this,uname,age,scroce);
this.scroce = scroce;
}
let son = new Son('刘德华',18,100);
console.log(son);
</script>
</body>
</html>
11、类的本质
12、迭代(遍历)数组forEach方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// forEach 迭代(遍历)数组
let arr = [1,28,3];
let sum = 0;
arr.forEach(function (value, index, array) {
console.log('索引号:'+index+' 的值为:'+value);
console.log("数组本身为:",array);
sum += value;
})
console.log("该数组的和为:",sum);
</script>
</body>
</html>
13、筛选数组filter方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// filter 筛选数组,筛选出数组中偶数的值
let arr = [11,22,33,44,55,66,88,99,77];
let newArr = arr.filter(function (value,index) {
return value % 2 === 0;
})
console.log(newArr);
</script>
</body>
</html>
//结果:[22,44,66,88]
14、some方法(一真即真)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
let arr = ['pink','yellow','xiaoebaba','red'];
let flag = arr.some(function (value) {
return value === "xiaoebaba";
})
console.log(flag);
</script>
</body>
</html>
//结果:true
15、every方法(一假即假)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
let arr = ['pink','yellow','xiaoebaba','red'];
let flag = arr.every(function (value) {
return value === "xiaoebaba";
})
console.log(flag);
</script>
</body>
</html>
//结果:false
16、利用数组新增方法操作数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
table {
width: 400px;
border: 1px solid #000;
border-collapse: collapse;
margin: 0 auto;
}
td,
th {
border: 1px solid #000;
text-align: center;
}
input {
width: 50px;
}
.search {
width: 600px;
margin: 20px auto;
}
</style>
</head>
<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、获取相应元素
let tbody = document.querySelector('tbody');
let search_price = document.querySelector('.search-price');
let start = document.querySelector('.start');
let end = document.querySelector('.end');
let search_pro = document.querySelector('.search-pro');
let product = document.querySelector('.product');
// 2、把数据渲染到页面
setData(data);
function setData(myData){
tbody.innerHTML = '';
myData.forEach(function (value) {
let 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 () {
let newData = data.filter(function (value) {
return value.price >= start.value && value.price <= end.value;
});
setData(newData);
})
// 4、根据商品名筛选渲染到页面
search_pro.addEventListener('click',function () {
let arr = [];
data.some(function (value) {
if (value.pname === product.value){
arr.push(value);
return true;
}
})
setData(arr);
})
</script>
</body>
</html>
17、forEach、some和filter的区别
(1)如果查询数组中唯一的元素,用some方法更合适
(2)some遇到return true会终止遍历,迭代效率更高
18、trim方法(字符串)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text"><button>确定</button>
<div></div>
<script>
// 利用trim方法去掉两侧空格
let ipt = document.querySelector('input');
let btn = document.querySelector('button');
let div = document.querySelector('div');
btn.addEventListener('click',function () {
let str = ipt.value.trim();
if (str === ''){
alert('请输入内容!');
}else {
div.innerHTML = str;
}
})
</script>
</body>
</html>
19、Object.defineProperty()方法(对象)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
let obj ={
id:1,
phone:1234567890
};
Object.defineProperty(obj,'address',{
value:'广东省广州市',// value设置默认的值,默认为undefined
writable:false, // writable设置是否可以重写,默认为false,不允许重写
enumerable:true, // enumerable设置是否可以被枚举,默认为false,不允许被枚举
configurable:false // configurable设置是否可以被删除或者是否可以再次修改特性,默认为false
})
console.log(obj);
</script>
</body>
</html>
20、函数的定义方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<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);
</script>
</body>
</html>
21、函数的调用方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<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>
</body>
</html>
22、函数内的this指向
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button>点击</button>
<script>
// 函数的不同调用方式决定了this 的指向不同
// 1. 普通函数 this 指向window
function fn() {
console.log('普通函数的this' + this);
}
window.fn();
// 2. 对象的方法 this指向的是对象 o
var o = {
sayHi: function() {
console.log('对象方法的this:' + this);
}
}
o.sayHi();
// 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 指向的也是window
window.setTimeout(function() {
console.log('定时器的this:' + this);
}, 1000);
// 6. 立即执行函数 this还是指向window
(function() {
console.log('立即执行函数的this' + this);
})();
</script>
</body>
</html>
23、apply方法(函数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<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, ['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);
var max = Math.max.apply(Math, arr);
var min = Math.min.apply(Math, arr);
console.log(max, min);
</script>
</body>
</html>
24、bind方法(函数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
// 改变函数内this指向 js提供了三种方法 call() apply() bind()
// 3. bind() 绑定 捆绑的意思
var o = {
name: 'andy'
};
function fn(a, b) {
console.log(this);
console.log(a + b);
};
var f = fn.bind(o, 1, 2);
f();
// 1. 不会调用原来的函数 可以改变原来函数内部的this 指向
// 2. 返回的是原函数改变this之后产生的新函数
// 3. 如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind
</script>
</body>
</html>
25、bind方法的应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button>点击</button>
<button>点击</button>
<button>点击</button>
<script>
// 1. 不会调用原来的函数 可以改变原来函数内部的this 指向
// 2. 返回的是原函数改变this之后产生的新函数
// 3. 如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind
// 4. 我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮
// 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 指向的是btn 这个对象
// }
var btns = document.querySelectorAll('button');
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
this.disabled = true;
setTimeout(function() {
this.disabled = false;
}.bind(this), 2000);
}
}
</script>
</body>
</html>
26、call、apply、bind的异同
27、闭包的应用-点击li输出索引号
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
<li>我是第一个</li>
<li>我是第二个</li>
<li>我是第三个</li>
<li>我是第四个</li>
<li>我是第五个</li>
</ul>
<script>
let lis = document.querySelector('ul').querySelectorAll('li');
// 传统方法
// for (let i = 0; i < lis.length; i++){
// lis[i].index = i;
// lis[i].addEventListener('click',function () {
// console.log(this.index);
// })
// }
// 利用闭包(立即函数)
for (let i = 0;i < lis.length;i++){
(function (i) {
lis[i].addEventListener('click',function () {
console.log(i);
})
})(i)
}
</script>
</body>
</html>
28、闭包的应用-定时器中的闭包
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<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++) {
(function(i) {
setTimeout(function() {
console.log(lis[i].innerHTML);
}, 3000)
})(i);
}
</script>
</body>
</html>
29、浅拷贝
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<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('--------------');
Object.assign(o, obj);
console.log(o);
o.msg.age = 20;
console.log(obj);
</script>
</body>
</html>
30、深拷贝
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<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);
o.msg.age = 20;
console.log(obj);
</script>
</body>
</html>
31、正则表达式
元字符
代表特殊含义的元字符
\d : 0-9之间的任意一个数字 \d只占一个位置
\w : 数字,字母 ,下划线 0-9 a-z A-Z _
\s : 空格或者空白等
\D : 除了\d
\W : 除了\w
\S : 除了\s
. : 除了\n之外的任意一个字符
\ : 转义字符
| : 或者
() : 分组
\n : 匹配换行符
\b : 匹配边界 字符串的开头和结尾 空格的两边都是边界 => 不占用字符串位数
^ : 限定开始位置 => 本身不占位置
$ : 限定结束位置 => 本身不占位置
[a-z] : 任意字母 []中的表示任意一个都可以
[^a-z] : 非字母 []中^代表除了
[abc] : abc三个字母中的任何一个 [^abc]除了这三个字母中的任何一个字符
代表次数的量词元字符
* : 0到多个
+ : 1到多个
? : 0次或1次 可有可无
{n} : 正好n次;
{n,} : n到多次
{n,m} : n次到m次
32、验证用户名是否输入正确
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
span {
color: #aaa;
font-size: 14px;
}
.right {
color: green;
}
.wrong {
color: red;
}
</style>
</head>
<body>
<input type="text" class="uname"> <span>请输入用户名</span>
<script>
let ipt = document.querySelector('.uname');
let span = document.querySelector('span');
let reg = /^[a-zA-Z0-9-_]{6,16}$/;
ipt.addEventListener('blur',function(){
if(reg.test(this.value)){
span.className = 'right';
span.innerHTML = '用户名输入格式正确!';
}else{
span.className = 'wrong';
span.innerHTML = '用户名输入格式错误!!';
}
})
</script>
</body>
</html>
33、正则表达式中的替换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
textarea {
width: 300px;
height: 100px;
border: 1px solid #ccc;
}
</style>
</head>
<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);
// /表达式/[switch] switch也称为修饰符,按照什么模式来匹配,有三种值:
// g:全局匹配
// i:忽略大小写
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>
</html>